diff --git a/.codeclimate.yml b/.codeclimate.yml index 7ca619bbc..2851f2f2d 100644 --- a/.codeclimate.yml +++ b/.codeclimate.yml @@ -1,4 +1,4 @@ languages: JavaScript: true exclude_paths: -- "public/js/bootstrap-datepicker.js" + - "public/js/bootstrap-datepicker.js" diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 000000000..2e3898efa --- /dev/null +++ b/.dockerignore @@ -0,0 +1,5 @@ +.git +.github +.vscode +docs +config/app.json diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 000000000..cd4ff6adc --- /dev/null +++ b/.editorconfig @@ -0,0 +1,15 @@ +# EditorConfig is awesome: https://EditorConfig.org + +# top-most EditorConfig file +root = true + +[*] +indent_style = space +indent_size = 2 +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true + +[*.js] +quote_type = single diff --git a/.eslintrc.json b/.eslintrc.json new file mode 100644 index 000000000..6437ca7df --- /dev/null +++ b/.eslintrc.json @@ -0,0 +1,33 @@ +{ + "env": { + "browser": true, + "commonjs": true, + "es2021": true + }, + "extends": [ + "standard", + "prettier", + "plugin:mocha/recommended" + ], + "parserOptions": { + "ecmaVersion": "latest" + }, + "plugins": [ + "mocha" + ], + "rules": { + "camelcase": 0, + "space-before-function-paren": 0, + "arrow-body-style": ["error", "as-needed"], + //"prefer-arrow-callback": [ + // "error", + // { "allowNamedFunctions": true } + //], + "func-style": [ + "error", + "declaration", + { "allowArrowFunctions": true } + ] + + } +} diff --git a/.github/workflows/docker-image.yml b/.github/workflows/docker-image.yml new file mode 100644 index 000000000..76b71bcca --- /dev/null +++ b/.github/workflows/docker-image.yml @@ -0,0 +1,38 @@ +name: Publish Docker image + +on: + push: + branches: + - master + - release/* + release: + types: [published] + +jobs: + push_to_registry: + name: Push Docker image to Docker Hub + runs-on: ubuntu-latest + steps: + - name: Check out the repo + uses: actions/checkout@v4 + + - name: Log in to Docker Hub + uses: docker/login-action@f4ef78c080cd8ba55a85445d5b36e214a81df20a + with: + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_PASSWORD }} + + - name: Extract metadata (tags, labels) for Docker + id: meta + uses: docker/metadata-action@9ec57ed1fcdbf14dcef7dfbe97b2010124a938b7 + with: + images: aliengen/timeoff-management-application + + - name: Build and push Docker image + uses: docker/build-push-action@3b5e8027fcad23fda98b2e3ac259d8d67585f671 + with: + context: . + file: ./Dockerfile + push: true + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} diff --git a/.gitignore b/.gitignore index 1d1d2ef66..24ab17c91 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,5 @@ *.swm node_modules/ *.sqlite +*.DS_Store +t/integration/test.csv diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 000000000..9f8ecd9f0 --- /dev/null +++ b/.prettierrc @@ -0,0 +1,6 @@ +{ + "semi": false, + "singleQuote": true, + "arrowParens": "avoid", + "trailingComma": "none" +} diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 000000000..a2f7461e3 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,25 @@ +{ + "editor.formatOnSave": true, + "editor.codeActionsOnSave": { + "source.organizeImports": "explicit", + "source.addMissingImports": "explicit", + "source.fixAll.eslint": "explicit" + }, + "search.exclude": { + "**/node_modules": true, + "**/.vscode": true, + "**/build": true, + "**/dist": true + }, + "git.autofetch": true, + "editor.trimAutoWhitespace": true, + "files.encoding": "utf8", + "files.trimFinalNewlines": false, + "files.trimTrailingWhitespace": true, + "css.validate": false, + "editor.quickSuggestions": { + "strings": true + }, + "editor.detectIndentation": false, + "editor.tabSize": 2 +} diff --git a/Dockerfile b/Dockerfile index c97aa3606..741ed35b0 100644 --- a/Dockerfile +++ b/Dockerfile @@ -5,38 +5,46 @@ # ============= # 1. Create an empty directory and copy this file into it. # -# 2. Create image with: +# 2. Create image with: # docker build --tag timeoff:latest . # -# 3. Run with: +# 3. Run with: # docker run -d -p 3000:3000 --name alpine_timeoff timeoff # -# 4. Login to running container (to update config (vi config/app.json): -# docker exec -ti --user root alpine_timeoff /bin/sh # -------------------------------------------------------------------- -FROM alpine:latest as dependencies +FROM node:16-alpine -RUN apk add --no-cache \ - nodejs npm +RUN apk update +#RUN apk upgrade -COPY package.json . -RUN npm install +# Install dependencies +RUN apk add \ + git \ + make \ + python3 \ + g++ \ + gcc \ + libc-dev \ + clang -FROM alpine:latest +WORKDIR /app LABEL org.label-schema.schema-version="1.0" LABEL org.label-schema.docker.cmd="docker run -d -p 3000:3000 --name alpine_timeoff" -RUN apk add --no-cache \ - nodejs npm \ - vim +# Cache the docker layer with the node_modules +COPY package.json /app/package.json +COPY package-lock.json /app/package-lock.json -RUN adduser --system app --home /app -USER app -WORKDIR /app +RUN npm install -y + +# Copy the application into the container. COPY . /app -COPY --from=dependencies node_modules ./node_modules -CMD npm start +# Add user so it doesn't run as root +RUN adduser --system app --home /app +USER app EXPOSE 3000 + +CMD npm start diff --git a/README.md b/README.md index a28d76be5..9dd7c53f8 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,3 @@ - # TimeOff.Management Web application for managing employee absences. @@ -51,9 +50,9 @@ Ability to back up entire company leave data into CSV file. So it could be used The most used customer paths are mobile friendly: -* employee is able to request new leave from mobile device +- employee is able to request new leave from mobile device -* supervisor is able to record decision from the mobile as well. +- supervisor is able to record decision from the mobile as well. **Lots of other little things that would make life easier** @@ -80,18 +79,158 @@ Create company account and use cloud based version. ### Self hosting +```bash +# Clone the repository +git clone https://github.com/timeoff-management/application.git timeoff-management +cd timeoff-management +``` + +Edit the configuration inside the `config` folder. + +#### Standalone + Install TimeOff.Management application within your infrastructure: -(make sure you have Node.js (>=4.0.0) and SQLite installed) +(make sure you have Node.js (>=16.0.0) and SQLite installed) ```bash -git clone https://github.com/timeoff-management/application.git timeoff-management -cd timeoff-management npm install npm start ``` + Open http://localhost:3000/ in your browser. +#### Using Docker + +##### Using an image from DockerHub [aliengen/timeoff-management-application](https://hub.docker.com/r/aliengen/timeoff-management-application) + +```bash +# Pull the image +docker pull aliengen/timeoff-management-application:master + +# Run the container using an `env` file to load the configuration +docker run -d -p 3000:3000 --env-file ./env --name timeoff aliengen/timeoff-management-application:master + +# Or you can run the container using the `app.json` file to load the configuration +docker run -d -p 3000:3000 -v ./config/app.json:/app/config/app.json --name timeoff aliengen/timeoff-management-application:master +``` + +##### Build the image manually + +You can build the image from the latest version of the repository. + +```bash +# Build the docker image +docker build --tag timeoff:latest . + +# Launch the docker image +docker run -d -p 3000:3000 --name alpine_timeoff timeoff +``` + +##### Using Docker-compose + +```bash +docker-compose up +``` + +## Configuration + +### Using environment variables + +| Variable | Description | Default value | +| ------------------------- | ------------------------------------------------------------ | --------------- | +| BRANDING_URL | URL of the application | http://app.timeoff.management/ | +| BRANDING_WEBSITE | URL of the company's website | http://timeoff.management/ | +| PORT | Port of the application | 3000 | +| NODE_ENV | Environment of NodeJs | development | +| CRYPTO_SECRET | Secret for password hashing | | +| DATABASE_URL | Database URL format (`mysql://localhost:3306/database`) | | +| DB_HOST | Database hostname | | +| DB_DATABASE | Database name | | +| DB_USERNAME | Database username | | +| DB_PASSWORD | Database password | | +| DB_DIALECT | Database dialect (sqlite, mysql, postgres) | sqlite | +| DB_STORAGE | Database storage file | db.[ENV].sqlite | +| DB_LOGGING | Logging of queries | false | +| DB_POOL_MAX | Maximum number of connection in pool | 5 | +| DB_POOL_MIN | Minimum number of connection in pool | 0 | +| DB_POOL_ACQUIRE | The maximum time, in milliseconds, that pool will try to get connection before throwing error | 60000 | +| DB_POOL_IDLE | The maximum time, in milliseconds, that a connection can be idle before being released. | 10000 | +| SMTP_HOST | Host of the smtp server | localhost | +| SMTP_PORT | Port of the smtp server | 25 | +| SMTP_FROM | Sender email | email@test.com | +| SMTP_AUTH_USER | Username for the smtp server | | +| SMTP_AUTH_PASS | Password for the smtp server | | +| SMTP_REQUIRE_TLS | Use STARTTLS | false | +| SESSIONS_SECRET | Secret for the sessions | | +| SESSIONS_STORE | Storage for the sessions (`sequelize`,`redis`) | sequelize | +| SESSIONS_REDIS_HOST | Redis hostname | localhost | +| SESSIONS_REDIS_PORT | Redis port | 6379 | +| SLACK_TOKEN | If set, the Slack token to send message | | +| SLACK_BOT_NAME | Name of the bot on Slack | | +| SLACK_ICON_URL | Icon of the bot on Slack | | +| LOGIN_DEFAULT | Display the default login form | true | +| LOGIN_GOOGLE | Enable the authentication with Google | false | +| GOOGLE_ANALYTICS_TRACKER | Google Analytics tracker code | | +| GOOGLE_AUTH_CLIENTID | Google Auth client ID | | +| GOOGLE_AUTH_CLIENTSECRET | Google Auth client secret | | +| GOOGLE_AUTH_DOMAINS | Allowed domains | | +| OPTIONS_REGISTRATION | Allow users to create a new company account on Timeoff | true | + +### Using the JSON configuration files + +#### app.json + +```json +{ + "branding": { + "url": "http://app.timeoff.management", + "website": "http://timeoff.management" + }, + "crypto_secret": "Secret used for password hashing", + "login": { + "default": true, + "google": false + }, + "smtp": { + "host": "localhost", + "port": 25, + "from": "email@test.com", + "auth": { + "user": "user", + "pass": "pass" + } + }, + "sessions": { + "secret": "Secret used for sessions", + "store": "sequelize", + "redis": { + "host": "localhost", + "port": 6379 + } + }, + "google": { + "analytics": { + "tracker": "Your GA tracker code" + }, + "auth": { + "clientId": "123", + "clientSecret": "123", + "domains": ["myalloweddomain.com"] + } + }, + "slack": { + "token": "Get your Web API token from you Slack admin page.", + "icon_url": "The image can be hosted anywhere, but I would recoment to upload an icon to your Slack and use it's url.", + "bot_name": "The display name for the messages being sent." + }, + "options": { + "registration": true + }, +} +``` + + ## Run tests We have quite a wide test coverage, to make sure that the main user paths work as expected. diff --git a/app.js b/app.js index 7b087ba33..1e4e25e6c 100644 --- a/app.js +++ b/app.js @@ -1,106 +1,112 @@ - -var express = require('express'); -var path = require('path'); -var favicon = require('serve-favicon'); -var logger = require('morgan'); -var cookieParser = require('cookie-parser'); -var bodyParser = require('body-parser'); -var moment = require('moment'); -const createSessionMiddleware = require('./lib/middleware/withSession'); - -var app = express(); +const express = require('express') +const path = require('path') +const favicon = require('serve-favicon') +const logger = require('morgan') +const cookieParser = require('cookie-parser') +const bodyParser = require('body-parser') +const moment = require('moment') +const _handlebars = require('handlebars') +const { + allowInsecurePrototypeAccess +} = require('@handlebars/allow-prototype-access') + +const app = express() + +// Handlebars +// +// Secure if only developers have access to the templates +// https://stackoverflow.com/questions/59690923/handlebars-access-has-been-denied-to-resolve-the-property-from-because-it-is // View engine setup -var handlebars = require('express-handlebars') - .create({ - defaultLayout : 'main', - extname : '.hbs', - helpers : require('./lib/view/helpers')(), - }); +const handlebars = require('express-handlebars').create({ + defaultLayout: 'main', + extname: '.hbs', + helpers: require('./lib/view/helpers')(), + handlebars: allowInsecurePrototypeAccess(_handlebars) +}) -app.engine('.hbs', handlebars.engine); -app.set('view engine', '.hbs'); +app.engine('.hbs', handlebars.engine) +app.set('view engine', '.hbs') // Add single reference to the model into application object // and reuse it whenever an access to DB is needed -app.set('db_model', require('./lib/model/db')); +app.set('db_model', require('./lib/model/db')) // uncomment after placing your favicon in /public -//app.use(favicon(__dirname + '/public/favicon.ico')); -app.use(logger('dev')); -app.use(bodyParser.json()); -app.use(bodyParser.urlencoded({ extended: false })); -app.use(cookieParser()); -app.use(express.static(path.join(__dirname, 'public'))); - - +// app.use(favicon(__dirname + '/public/favicon.ico')); +app.use(logger('dev')) +app.use(bodyParser.json()) +app.use(bodyParser.urlencoded({ extended: false })) +app.use(cookieParser()) +app.use(express.static(path.join(__dirname, 'public'))) // Setup authentication mechanism -const passport = require('./lib/passport')(); - -app.use(createSessionMiddleware({ - sequelizeDb: app.get('db_model').sequelize, -})) -app.use(passport.initialize()); -app.use(passport.session()); - +const passport = require('./lib/passport')() +const session = require('express-session') +// initalize sequelize with session store +const SequelizeStore = require('connect-session-sequelize')(session.Store) +app.use( + session({ + secret: 'my dirty secret ;khjsdkjahsdajhasdam,nnsnad,', + resave: false, + saveUninitialized: false, + store: new SequelizeStore({ + db: app.get('db_model').sequelize + }) + }) +) +app.use(passport.initialize()) +app.use(passport.session()) // Custom middlewares // // Make sure session and user objects are available in templates -app.use(function(req,res,next){ - +app.use(function(req, res, next) { // Get today given user's timezone - var today; + let today - if ( req.user && req.user.company ) { - today = req.user.company.get_today(); + if (req.user && req.user.company) { + today = req.user.company.get_today() } else { - today = moment.utc(); + today = moment.utc() } - res.locals.session = req.session; - res.locals.logged_user = req.user; - res.locals.url_to_the_site_root = '/'; - res.locals.requested_path = req.originalUrl; + res.locals.session = req.session + res.locals.logged_user = req.user + res.locals.url_to_the_site_root = '/' + res.locals.requested_path = req.originalUrl // For book leave request modal - res.locals.booking_start = today, - res.locals.booking_end = today, - res.locals.keep_team_view_hidden = - !! (req.user && req.user.company.is_team_view_hidden && ! req.user.admin); - - next(); -}); - -app.use(function(req,res,next){ - res.locals.custom_java_script = [ - '/js/bootstrap-datepicker.js', - '/js/global.js' - ]; - res.locals.custom_css = [ - '/css/bootstrap-datepicker3.standalone.css' - ]; - - next(); -}); + res.locals.booking_start = today + res.locals.booking_end = today + res.locals.keep_team_view_hidden = !!( + req.user && + req.user.company.is_team_view_hidden && + !req.user.admin + ) + + next() +}) + +app.use(function(_req, res, next) { + res.locals.custom_java_script = [ + '/js/bootstrap-datepicker.js', + '/js/global.js' + ] + res.locals.custom_css = ['/css/bootstrap-datepicker3.standalone.css'] + next() +}) // Enable flash messages within session -app.use( require('./lib/middleware/flash_messages') ); +app.use(require('./lib/middleware/flash_messages')) -app.use( require('./lib/middleware/session_aware_redirect') ); +app.use(require('./lib/middleware/session_aware_redirect')) // Here will be publicly accessible routes -app.use( - '/feed/', - require('./lib/route/feed') -); +app.use('/feed/', require('./lib/route/feed')) -app.use( - '/integration/v1/', - require('./lib/route/integration_api')(passport) -); +app.use('/integration/v1/', require('./lib/route/integration_api')(passport)) app.use( '/', @@ -108,74 +114,60 @@ app.use( // All rotes bellow are only for authenticated users require('./lib/route/dashboard') -); +) -app.use('/api/v1/', require('./lib/route/api')); +app.use('/api/v1/', require('./lib/route/api')) -app.use( - '/calendar/', - require('./lib/route/calendar') -); +app.use('/calendar/', require('./lib/route/calendar')) -app.use( - '/settings/', - require('./lib/route/settings') -); +app.use('/settings/', require('./lib/route/settings')) // '/settings/' path is quite big hence there are two modules providing handlers for it -app.use('/settings/', require('./lib/route/departments')); -app.use('/settings/', require('./lib/route/bankHolidays')); +app.use('/settings/', require('./lib/route/departments')) +app.use('/settings/', require('./lib/route/bankHolidays')) app.use( '/users/', // Order of following requires for /users/ matters require('./lib/route/users/summary'), require('./lib/route/users') -); +) -app.use( - '/requests/', - require('./lib/route/requests') -); +app.use('/requests/', require('./lib/route/requests')) -app.use( - '/audit/', - require('./lib/route/audit') -); +app.use('/audit/', require('./lib/route/audit')) -app.use( - '/reports/', - require('./lib/route/reports') -); +app.use('/reports/', require('./lib/route/reports')) // catch 404 app.use(function(req, res, next) { - res.render('not_found'); -}); - + res.render('not_found') +}) // error handlers // development error handler // will print stacktrace if (app.get('env') === 'development') { - app.use(function(err, req, res, next) { - res.status(err.status || 500); - res.render('error', { - message: err.message, - error: err - }); - }); + app.use(function(err, req, res, next) { + console.error(err) + res.status(err.status || 500) + res.render('error', { + message: err.message, + error: err + }) + }) } // production error handler // no stacktraces leaked to user app.use(function(err, req, res, next) { - res.status(err.status || 500); - res.render('error', { - message: err.message, - error: {} - }); -}); - -module.exports = app; + console.error(err) + res.status(err.status || 500) + res.render('error', { + message: err.message, + error: {} + }) +}) + +module.exports = app diff --git a/bin/calculate_carry_over_allowance_for_all_users.js b/bin/calculate_carry_over_allowance_for_all_users.js index e1800fa42..adafa3a43 100644 --- a/bin/calculate_carry_over_allowance_for_all_users.js +++ b/bin/calculate_carry_over_allowance_for_all_users.js @@ -1,14 +1,15 @@ +'use strict' -'use strict'; +const { + calculateCarryOverAllowance + } = require('../lib/model/calculateCarryOverAllowance'); + const models = require('../lib/model/db') -const - {calculateCarryOverAllowance} = require('../lib/model/calculateCarryOverAllowance'), - models = require('../lib/model/db'); - -models.User - .findAll() - .then(users =>calculateCarryOverAllowance({users})) +models.User.findAll() + .then(users => calculateCarryOverAllowance({ users })) .then(() => console.log('Done!')) - .catch(error => console.log( - `Failed to recalculate carry over allowance: ${error} at ${error.stack}` - )); + .catch(error => + console.log( + `Failed to recalculate carry over allowance: ${error} at ${error.stack}` + ) + ) diff --git a/bin/check_where_i_am_on_google.js b/bin/check_where_i_am_on_google.js index 028a82f19..d568650c5 100644 --- a/bin/check_where_i_am_on_google.js +++ b/bin/check_where_i_am_on_google.js @@ -1,66 +1,106 @@ - // Usage: // node bin/check_where_i_am_on_google.js --domain="nixieshop.com" --query="nixie shop" -'use strict'; - -var - optimist = require('optimist').argv, - search_query = optimist.query || 'time off manager', - web_site_domain = optimist.domain || 'timeoffmanager.com', - stop_on_first = true; - -console.log('-----------------------------------'); -console.log(' Cheking query string : '+search_query); -console.log(' Look for domain : '+web_site_domain); -console.log('-----------------------------------'); +'use strict' +const optimist = require('optimist').argv; + const search_query = optimist.query || 'time off manager'; + const web_site_domain = optimist.domain || 'timeoffmanager.com'; + const stop_on_first = true -var webdriver = require('selenium-webdriver'), - _ = require('underscore'), - google_url = 'https://www.google.com/search?q='+search_query+'&start=', - driver; +console.log('-----------------------------------') +console.log(' Cheking query string : ' + search_query) +console.log(' Look for domain : ' + web_site_domain) +console.log('-----------------------------------') +const webdriver = require('selenium-webdriver'); + const _ = require('underscore'); + const google_url = 'https://www.google.com/search?q=' + search_query + '&start='; + let driver // Instantiate new driver object driver = new webdriver.Builder() .withCapabilities(webdriver.Capabilities.chrome()) - .build(); - - - -_.map([ - 0,10,20,30,40,50,60,70,80,90,100, - 110,120,130,140,150,160,170,180,190,200, - 210,220,230,240,250,260,270,280,290,300, - 310,320,330,340,350,360,370,380,390,400, - 410,420,430,440,450,460,470,480,490,500, -// 510,520,530,540,550,560,570,580,590,600, -// 610,620,630,640,650,660,670,680,690,700, -// 710,720,730,740,750,760,770,780,790,800, -// 810,820,830,840,850,860,870,880,890,900, -// 910,920,930,940,950,960,970,980,990,1000, -], function(i){ - - driver.sleep(500); + .build() + +_.map( + [ + 0, + 10, + 20, + 30, + 40, + 50, + 60, + 70, + 80, + 90, + 100, + 110, + 120, + 130, + 140, + 150, + 160, + 170, + 180, + 190, + 200, + 210, + 220, + 230, + 240, + 250, + 260, + 270, + 280, + 290, + 300, + 310, + 320, + 330, + 340, + 350, + 360, + 370, + 380, + 390, + 400, + 410, + 420, + 430, + 440, + 450, + 460, + 470, + 480, + 490, + 500 + // 510,520,530,540,550,560,570,580,590,600, + // 610,620,630,640,650,660,670,680,690,700, + // 710,720,730,740,750,760,770,780,790,800, + // 810,820,830,840,850,860,870,880,890,900, + // 910,920,930,940,950,960,970,980,990,1000, + ], + function(i) { + driver.sleep(500) // Go to front page - driver.get( google_url + i ); - - driver.getPageSource().then(function(source){ - if (source.match(new RegExp('http(s)?://(www.)?'+web_site_domain))) { - console.log('>>>>>>> Found on '+(1+i/10)+' page'); - if (stop_on_first) { - driver.quit().then(function(){ - process.exit(); - }); - } - } else { - console.log((1+i/10)+'...'); + driver.get(google_url + i) + + driver.getPageSource().then(function(source) { + if (source.match(new RegExp('http(s)?://(www.)?' + web_site_domain))) { + console.log('>>>>>>> Found on ' + (1 + i / 10) + ' page') + if (stop_on_first) { + driver.quit().then(function() { + process.exit() + }) } - }); -}); - - -driver.quit(); - + } else { + console.log(1 + i / 10 + '...') + } + }) + } +) + +driver.quit() diff --git a/bin/fetch_user_stat.js b/bin/fetch_user_stat.js index 25d2d4c9c..3c38f1cf2 100644 --- a/bin/fetch_user_stat.js +++ b/bin/fetch_user_stat.js @@ -1,18 +1,13 @@ +'use strict' -'use strict'; - -var test = require('selenium-webdriver/testing'), - By = require('selenium-webdriver').By, - expect = require('chai').expect, - _ = require('underscore'), - Promise = require("bluebird"), - until = require('selenium-webdriver').until, - register_new_user_func = require('../t/lib/register_new_user'), - login_user_func = require('../t/lib/login_with_user'), - logout_user_func = require('../t/lib/logout_user'), - open_page_func = require('../t/lib/open_page'), - config = require('../t/lib/config'), - application_host = config.get_application_host(); +const By = require('selenium-webdriver').By +const Promise = require('bluebird') +const register_new_user_func = require('../t/lib/register_new_user') +const login_user_func = require('../t/lib/login_with_user') +const logout_user_func = require('../t/lib/logout_user') +const open_page_func = require('../t/lib/open_page') +const config = require('../t/lib/config') +const application_host = config.get_application_host() /* * THis is simple scrip to execute on different versions of application @@ -24,84 +19,92 @@ var test = require('selenium-webdriver/testing'), * * */ -describe('Collect remaining days for employees', function(){ - - this.timeout( config.get_execution_timeout() ); +describe('Collect remaining days for employees', function() { + this.timeout(config.get_execution_timeout()) - var report = {}, - driver; + const report = {} + let driver - it("Create new company", function(done){ + it('Create new company', function(done) { register_new_user_func({ - application_host : application_host, + application_host + }).then(function(data) { + driver = data.driver + done() }) - .then(function(data){ - driver = data.driver; - done(); - }); - }); + }) - it("Logout", function(done){ + it('Logout', function(done) { logout_user_func({ - application_host : application_host, - driver : driver, + application_host, + driver + }).then(function() { + done() }) - .then(function(){ done() }); - }); + }) // This is a list of accountes to iterate through // By default it is dummy ones - [ - 'test@test.com', - 'test2@test.com' - ].forEach( email => { + const users = ['test@test.com', 'test2@test.com'] - it("Login as user", function(done){ + for (const email of users) { + it('Login as user', function(done) { login_user_func({ - application_host : application_host, - user_email : email, - driver : driver, + application_host, + user_email: email, + driver + }).then(function() { + done() }) - .then(function(){ done() }); - }); + }) - it("Open users page", function(done){ + it('Open users page', function(done) { open_page_func({ - url : application_host + 'users/', - driver : driver, + url: application_host + 'users/', + driver + }).then(function() { + done() }) - .then(function(){ done() }); - }); - - it("Fetch remaining days for each employee", function(done){ + }) + it('Fetch remaining days for each employee', function(done) { driver .findElements(By.css('tr[data-vpp-user-row]')) - .then(els => Promise.map(els, el => { - let user_id; - - return el.getAttribute('data-vpp-user-row') - .then(u_id => Promise.resolve( user_id = u_id )) - .then(() => el.findElement(By.css('td.vpp-days-remaining'))) - .then(el => el.getText()) - .then(days => Promise.resolve( report[ user_id ] = days )); - }, { concurrency : 0 })) + .then(els => + Promise.map( + els, + el => { + let user_id + + return el + .getAttribute('data-vpp-user-row') + .then(u_id => Promise.resolve((user_id = u_id))) + .then(() => el.findElement(By.css('td.vpp-days-remaining'))) + .then(el => el.getText()) + .then(days => Promise.resolve((report[user_id] = days))) + }, + { concurrency: 0 } + ) + ) .then(() => done()) - }); + }) - it("Logout", function(done){ + it('Logout user', function(done) { logout_user_func({ - application_host : application_host, - driver : driver, + application_host, + driver + }).then(function() { + done() }) - .then(function(){ done() }); - }); - }); + }) + } - after(function(done){ - console.dir(report); - driver.quit().then(function(){ done(); }); - }); -}); + after(function(done) { + console.dir(report) + driver.quit().then(function() { + done() + }) + }) +}) diff --git a/bin/wwww b/bin/wwww index 2caaa0a8c..1fc786667 100755 --- a/bin/wwww +++ b/bin/wwww @@ -1,12 +1,15 @@ #!/usr/bin/env node -var debug = require('debug')('vacation-tracker'); -var app = require('../app'); +const debug = require('debug')('vacation-tracker') +const app = require('../app') -app.set('port', process.env.PORT || 3000); +app.set('port', process.env.PORT || 3000) -app.get('db_model').sequelize.sync().then(function () { - var server = app.listen(app.get('port'), function() { - debug('Express server listening on port ' + server.address().port); - }); -}); +app + .get('db_model') + .sequelize.sync() + .then(function() { + var server = app.listen(app.get('port'), function() { + debug('Express server listening on port ' + server.address().port) + }) + }) diff --git a/bin/wwww_cluster b/bin/wwww_cluster index 039fc8f6c..b4afea0b0 100644 --- a/bin/wwww_cluster +++ b/bin/wwww_cluster @@ -1,28 +1,30 @@ #!/usr/bin/env node -var debug = require('debug')('vacation-tracker'); -var app = require('../app'); +const debug = require('debug')('vacation-tracker') +const app = require('../app') -var cluster = require('cluster'); +const cluster = require('cluster') -if (cluster.isMaster ) { - - cluster.on('exit', function(worker, code){ - if(code != 0 && !worker.suicide) { - console.log('>>>>>> Worker crashed. Starting a new worker'); - cluster.fork(); +if (cluster.isMaster) { + cluster.on('exit', function(worker, code) { + if (code != 0 && !worker.suicide) { + console.log('>>>>>> Worker crashed. Starting a new worker') + cluster.fork() } - }); - - [1,2].forEach(function(){cluster.fork()}); + }) + ;[1, 2].forEach(function() { + cluster.fork() + }) } else { - app.set('port', process.env.PORT || 3000); - - app.get('db_model').sequelize.sync().then(function () { - var server = app.listen(app.get('port'), function() { - console.log('Started to listen on port ' + server.address().port); - }); - }); - + app.set('port', process.env.PORT || 3000) + + app + .get('db_model') + .sequelize.sync() + .then(function() { + var server = app.listen(app.get('port'), function() { + console.log('Started to listen on port ' + server.address().port) + }) + }) } diff --git a/config/app.json b/config/app.json index 26f10a8d0..008eca690 100644 --- a/config/app.json +++ b/config/app.json @@ -1,26 +1,48 @@ { - "allow_create_new_accounts" : true, - "send_emails" : false, - "application_sender_email" : "email@test.com", - "email_transporter" : { - "host" : "localhost", - "port" : 25, - "auth" : { - "user" : "user", - "pass" : "pass" + "branding": { + "url": "http://app.timeoff.management", + "website": "http://timeoff.management" + }, + "crypto_secret": "!2~`HswpPPLa22+=±§sdq qwe,appp qwwokDF_", + "login": { + "default": true, + "google": false + }, + "smtp": { + "host": "localhost", + "port": 25, + "from": "email@test.com", + "auth": { + "user": "user", + "pass": "pass" } }, - "sessionStore": { - "useRedis": false, - "redisConnectionConfiguration": { + "sessions": { + "secret": "my dirty secret ;khjsdkjahsdajhasdam,nnsnad,", + "store": "sequelize", + "redis": { "host": "localhost", "port": 6379 } }, - "ga_analytics_on" : false, - "crypto_secret" : "!2~`HswpPPLa22+=±§sdq qwe,appp qwwokDF_", - "application_domain" : "http://app.timeoff.management", - "promotion_website_domain" : "http://timeoff.management", + "google": { + "analytics": { + "tracker": "" + }, + "auth": { + "clientId": "123", + "clientSecret": "123", + "domains": ["mydomain.com"] + } + }, + "slack": { + "token": "Get your Web API token from you Slack admin page.", + "icon_url": "The image can be hosted anywhere, but I would recoment to upload an icon to your Slack and use it's url.", + "bot_name": "The display name for the messages being sent." + }, + "options": { + "registration": true + }, "locale_code_for_sorting": "en", "force_to_explicitly_select_type_when_requesting_new_leave": false } diff --git a/config/db.json b/config/db.json deleted file mode 100644 index 4b32f445b..000000000 --- a/config/db.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "development": { - "dialect": "sqlite", - "storage": "./db.development.sqlite", - "logging": false - }, - "test": { - "username": "root", - "password": null, - "database": "database_test", - "host": "127.0.0.1", - "dialect": "mysql" - }, - "production": { - "username": "root", - "password": null, - "database": "database_production", - "host": "127.0.0.1", - "dialect": "mysql" - } -} diff --git a/config/localisation.json b/config/localisation.json index e14e253b8..d44b720c8 100644 --- a/config/localisation.json +++ b/config/localisation.json @@ -1,5 +1,5 @@ { - "countries" : { + "countries": { "AD": { "name": "Andorra", "bank_holidays": [ @@ -27278,8 +27278,8 @@ "name": "Other", "bank_holidays": [ { - "name" : "Early May bank holiday", - "date" : "2015-05-04" + "name": "Early May bank holiday", + "date": "2015-05-04" } ] } diff --git a/docker-compose.yaml b/docker-compose.yaml new file mode 100644 index 000000000..d6466dea1 --- /dev/null +++ b/docker-compose.yaml @@ -0,0 +1,9 @@ +version: "3" + +services: + timeoff: + build: . + ports: + - "3000:3000" + volumes: + - ./config:/app/config diff --git a/docs/SessionStoreInRedis.md b/docs/SessionStoreInRedis.md index 6785ce696..c019af7d3 100644 --- a/docs/SessionStoreInRedis.md +++ b/docs/SessionStoreInRedis.md @@ -9,7 +9,7 @@ It is possible to use different storage mechanism for Sessions data: [Redis](htt * Ensure the application's source is at least `1.4.0` * Stop the application * Open `config/app.json` for editing -* Update `sessionStore.useRedis` section to be `true` -* Update `sessionStore.redisConnectionConfiguration`'s `host` and `port` pointing to corresponding instance of Redis -* Save the configuration file +* Update `sessions.store` section to be `redis` +* Update `sessions.redis`'s `host` and `port` pointing to corresponding instance of Redis +* Save the configuration file * Restart the application diff --git a/docs/bootstrap_config.json b/docs/bootstrap_config.json index f9368e601..88ff907ee 100755 --- a/docs/bootstrap_config.json +++ b/docs/bootstrap_config.json @@ -432,4 +432,4 @@ "transition.js" ], "customizerUrl": "http://getbootstrap.com/customize/?id=2f747106c336fe71d867" -} \ No newline at end of file +} diff --git a/docs/db_design.txt b/docs/db_design.txt index 37c880696..23895cbd8 100644 --- a/docs/db_design.txt +++ b/docs/db_design.txt @@ -47,11 +47,11 @@ To have nice visualisation of database schema use this tool http://ondras.zarovi VARBINARY NULL - + INTEGER NULL - + INTEGER NULL @@ -71,6 +71,9 @@ To have nice visualisation of database schema use this tool http://ondras.zarovi TINYINT NULL + +VARBINARY +'NULL' id @@ -112,7 +115,7 @@ To have nice visualisation of database schema use this tool http://ondras.zarovi INTEGER NULL - + INTEGER NULL @@ -124,7 +127,7 @@ To have nice visualisation of database schema use this tool http://ondras.zarovi INTEGER NULL - + INTEGER NULL @@ -142,7 +145,7 @@ To have nice visualisation of database schema use this tool http://ondras.zarovi INTEGER NULL - + INTEGER NULL diff --git a/lib/config.js b/lib/config.js index d01d611de..9bbc16929 100644 --- a/lib/config.js +++ b/lib/config.js @@ -1,11 +1,69 @@ +'use strict' -'use strict'; - -var nconf = require('nconf'); +const nconf = require('nconf') nconf .argv() - .file('localisation', { file: __dirname+'/../config/localisation.json' }) - .file({ file: __dirname+'/../config/app.json' }); + .env({ + separator: '_', + lowerCase: true, + parseValues: true, + transform: function(obj) { + if (obj.key === 'GOOGLE_AUTH_DOMAINS') { + obj.value = obj.value.split(',') + } + return obj + } + }) + .file('localisation', { file: __dirname + '/../config/localisation.json' }) + .file({ file: __dirname + '/../config/app.json' }) + .defaults({ + branding: { + url: 'http://app.timeoff.management', + website: 'http://timeoff.management' + }, + crypto_secret: '!2~`HswpPPLa22+=±§sdq qwe,appp qwwokDF_', + login: { + default: true, + google: false + }, + smtp: { + host: 'localhost', + port: 25, + from: 'email@test.com', + auth: { + user: '', + pass: '' + } + }, + sessions: { + secret: 'my dirty secret ;khjsdkjahsdajhasdam,nnsnad,', + store: 'sequelize', + redis: { + host: 'localhost', + port: 6379 + } + }, + google: { + analytics: { + tracker: '' + }, + auth: { + clientId: '', + clientSecret: '', + domains: [] + } + }, + slack: { + token: '', + icon_url: '', + bot_name: '' + }, + options: { + registration: true + }, + locale_code_for_sorting: 'en', + force_to_explicitly_select_type_when_requesting_new_leave: false + }) -module.exports = nconf; +module.exports = nconf diff --git a/lib/email.js b/lib/email.js index d62c2aedd..9f25dff91 100644 --- a/lib/email.js +++ b/lib/email.js @@ -1,31 +1,31 @@ - -'use strict'; - -const - bluebird = require('bluebird'), - handlebars = require('express-handlebars').create({ - partialsDir : __dirname+'/../views/partials/', - extname : '.hbs', - helpers : require('./view/helpers')(), - }), - config = require('./config'), - nodemailer = require('nodemailer'), - smtpTransport = require('nodemailer-smtp-transport'), - model = require('./model/db'), - {getCommentsForLeave} = require('./model/comment'); - -function Email(){ - -} +'use strict' + +const bluebird = require('bluebird') +const handlebars = require('express-handlebars').create({ + partialsDir: __dirname + '/../views/partials/', + extname: '.hbs', + helpers: require('./view/helpers')() +}) +const config = require('./config') +const nodemailer = require('nodemailer') +const smtpTransport = require('nodemailer-smtp-transport') +const model = require('./model/db') +const { getCommentsForLeave } = require('./model/comment') + +function Email() {} + +const transporter = nodemailer.createTransport( + smtpTransport(config.get('smtp')) +) // This is a little helper that ensure that data in context are in a shape // suitable for usage in templates // function _promise_to_unfold_context(context) { - if (context.hasOwnProperty('user')){ - return context.user.reload_with_session_details(); + if (context.user) { + return context.user.reload_with_session_details() } else { - return bluebird.resolve(1); + return bluebird.resolve(1) } } @@ -35,422 +35,455 @@ function _promise_to_unfold_context(context) { // * render inner part of template // * place the innerpart ingo ready to use HTML wrapper -Email.prototype.promise_rendered_email_template = function(args){ - var filename = args.template_name, - context = args.context || {}; - - return bluebird.resolve() - - // Prepare context to be passed into first rendering stage - .then(function(){ - return _promise_to_unfold_context(context); - }) - - // Render inner part of email - .then(function(){ - return handlebars.render( - __dirname+'/../views/email/'+filename+'.hbs', - context - ); - }) - - // Produce final (ready to use) version of email and Subject - .then(function(text){ - - // Extract subject from email - var subject_and_body = text.split(/\r?\n=====\r?\n/); - - return handlebars - // Render ready to use email: wrap the content with fancy HTML boilerplate - .render( - __dirname+'/../views/email/wrapper.hbs', - { - subject : subject_and_body[0], - body : subject_and_body[1], - } +Email.prototype.promise_rendered_email_template = function(args) { + const filename = args.template_name + const context = args.context || {} + + return ( + bluebird + .resolve() + + // Prepare context to be passed into first rendering stage + .then(() => _promise_to_unfold_context(context)) + + // Render inner part of email + .then(() => + handlebars.render( + __dirname + '/../views/email/' + filename + '.hbs', + context + ) ) - .then(function(final_email){ - return bluebird.resolve({ - subject : subject_and_body[0], - body : final_email, - }); - }); - }); -}; + // Produce final (ready to use) version of email and Subject + .then(text => { + // Extract subject from email + const subject_and_body = text.split(/\r?\n=====\r?\n/) + + return ( + handlebars + // Render ready to use email: wrap the content with fancy HTML boilerplate + .render(__dirname + '/../views/email/wrapper.hbs', { + subject: subject_and_body[0], + body: subject_and_body[1] + }) + .then(final_email => + bluebird.resolve({ + subject: subject_and_body[0], + body: final_email + }) + ) + ) + }) + ) +} // Return function that support same interface as sendMail but promisified. // If current configuration does not allow sending emails, it return empty function // -Email.prototype.get_send_email = function(){ - +Email.prototype.get_send_email = function() { // Check if current installation is set to send emails - if (! config.get("send_emails") || ! config.get("email_transporter") ) { - return function(){ - console.log('Pretend to send email: '+ JSON.stringify(arguments)); - return bluebird.resolve(); - }; + if (!config.get('smtp:host')) { + return function() { + console.debug('Pretend to send email: ' + JSON.stringify(arguments)) + return bluebird.resolve() + } } - var transporter = nodemailer.createTransport(smtpTransport( - config.get("email_transporter") - )); - - var send_mail = bluebird.promisify(transporter.sendMail, transporter); - - return send_mail; -}; + // Send E-mail transactionnally + return function(data) { + return new Promise(function(resolve, reject) { + transporter.sendMail(data, (err, info) => { + if (err) { + console.error('Error while sending mail', err) + return reject(err) + } + resolve(info) + }) + }) + } +} // Send registration complete email for provided user // -Email.prototype.promise_registration_email = function(args){ - var self = this, - user = args.user; - var send_mail = self.get_send_email(); - - return self.promise_rendered_email_template({ - template_name : 'registration_complete', - context : {user : user} - }) - .then(function(email_obj){ - - return send_mail({ - from : config.get('application_sender_email'), - to : user.email, - subject : email_obj.subject, - html : email_obj.body, +Email.prototype.promise_registration_email = function(args) { + const self = this + const user = args.user + const send_mail = self.get_send_email() + + return self + .promise_rendered_email_template({ + template_name: 'registration_complete', + context: { user } }) - .then(function(send_result){ - return user.record_email_addressed_to_me(email_obj) - .then(function(){ return bluebird.resolve( send_result ); }); - }); - }); -}; - -Email.prototype.promise_add_new_user_email = function(args){ - var self = this, - company = args.company, - admin_user = args.admin_user, - new_user = args.new_user, - send_mail = self.get_send_email(); - - return self.promise_rendered_email_template({ - template_name : 'add_new_user', - context : { - new_user : new_user, - admin_user : admin_user, - company : company, - user : new_user, - } - }) - .then(function(email_obj){ - - return send_mail({ - from : config.get('application_sender_email'), - to : new_user.email, - subject : email_obj.subject, - html : email_obj.body, - }) - .then(function(send_result){ - return new_user.record_email_addressed_to_me(email_obj) - .then(function(){ return bluebird.resolve( send_result ); }); - }); - }); + .then(email_obj => + send_mail({ + from: config.get('smtp:from'), + to: user.email, + subject: email_obj.subject, + html: email_obj.body + }) + .then(send_result => bluebird.resolve(send_result)) + .finally(() => user.record_email_addressed_to_me(email_obj)) + ) +} -}; +Email.prototype.promise_add_new_user_email = function(args) { + const self = this + const company = args.company + const admin_user = args.admin_user + const new_user = args.new_user + const send_mail = self.get_send_email() + + return self + .promise_rendered_email_template({ + template_name: 'add_new_user', + context: { + new_user, + admin_user, + company, + user: new_user + } + }) + .then(email_obj => + send_mail({ + from: config.get('smtp:from'), + to: new_user.email, + subject: email_obj.subject, + html: email_obj.body + }) + .then(send_result => bluebird.resolve(send_result)) + .finally(() => new_user.record_email_addressed_to_me(email_obj)) + ) +} -Email.prototype.promise_leave_request_revoke_emails = function(args){ - const self = this, - leave = args.leave, - send_mail = self.get_send_email(); +Email.prototype.promise_leave_request_revoke_emails = function(args) { + const self = this + const leave = args.leave + const send_mail = self.get_send_email() - let template_name_to_supervisor = 'leave_request_revoke_to_supervisor'; - let template_name_to_requestor = 'leave_request_revoke_to_requestor'; + let template_name_to_supervisor = 'leave_request_revoke_to_supervisor' + let template_name_to_requestor = 'leave_request_revoke_to_requestor' - if ( model.Leave.does_skip_approval( leave.get('user'), leave.get('leave_type') ) ) { - template_name_to_supervisor = 'leave_request_revoke_to_supervisor_autoapprove'; - template_name_to_requestor = 'leave_request_revoke_to_requestor_autoapprove'; + if ( + model.Leave.does_skip_approval(leave.get('user'), leave.get('leave_type')) + ) { + template_name_to_supervisor = + 'leave_request_revoke_to_supervisor_autoapprove' + template_name_to_requestor = 'leave_request_revoke_to_requestor_autoapprove' } - const promise_email_to_supervisor = comments => self.promise_rendered_email_template({ - template_name : template_name_to_supervisor, - context : { - leave, - comments, - approver : leave.get('approver'), - requester : leave.get('user'), - user : leave.get('approver'), - } - }) - .then(email_obj => - send_mail({ - from : config.get('application_sender_email'), - to : leave.get('approver').email, - subject : email_obj.subject, - html : email_obj.body, - }) - .then(() => leave.get('approver').record_email_addressed_to_me(email_obj)) - ); - - const promise_email_to_requestor = comments => self.promise_rendered_email_template({ - template_name : template_name_to_requestor, - context : { - leave, - comments, - approver : leave.get('approver'), - requester : leave.get('user'), - user : leave.get('user'), - } - }) - .then(email_obj => - send_mail({ - from : config.get('application_sender_email'), - to : leave.get('user').email, - subject : email_obj.subject, - html : email_obj.body, - }) - .then(() => leave.get('user').record_email_addressed_to_me(email_obj)) - ); + const promise_email_to_supervisor = comments => + self + .promise_rendered_email_template({ + template_name: template_name_to_supervisor, + context: { + leave, + comments, + approver: leave.get('approver'), + requester: leave.get('user'), + user: leave.get('approver') + } + }) + .then(email_obj => + send_mail({ + from: config.get('smtp:from'), + to: leave.get('approver').email, + subject: email_obj.subject, + html: email_obj.body + }).finally(() => + leave.get('approver').record_email_addressed_to_me(email_obj) + ) + ) + + const promise_email_to_requestor = comments => + self + .promise_rendered_email_template({ + template_name: template_name_to_requestor, + context: { + leave, + comments, + approver: leave.get('approver'), + requester: leave.get('user'), + user: leave.get('user') + } + }) + .then(email_obj => + send_mail({ + from: config.get('smtp:from'), + to: leave.get('user').email, + subject: email_obj.subject, + html: email_obj.body + }).finally(() => + leave.get('user').record_email_addressed_to_me(email_obj) + ) + ) - return getCommentsForLeave({leave}) - .then(comments => bluebird.join( - promise_email_to_supervisor(comments), promise_email_to_requestor(comments), + return getCommentsForLeave({ leave }).then(comments => + bluebird.join( + promise_email_to_supervisor(comments), + promise_email_to_requestor(comments), () => bluebird.resolve() - )); -}; + ) + ) +} -Email.prototype.promise_leave_request_emails = function(args){ - var self = this, - leave = args.leave, - send_mail = self.get_send_email(); +Email.prototype.promise_leave_request_emails = function(args) { + const self = this + const leave = args.leave + const send_mail = self.get_send_email() - var template_name_to_supervisor = 'leave_request_to_supervisor'; - var template_name_to_requestor = 'leave_request_to_requestor'; + let template_name_to_supervisor = 'leave_request_to_supervisor' + let template_name_to_requestor = 'leave_request_to_requestor' - if ( model.Leave.does_skip_approval( leave.get('user'), leave.get('leave_type') ) ) { - template_name_to_supervisor = 'leave_request_to_supervisor_autoapprove'; - template_name_to_requestor = 'leave_request_to_requestor_autoapprove'; + if (leave.is_auto_approve()) { + template_name_to_supervisor = 'leave_request_to_supervisor_autoapprove' + template_name_to_requestor = 'leave_request_to_requestor_autoapprove' } - const promise_email_to_supervisor = ({comments, requesterAllowance}) => supervisor => self.promise_rendered_email_template({ - template_name : template_name_to_supervisor, - context : { - leave, - comments, - approver : supervisor, - requester : leave.get('user'), - user : supervisor, - requesterAllowance, - } - }) - .then(email_obj => - send_mail({ - from : config.get('application_sender_email'), - to : supervisor.email, - subject : email_obj.subject, - html : email_obj.body, - }) - .then(() => supervisor.record_email_addressed_to_me(email_obj)) - ); - - const promise_email_to_requestor = ({comments, requesterAllowance}) => self.promise_rendered_email_template({ - template_name : template_name_to_requestor, - context : { - leave, - comments, - approver : leave.get('approver'), - requester : leave.get('user'), - user : leave.get('approver'), - requesterAllowance, - } - }) - .then(email_obj => send_mail({ - from : config.get('application_sender_email'), - to : leave.get('user').email, - subject : email_obj.subject, - html : email_obj.body, - }) - .then(() => leave.get('user').record_email_addressed_to_me(email_obj)) - ); + const promise_email_to_supervisor = ({ + comments, + requesterAllowance + }) => supervisor => + self + .promise_rendered_email_template({ + template_name: template_name_to_supervisor, + context: { + leave, + comments, + approver: supervisor, + requester: leave.get('user'), + user: supervisor, + requesterAllowance + } + }) + .then(email_obj => + send_mail({ + from: config.get('smtp:from'), + to: supervisor.email, + subject: email_obj.subject, + html: email_obj.body + }).finally(() => supervisor.record_email_addressed_to_me(email_obj)) + ) + + const promise_email_to_requestor = ({ comments, requesterAllowance }) => + self + .promise_rendered_email_template({ + template_name: template_name_to_requestor, + context: { + leave, + comments, + approver: leave.get('approver'), + requester: leave.get('user'), + user: leave.get('approver'), + requesterAllowance + } + }) + .then(email_obj => + send_mail({ + from: config.get('smtp:from'), + to: leave.get('user').email, + subject: email_obj.subject, + html: email_obj.body + }).finally(() => + leave.get('user').record_email_addressed_to_me(email_obj) + ) + ) return Promise.all([ - getCommentsForLeave({leave}), - leave.get('user').promise_allowance(), - ]) - .then(([comments, requesterAllowance]) => bluebird.join( - promise_email_to_requestor({comments, requesterAllowance}), - leave.get('user') + getCommentsForLeave({ leave }), + leave.get('user').promise_allowance() + ]).then(([comments, requesterAllowance]) => + bluebird.join( + promise_email_to_requestor({ comments, requesterAllowance }), + leave + .get('user') .promise_supervisors() - .map(supervisor => promise_email_to_supervisor({comments, requesterAllowance})(supervisor)), + .map(supervisor => + promise_email_to_supervisor({ comments, requesterAllowance })( + supervisor + ) + ), () => bluebird.resolve() - )); -}; - - -Email.prototype.promise_leave_request_decision_emails = function(args){ - const - self = this, - leave = args.leave, - action = args.action, - was_pended_revoke = args.was_pended_revoke, - send_mail = self.get_send_email(); - - const promise_email_to_supervisor = comments => self.promise_rendered_email_template({ - template_name : 'leave_request_decision_to_supervisor', - context : { - leave, - action, - was_pended_revoke, - comments, - approver: leave.get('approver'), - requester: leave.get('user'), - user: leave.get('approver'), - } - }) - .then(email_obj => - send_mail({ - from : config.get('application_sender_email'), - to : leave.get('approver').email, - subject : email_obj.subject, - html : email_obj.body, - }) - .then(()=>leave.get('approver').record_email_addressed_to_me(email_obj)) - ); - - const promise_email_to_requestor = comments => self.promise_rendered_email_template({ - template_name : 'leave_request_decision_to_requestor', - context : { - leave, - action, - was_pended_revoke, - comments, - approver: leave.get('approver'), - requester: leave.get('user'), - user: leave.get('user'), - } - }) - .then(email_obj => - send_mail({ - from : config.get('application_sender_email'), - to : leave.get('user').email, - subject : email_obj.subject, - html : email_obj.body, - }) - .then(() => leave.get('user').record_email_addressed_to_me(email_obj)) - ); + ) + ) +} + +Email.prototype.promise_leave_request_decision_emails = function(args) { + const self = this + const leave = args.leave + const action = args.action + const was_pended_revoke = args.was_pended_revoke + const send_mail = self.get_send_email() + + const promise_email_to_supervisor = comments => + self + .promise_rendered_email_template({ + template_name: 'leave_request_decision_to_supervisor', + context: { + leave, + action, + was_pended_revoke, + comments, + approver: leave.get('approver'), + requester: leave.get('user'), + user: leave.get('approver') + } + }) + .then(email_obj => + send_mail({ + from: config.get('smtp:from'), + to: leave.get('approver').email, + subject: email_obj.subject, + html: email_obj.body + }).finally(() => + leave.get('approver').record_email_addressed_to_me(email_obj) + ) + ) - return getCommentsForLeave({leave}) - .then(comments => bluebird.join( - promise_email_to_supervisor(comments), promise_email_to_requestor(comments), + const promise_email_to_requestor = comments => + self + .promise_rendered_email_template({ + template_name: 'leave_request_decision_to_requestor', + context: { + leave, + action, + was_pended_revoke, + comments, + approver: leave.get('approver'), + requester: leave.get('user'), + user: leave.get('user') + } + }) + .then(email_obj => + send_mail({ + from: config.get('smtp:from'), + to: leave.get('user').email, + subject: email_obj.subject, + html: email_obj.body + }).finally(() => + leave.get('user').record_email_addressed_to_me(email_obj) + ) + ) + + return getCommentsForLeave({ leave }).then(comments => + bluebird.join( + promise_email_to_supervisor(comments), + promise_email_to_requestor(comments), () => bluebird.resolve() - )); -}; - -Email.prototype.promise_forgot_password_email = function(args){ - var self = this, - user = args.user, - send_mail = self.get_send_email(); - - return user.getCompany() - .then(function(company){ - return self.promise_rendered_email_template({ - template_name : 'forgot_password', - context : { - user : user, - company : company, + ) + ) +} + +Email.prototype.promise_forgot_password_email = function(args) { + const self = this + const user = args.user + const send_mail = self.get_send_email() + + return user + .getCompany() + .then(company => + self.promise_rendered_email_template({ + template_name: 'forgot_password', + context: { + user, + company } - }); - }) - .then(function(email_obj){ - - return send_mail({ - from : config.get('application_sender_email'), - to : user.email, - subject : email_obj.subject, - html : email_obj.body, - }) - .then(function(send_result){ - return user.record_email_addressed_to_me(email_obj) - .then(function(){ return bluebird.resolve( send_result ); }); - }); - }); -}; - -Email.prototype.promise_reset_password_email = function(args){ - var self = this, - user = args.user, - send_mail = self.get_send_email(); - - return self.promise_rendered_email_template({ - template_name : 'reset_password', - context : { - user : user, - } - }) - .then(function(email_obj){ - - return send_mail({ - from : config.get('application_sender_email'), - to : user.email, - subject : email_obj.subject, - html : email_obj.body, - }) - .then(function(send_result){ - return user.record_email_addressed_to_me(email_obj) - .then(function(){ return bluebird.resolve( send_result ); }); - }); - }); -}; - -Email.prototype.promise_leave_request_cancel_emails = function(args){ - const - self = this, - leave = args.leave, - send_mail = self.get_send_email(); - - const promise_email_to_supervisor = comments => self.promise_rendered_email_template({ - template_name : 'leave_request_cancel_to_supervisor', - context : { - leave, - comments, - approver: leave.get('approver'), - requester: leave.get('user'), - user: leave.get('approver'), - } - }) - .then(emailObj => send_mail({ - from : config.get('application_sender_email'), - to : leave.get('approver').email, - subject : emailObj.subject, - html : emailObj.body, - }) - .then(() => leave.get('approver').record_email_addressed_to_me(emailObj)) - ); - - const promise_email_to_requestor = comments => self.promise_rendered_email_template({ - template_name : 'leave_request_cancel_to_requestor', - context : { - leave, - comments, - approver: leave.get('approver'), - requester: leave.get('user'), - user: leave.get('user'), - } - }) - .then(emailObj => send_mail({ - from : config.get('application_sender_email'), - to : leave.get('user').email, - subject : emailObj.subject, - html : emailObj.body, + }) + ) + .then(email_obj => + send_mail({ + from: config.get('smtp:from'), + to: user.email, + subject: email_obj.subject, + html: email_obj.body + }) + .then(send_results => bluebird.resolve(send_results)) + .finally(() => user.record_email_addressed_to_me(email_obj)) + ) +} + +Email.prototype.promise_reset_password_email = function(args) { + const self = this + const user = args.user + const send_mail = self.get_send_email() + + return self + .promise_rendered_email_template({ + template_name: 'reset_password', + context: { + user + } }) - .then(() => leave.get('user').record_email_addressed_to_me(emailObj)) - ); + .then(email_obj => + send_mail({ + from: config.get('smtp:from'), + to: user.email, + subject: email_obj.subject, + html: email_obj.body + }) + .then(send_results => bluebird.resolve(send_results)) + .finally(() => user.record_email_addressed_to_me(email_obj)) + ) +} + +Email.prototype.promise_leave_request_cancel_emails = function(args) { + const self = this + const leave = args.leave + const send_mail = self.get_send_email() + + const promise_email_to_supervisor = comments => + self + .promise_rendered_email_template({ + template_name: 'leave_request_cancel_to_supervisor', + context: { + leave, + comments, + approver: leave.get('approver'), + requester: leave.get('user'), + user: leave.get('approver') + } + }) + .then(emailObj => + send_mail({ + from: config.get('smtp:from'), + to: leave.get('approver').email, + subject: emailObj.subject, + html: emailObj.body + }).finally(() => + leave.get('approver').record_email_addressed_to_me(emailObj) + ) + ) - return getCommentsForLeave({leave}) - .then(comments => bluebird.join( - promise_email_to_supervisor(comments), promise_email_to_requestor(comments), + const promise_email_to_requestor = comments => + self + .promise_rendered_email_template({ + template_name: 'leave_request_cancel_to_requestor', + context: { + leave, + comments, + approver: leave.get('approver'), + requester: leave.get('user'), + user: leave.get('user') + } + }) + .then(emailObj => + send_mail({ + from: config.get('smtp:from'), + to: leave.get('user').email, + subject: emailObj.subject, + html: emailObj.body + }).finally(() => + leave.get('user').record_email_addressed_to_me(emailObj) + ) + ) + + return getCommentsForLeave({ leave }).then(comments => + bluebird.join( + promise_email_to_supervisor(comments), + promise_email_to_requestor(comments), () => bluebird.resolve() - )); -}; + ) + ) +} -module.exports = Email; +module.exports = Email diff --git a/lib/error/index.js b/lib/error/index.js index f65824e99..f989ecacc 100644 --- a/lib/error/index.js +++ b/lib/error/index.js @@ -1,86 +1,81 @@ +'use strict' -"use strict"; - -const - Joi = require('joi'); +const Joi = require('joi') const schema_throw_user_error = [ - Joi.object() - .keys({ - system_error : Joi.string().required(), - user_error : Joi.string().required(), - }), + Joi.object().keys({ + system_error: Joi.string().required(), + user_error: Joi.string().required() + }), Joi.string() -]; +] function throw_user_error(args) { - const validate_args = Joi.validate(args, schema_throw_user_error); + const validate_args = Joi.validate(args, schema_throw_user_error) // Ensure all necesasry info was privided - if ( validate_args.error) { + if (validate_args.error) { // Tricky case here as we failed to rais exception, so log all data we have // and still rais generic exception console.log( - 'throw_user_error got invalid parameters: ' - + validate_args.annotate() - ); - console.dir(args); - throw new Error('Failed to throw user errors'); + 'throw_user_error got invalid parameters: ' + validate_args.annotate() + ) + console.dir(args) + throw new Error('Failed to throw user errors') } - let system_error_message, - user_error_message; + let system_error_message, user_error_message // Special case when user is lazy and specified generic error message to be // used for system and customer level - if ( typeof args === 'string' ) { - system_error_message = user_error_message = args; + if (typeof args === 'string') { + system_error_message = user_error_message = args } else { - system_error_message = args.system_error; - user_error_message = args.user_error; + system_error_message = args.system_error + user_error_message = args.user_error } - let exception = new Error( system_error_message ); + const exception = new Error(system_error_message) - if ( user_error_message ) { - exception.user_error_message = user_error_message; + if (user_error_message) { + exception.user_error_message = user_error_message } - exception.tom_error = true; + exception.tom_error = true - throw exception; + throw exception } function extract_system_error_message(error) { - if ( ! error ) { - return null; + if (!error) { + return null } - return error; + return error } function extract_user_error_message(error) { - if ( ! error ) { - return null; + if (!error) { + return null } if (typeof error === 'string') { - return error; + return error } - if ( error.hasOwnProperty( 'user_error_message' )) { - return error.user_error_message; + if (error.user_error_message) { + return error.user_error_message } - return 'N/A'; + return 'N/A' } module.exports = { - throw_user_error : throw_user_error, - extract_user_error_message : extract_user_error_message, - extract_system_error_message : extract_system_error_message, - - throwUserError : throw_user_error, - extractUserErrorMessage : extract_user_error_message, - extractSystemErrorMessage : extract_system_error_message, -}; + throw_user_error, + extract_user_error_message, + extract_system_error_message, + + throwUserError: throw_user_error, + extractUserErrorMessage: extract_user_error_message, + extractSystemErrorMessage: extract_system_error_message +} diff --git a/lib/middleware/ensure_user_is_admin.js b/lib/middleware/ensure_user_is_admin.js index 97d6d012d..d1c6c76b7 100644 --- a/lib/middleware/ensure_user_is_admin.js +++ b/lib/middleware/ensure_user_is_admin.js @@ -4,19 +4,18 @@ * In case of failure - redirects to the route. * * */ -"use strict"; +'use strict' -module.exports = function(req, res, next){ +module.exports = function(req, res, next) { + // User should be login to view settings pages + if (!req.user) { + return res.redirect_with_session(303, '/') + } - // User should be login to view settings pages - if ( !req.user ) { - return res.redirect_with_session(303, '/'); - } + // Only Admin users allowed to deal with settings pages + if (!req.user.is_admin()) { + return res.redirect_with_session(303, '/') + } - // Only Admin users allowed to deal with settings pages - if ( !req.user.is_admin() ) { - return res.redirect_with_session(303, '/'); - } - - next(); -}; + next() +} diff --git a/lib/middleware/flash_messages.js b/lib/middleware/flash_messages.js index e86c04939..ff961c021 100644 --- a/lib/middleware/flash_messages.js +++ b/lib/middleware/flash_messages.js @@ -19,51 +19,53 @@ * * */ -"use strict"; +'use strict' // Move flash object out of session and place it in to locals // so template is aware of it -module.exports = function(req, res, next){ - res.locals.flash = req.session.flash; - delete req.session.flash; +module.exports = function(req, res, next) { + res.locals.flash = req.session.flash + delete req.session.flash - // This is is a function that return custom function to be installed - // into session object as a method to add new message or array of - // messages. - var install_flash_array = function(key) { + // This is is a function that return custom function to be installed + // into session object as a method to add new message or array of + // messages. + function install_flash_array(key) { + return function(error_message) { + if (!this.flash) { + this.flash = {} + } + if (!Array.isArray(this.flash[key])) { + this.flash[key] = [] + } - return function(error_message){ - if ( ! this.flash ) { - this.flash = {}; - } - if ( ! Array.isArray( this.flash[key] ) ) { - this.flash[key] = []; - } + if (Array.isArray(error_message)) { + this.flash[key] = this.flash[key].concat(error_message) + } else { + this.flash[key].push(error_message) + } + } + } - if (Array.isArray(error_message)) { - this.flash[key] = this.flash[key].concat( error_message ); - } else { - this.flash[key].push( error_message ); - } - }; - }; + req.session.flash_error = install_flash_array('errors') + req.session.flash_message = install_flash_array('messages') - req.session.flash_error = install_flash_array('errors'); - req.session.flash_message = install_flash_array('messages'); + req.session.flash_has_errors = function() { + return ( + this.flash && + Array.isArray(this.flash.errors) && + this.flash.errors.length > 0 + ) + } - req.session.flash_has_errors = function(){ - return this.flash - && Array.isArray( this.flash.errors ) - && this.flash.errors.length > 0; - }; + req.session.keep_old = function() { + if (res.locals.flash) { + if (res.locals.flash.errors) this.flash_error(res.locals.flash.errors) + if (res.locals.flash.messages) { + this.flash_message(res.locals.flash.messages) + } + } + } - req.session.keep_old = function(){ - if (res.locals.flash) { - if (res.locals.flash.errors) this.flash_error( res.locals.flash.errors ); - if (res.locals.flash.messages) this.flash_message( res.locals.flash.messages ); - } - }; - - next(); - -}; + next() +} diff --git a/lib/middleware/session_aware_redirect.js b/lib/middleware/session_aware_redirect.js index 1c4e4fb8d..b434769ba 100644 --- a/lib/middleware/session_aware_redirect.js +++ b/lib/middleware/session_aware_redirect.js @@ -1,5 +1,4 @@ - -"use strict"; +'use strict' /* Because a bug in express-session middleware, when working @@ -14,21 +13,19 @@ TODO: Consider to completly substitute redirect function with new logic. */ -module.exports = function(req, res, next){ - - res.redirect_with_session = function(a,b){ - - if (arguments.length === 2) { - req.session.save(function(){ - res.redirect(a,b); - }); - } else { - req.session.save(function(){ - res.redirect(a); - }); - } - return true; - }; - - next(); -}; +module.exports = function(req, res, next) { + res.redirect_with_session = function(a, b) { + if (arguments.length === 2) { + req.session.save(() => { + res.redirect(a, b) + }) + } else { + req.session.save(() => { + res.redirect(a) + }) + } + return true + } + + next() +} diff --git a/lib/middleware/withSession.js b/lib/middleware/withSession.js index 9cc3d2e72..6390d1b01 100644 --- a/lib/middleware/withSession.js +++ b/lib/middleware/withSession.js @@ -1,47 +1,52 @@ +const session = require('express-session') +const SequelizeStore = require('connect-session-sequelize')(session.Store) -const session = require('express-session'); -const SequelizeStore = require('connect-session-sequelize')(session.Store); +const redis = require('redis') +const connectRedis = require('connect-redis') -const redis = require('redis'); -const connectRedis = require('connect-redis'); +const config = require('../config') -const {sessionStore: sessionStoreConfig} = require(__dirname + '/../../config/app.json') || {}; +const createSessionMiddleware = ({ sequelizeDb }) => { + let store -const createSessionMiddleware = ({ - sequelizeDb, -}) => { - let store; + const storageType = config.get('sessions:store') - if (sessionStoreConfig && sessionStoreConfig.useRedis) { - const RedisStore = connectRedis(session); - const {redisConnectionConfiguration = {}} = sessionStoreConfig; - const {host, port} = redisConnectionConfiguration; + if (storageType === 'redis') { + const RedisStore = connectRedis(session) + + const redisConfiguration = config.get('sessions:redis') + const { host, port } = redisConfiguration if (!(host && port)) { - throw new Error('Missing configuration for Redis to use with Sessions'); + throw new Error('Missing configuration for Redis to use with Sessions') } - const redisClient = redis.createClient({ host, port }); - - redisClient.on('error', function (err) { - throw new Error(`Failed to connect to Redis: ${err}`); - }); - redisClient.on('connect', function (err) { - console.log('Connected to redis successfully'); - }); - - store = new RedisStore({ client: redisClient }); + const redisClient = redis.createClient({ host, port }) + + redisClient.on('error', err => { + throw new Error(`Failed to connect to Redis: ${err}`) + }) + redisClient.on('connect', err => { + if (err) { + throw new Error(`Failed to connect to Redis: ${err}`) + } + console.log('Connected to redis successfully') + }) + + store = new RedisStore({ client: redisClient }) } else { if (!sequelizeDb) { - throw new Error('Database connection was not provided into Session store manager!'); + throw new Error( + 'Database connection was not provided into Session store manager!' + ) } - store = new SequelizeStore({ db: sequelizeDb }); + store = new SequelizeStore({ db: sequelizeDb }) } return session({ store, - secret: 'my dirty secret ;khjsdkjahsdajhasdam,nnsnad,', + secret: config.get('sessions:secret'), resave: false, - saveUninitialized: false, - }); -}; + saveUninitialized: false + }) +} -module.exports = createSessionMiddleware; \ No newline at end of file +module.exports = createSessionMiddleware diff --git a/lib/model/Report.js b/lib/model/Report.js index 6a90258ac..81f4a9a0c 100644 --- a/lib/model/Report.js +++ b/lib/model/Report.js @@ -1,110 +1,125 @@ +'use strict' -"use strict"; - -const - Promise = require('bluebird'), - moment = require('moment'); +const Promise = require('bluebird') +const moment = require('moment') const getUsersWithLeaves = ({ company, - startDate=company.get_today(), - endDate=company.get_today(), - departmentId=null - + startDate = company.get_today(), + endDate = company.get_today(), + department_id = null }) => { - - let result = company.sequelize.models.Company.scope('with_active_users').findOne({ - where : {id : company.id}, - }); - - result = result.then(company => Promise.resolve(company.users)); - - if (departmentId) { - result = result.then(users => Promise.resolve(users.filter(u => String(u.DepartmentId) === String(departmentId)))); + let result = company.sequelize.models.Company.scope( + 'with_active_users' + ).findOne({ + where: { id: company.id } + }) + + result = result.then(company => Promise.resolve(company.users)) + + if (department_id) { + result = result.then(users => + Promise.resolve( + users.filter(u => String(u.department_id) === String(department_id)) + ) + ) } - result = result.then(users => Promise.map(users, user => user.reload_with_leave_details({}), { concurrency : 10})); + result = result.then(users => + Promise.map(users, user => user.reload_with_leave_details({}), { + concurrency: 10 + }) + ) - const filter = filterLeaves({startDate, endDate}); + const filter = filterLeaves({ startDate, endDate }) - result = result.then( - users => Promise.map( + result = result.then(users => + Promise.map( users, - (user) => user.promise_my_active_leaves_ever() - .then(leaves => Promise.resolve(leaves.filter(filter))) - .then(leaves => Promise.resolve({user, leaves})), - { concurrency : 10 } + user => + user + .promise_my_active_leaves_ever() + .then(leaves => Promise.resolve(leaves.filter(filter))) + .then(leaves => Promise.resolve({ user, leaves })), + { concurrency: 10 } ) - ); + ) - result = result.then(report => report.map( - ({user, leaves}) => - ({ - user:{ - id:user.id, + result = result.then(report => + report.map(({ user, leaves }) => ({ + user: { + id: user.id, department: user.department.name, - email:user.email, - fullName:user.full_name(), + email: user.email, + fullName: user.full_name() }, - leaves : leaves.map(l => leaveIntoObject(l)), - }) - )); + leaves: leaves.map(l => leaveIntoObject(l)) + })) + ) - return result; -}; + return result +} -const filterLeaves = ({startDate, endDate}) => (leave) => { - const sd = moment.utc(leave.get_start_leave_day().date); +const filterLeaves = ({ startDate, endDate }) => leave => { + const sd = moment.utc(leave.get_start_leave_day().date) const ed = moment.utc(leave.get_end_leave_day().date) return ( - (sd.isSameOrAfter(startDate, 'day') && sd.isSameOrBefore(endDate, 'day')) - || + (sd.isSameOrAfter(startDate, 'day') && sd.isSameOrBefore(endDate, 'day')) || (ed.isSameOrAfter(startDate, 'day') && ed.isSameOrBefore(endDate, 'day')) - ); -}; + ) +} -const leaveIntoObject = (leave) => { +const leaveIntoObject = leave => { + const dateFormat = 'YYYY-MM-DD' - const dateFormat = 'YYYY-MM-DD'; - - const Leave = leave.sequelize.models.Leave; + const Leave = leave.sequelize.models.Leave const statusMap = { - [Leave.status_new()]: 'New', - [Leave.status_approved()]: 'Approved', - [Leave.status_rejected()]: 'Rejected', + [Leave.status_new()]: 'New', + [Leave.status_approved()]: 'Approved', + [Leave.status_rejected()]: 'Rejected', [Leave.status_pended_revoke()]: 'Pended Revoke', - [Leave.status_canceled()]: 'Canceled', - }; + [Leave.status_canceled()]: 'Canceled' + } return { - startDate: moment.utc(leave.get_start_leave_day().date).format(dateFormat), - endDate: moment.utc(leave.get_end_leave_day().date).format(dateFormat), + startDate: moment.utc(leave.get_start_leave_day().date).format(dateFormat), + endDate: moment.utc(leave.get_end_leave_day().date).format(dateFormat), dayPartStart: leave.day_part_start, - dayPartEnd: leave.day_part_end, - type: leave.leave_type ? leave.leave_type.name : 'N/A', + dayPartEnd: leave.day_part_end, + type: leave.leave_type ? leave.leave_type.name : 'N/A', deductedDays: leave.leave_type ? leave.get_deducted_days_number() : 'N/A', - approver: (leave.approver ? leave.approver.full_name() : 'N/A'), - approverId: leave.approverId, - status: statusMap[leave.status]||'Unknown', + approver: leave.approver ? leave.approver.full_name() : 'N/A', + approverId: leave.approver_id, + status: statusMap[leave.status] || 'Unknown', id: leave.id, - employeeId: leave.userId, - employeeFullName: (leave.user ? leave.user.full_name() : 'N/A'), - employeeLastName: (leave.user ? leave.user.lastname : 'N/A'), - departmentId: (leave.user ? leave.user.departmentId : null), - departmentName: (leave.user && leave.user.department ? leave.user.department.name : 'N/A'), + employeeId: leave.user_id, + employeeFullName: leave.user ? leave.user.full_name() : 'N/A', + employeeLastName: leave.user ? leave.user.lastname : 'N/A', + departmentId: leave.user ? leave.user.departmentId : null, + departmentName: + leave.user && leave.user.department ? leave.user.department.name : 'N/A', typeId: leave.leaveTypeId, - createdAt: moment.utc(leave.createdAt).format(dateFormat), - }; -}; - -const fetchLeavesForLeavesReport = async ({startDate, endDate, departmentId, leaveTypeId, actingUser, dbModel}) => { - let users = await dbModel.User.findAll({where: {companyId: actingUser.companyId}}); + createdAt: moment.utc(leave.createdAt).format(dateFormat) + } +} + +const fetchLeavesForLeavesReport = async ({ + startDate, + endDate, + departmentId, + leaveTypeId, + actingUser, + dbModel +}) => { + let users = await dbModel.User.findAll({ + where: { company_id: actingUser.company_id } + }) // If department was provided in filter out everyone who is not part of it if (departmentId) { - users = users.filter(u => `${u.DepartmentId}` === `${departmentId}`); + users = users.filter(u => `${u.DepartmentId}` === `${departmentId}`) } // The way how we fetch the leaves is not most efficient way (mildly speaking) @@ -112,48 +127,59 @@ const fetchLeavesForLeavesReport = async ({startDate, endDate, departmentId, lea // logic. Hopefully that would make the app more stable when we come to refactor // underlying code. - let leavesObjects = []; + const leavesObjects = [] - for (let user of users) { - await user.promise_schedule_I_obey(); - let usersLeaves = await user.getMyActiveLeavesForDateRange({dateStart: startDate, dateEnd: endDate}); + for (const user of users) { + await user.promise_schedule_I_obey() + let usersLeaves = await user.getMyActiveLeavesForDateRange({ + dateStart: startDate, + dateEnd: endDate + }) // Filter out redundant leave types if we are interesting in only particular one if (leaveTypeId) { - usersLeaves = usersLeaves.filter(l => `${l.leaveTypeId}` === `${leaveTypeId}`); + usersLeaves = usersLeaves.filter( + l => `${l.leave_type_id}` === `${leaveTypeId}` + ) } - leavesObjects.push(...usersLeaves); + leavesObjects.push(...usersLeaves) } // Get comments that were added to leaves, so we can enrich leave data later. // The idea is to get all LEAVE comments into memory as a map and then use it // to inject comment into each leave while cycling through them - const allComments = await dbModel.Comment.findAll({where: { - companyId: actingUser.companyId, - entityType: dbModel.Comment.getEntityTypeLeave(), - }}); + const allComments = await dbModel.Comment.findAll({ + where: { + company_id: actingUser.company_id, + entityType: dbModel.Comment.getEntityTypeLeave() + } + }) const commentsMap = allComments.reduce((m, c) => { - if (m[c.entityId] === undefined) { - m[c.entityId] = [c] + if (m[c.entity_id] === undefined) { + m[c.entity_id] = [c] } else { - m[c.entityId].push(c); + m[c.entity_id].push(c) } - return m; - }, {}); - - let leaves = leavesObjects.map(l => leaveIntoObject(l)); + return m + }, {}) - leaves = leaves.map(l => ({...l, comment: (commentsMap[l.id] ? commentsMap[l.id].map(({comment}) => comment).join('. ') : '')})); + let leaves = leavesObjects.map(l => leaveIntoObject(l)) - return {leaves}; -}; + leaves = leaves.map(l => ({ + ...l, + comment: commentsMap[l.id] + ? commentsMap[l.id].map(({ comment }) => comment).join('. ') + : '' + })) + return { leaves } +} module.exports = { getUsersWithLeaves, fetchLeavesForLeavesReport, - leaveIntoObject, -}; + leaveIntoObject +} diff --git a/lib/model/audit.js b/lib/model/audit.js index beeaaa7e3..527e6a7ae 100644 --- a/lib/model/audit.js +++ b/lib/model/audit.js @@ -1,38 +1,35 @@ +'use strict' -'use strict'; +const Bluebird = require('bluebird') +const Models = require('./db') -const - Bluebird = require('bluebird'), - Models = require('./db'); - -const getAuditCaptureForUser = ({byUser, forUser, newAttributes}) => () => { +const getAuditCaptureForUser = ({ byUser, forUser, newAttributes }) => () => { const attributeUpdates = Object.keys(newAttributes) .filter(k => String(newAttributes[k]) !== String(forUser[k])) - .map( - attribute => Models.Audit.create({ - companyId: byUser.companyId, - byUserId: byUser.id, - entityType: 'USER', - entityId: forUser.id, + .map(attribute => + Models.Audit.create({ + company_id: byUser.company_id, + by_user_id: byUser.id, + entity_type: 'USER', + entity_id: forUser.id, attribute, - oldValue: String(forUser[attribute]), - newValue: String(newAttributes[attribute]), + old_value: String(forUser[attribute]), + new_value: String(newAttributes[attribute]) }) - ); + ) - return Bluebird.map(attributeUpdates, f => f, {concurrency : 5}); -}; + return Bluebird.map(attributeUpdates, f => f, { concurrency: 5 }) +} -const getAudit = ({companyId}) => { - return Models.Audit.findAll({ - where : { - companyId, +const getAudit = ({ company_id }) => + Models.Audit.findAll({ + where: { + company_id }, - raw: true, + raw: true }) -}; module.exports = { getAuditCaptureForUser, - getAudit, -}; + getAudit +} diff --git a/lib/model/calculateCarryOverAllowance.js b/lib/model/calculateCarryOverAllowance.js index 7d784375f..69a5bdbc3 100644 --- a/lib/model/calculateCarryOverAllowance.js +++ b/lib/model/calculateCarryOverAllowance.js @@ -1,46 +1,64 @@ +'use strict' -'use strict'; +const moment = require('moment') +const Promise = require('bluebird') -const - moment = require('moment'), - Promise= require('bluebird'); +const calculateCarryOverAllowance = ({ users }) => { + const yearFrom = moment + .utc() + .add(-1, 'y') + .year() + const yearTo = moment.utc().year() -const calculateCarryOverAllowance = ({users}) => { + let flow = Promise.resolve(users) - const - yearFrom = moment.utc().add(-1, 'y').year(), - yearTo = moment.utc().year(); + flow = flow.then(users => + Promise.map( + users, + user => { + let carryOver + return Promise.resolve( + user.getCompany().then(c => (carryOver = c.carry_over)) + ) + .then(() => + user.reload_with_leave_details({ + year: moment.utc(yearFrom, 'YYYY') + }) + ) + .then(user => + user.promise_allowance({ + year: moment.utc(yearFrom, 'YYYY'), + now: moment.utc(yearFrom, 'YYYY').endOf('year'), + forceNow: true + }) + ) + .then(allowance => { + const carried_over_allowance = + carryOver === 0 + ? 0 + : Math.min( + allowance.number_of_days_available_in_allowance, + carryOver + ) - let flow = Promise.resolve(users); + return user.promise_to_update_carried_over_allowance({ + carried_over_allowance, + year: yearTo + }) + }) + .then(() => + console.log( + `Carried over unused allowance ${yearFrom} -> ${yearTo} for user ${ + user.id + }` + ) + ) + }, + { concurrency: 1 } + ) + ) - flow = flow.then(users => Promise.map( - users, - user => { - let carryOver; - return Promise.resolve(user.getCompany().then(c => carryOver = c.carry_over)) - .then(() => user.reload_with_leave_details({year:moment.utc(yearFrom, 'YYYY')})) - .then(user => user.promise_allowance({ - year: moment.utc(yearFrom, 'YYYY'), - now: moment.utc(yearFrom, 'YYYY').endOf('year'), - forceNow: true, - })) - .then(allowance => { + return flow +} - const carried_over_allowance = (carryOver === 0) - ? 0 - : Math.min(allowance.number_of_days_available_in_allowance, carryOver); - - return user.promise_to_update_carried_over_allowance({ - carried_over_allowance, - year: yearTo, - }); - }) - .then(() => console.log(`Carried over unused allowance ${yearFrom} -> ${yearTo} for user ${user.id}`)); - }, - {concurrency : 1} - )); - - return flow; -}; - -module.exports = { calculateCarryOverAllowance }; +module.exports = { calculateCarryOverAllowance } diff --git a/lib/model/calendar_month.js b/lib/model/calendar_month.js index 54c1a147b..bec99967e 100644 --- a/lib/model/calendar_month.js +++ b/lib/model/calendar_month.js @@ -1,334 +1,374 @@ +'use strict' -'use strict'; +const moment = require('moment') +const _ = require('underscore') -var moment = require('moment'), - _ = require('underscore'); +function CalendarMonth(day, args) { + const self = this + this.date = moment.utc(day).startOf('month') + this._leaves = {} + this._bank_holidays = {} -function CalendarMonth(day, args){ - var self = this; - this.date = moment.utc(day).startOf('month'); - this._leaves = {}; - this._bank_holidays = {}; + if (args && args.today) { + self.today = args.today + } else { + throw new Error( + 'CalendarMonth requires today - moment object that represents today' + ) + } + if (args) { + self._schedule = args.schedule + } - if (args && args.today) { - self.today = args.today; - } else { - throw new Error('CalendarMonth requires today - moment object that represents today'); - } + if (!self._schedule) { + throw new Error('CalendarMonth requires schedule') + } - if (args){ - self._schedule = args.schedule; - } + if (args && args.bank_holidays) { + var map = {} + args.bank_holidays.forEach(day => { + day = { + date: moment.utc(day.date), + name: day.name + } + map[day.date.clone().format(self.default_date_format())] = day + }) + self._bank_holidays = map + } - if ( ! self._schedule ) { - throw new Error('CalendarMonth requires schedule'); - } + if (args && args.leave_days) { + var map = {} + args.leave_days.forEach(day => { + const attribute = moment.utc(day.date).format(self.default_date_format()) + if (!map[attribute]) { + map[attribute] = day + } else if (map[attribute]) { + if (map[attribute].is_all_day_leave()) { + return + } - if (args && args.bank_holidays){ - var map = {}; - args.bank_holidays.forEach(function(day){ - day = { - date : moment.utc(day.date), - name : day.name, - }; - map[day.date.clone().format(self.default_date_format())] = day; - }); - self._bank_holidays = map; - } + if (day.is_all_day_leave()) { + map[attribute] = day + } else if (map[attribute].day_part !== day.day_part) { + // Merge leave types from both days into one in "map" + if (day.is_morning_leave()) { + map[attribute].morning_leave_type_id = day.morning_leave_type_id + } - if (args && args.leave_days){ - var map = {}; - args.leave_days.forEach(function(day){ - var attribute = moment.utc(day.date).format(self.default_date_format()); - if ( ! map[attribute] ) { - map[attribute] = day; - } else if ( map[attribute] ) { - - if (map[attribute].is_all_day_leave()) { - return; - } - - if (day.is_all_day_leave()){ - map[attribute] = day; - } else if ( map[attribute].day_part !== day.day_part ) { - - // Merge leave types from both days into one in "map" - if (day.is_morning_leave()) { - map[attribute].morning_leave_type_id = day.morning_leave_type_id; - } - - if ( day.is_afternoon_leave() ) { - map[attribute].afternoon_leave_type_id = day.afternoon_leave_type_id; - } - - map[attribute].pretend_to_be_full_day(); - } - } - }); - self._leaves = map; - } + if (day.is_afternoon_leave()) { + map[attribute].afternoon_leave_type_id = day.afternoon_leave_type_id + } - self._leave_types_map = {}; + map[attribute].pretend_to_be_full_day() + } + } + }) + self._leaves = map + } - if (args && args.leave_types) { - // Build leave types look up dictionary - args.leave_types.forEach(lt => self._leave_types_map[ lt.id ] = lt); - } + self._leave_types_map = {} - return; -}; + if (args && args.leave_types) { + // Build leave types look up dictionary + args.leave_types.forEach(lt => (self._leave_types_map[lt.id] = lt)) + } +} CalendarMonth.prototype.is_bank_holiday = function(day) { - return this._bank_holidays && this._bank_holidays.hasOwnProperty( - this.get_base_date().date(day).format(this.default_date_format()) - ); -}; + return ( + this._bank_holidays && + this._bank_holidays.hasOwnProperty( + this.get_base_date() + .date(day) + .format(this.default_date_format()) + ) + ) +} CalendarMonth.prototype.get_bank_holiday_name = function(day) { - const self = this; + const self = this - if ( ! self.is_bank_holiday(day) ) { - return null; + if (!self.is_bank_holiday(day)) { + return null } return this._bank_holidays[ - this.get_base_date().date(day).format(this.default_date_format()) - ].name; + this.get_base_date() + .date(day) + .format(this.default_date_format()) + ].name } CalendarMonth.prototype.is_leave = function(day) { - var leave_day = this._leaves[ - this.get_base_date().date(day).format(this.default_date_format()) - ]; + const leave_day = this._leaves[ + this.get_base_date() + .date(day) + .format(this.default_date_format()) + ] - return leave_day && leave_day.is_all_day_leave(); -}; + return leave_day && leave_day.is_all_day_leave() +} CalendarMonth.prototype.is_leave_morning = function(day) { - var leave_day = this._leaves[ - this.get_base_date().date(day).format(this.default_date_format()) - ]; - return this.is_leave(day) - || (leave_day && leave_day.is_morning_leave()); -}; + const leave_day = this._leaves[ + this.get_base_date() + .date(day) + .format(this.default_date_format()) + ] + return this.is_leave(day) || (leave_day && leave_day.is_morning_leave()) +} CalendarMonth.prototype.is_leave_afternoon = function(day) { - var leave_day = this._leaves[ - this.get_base_date().date(day).format(this.default_date_format()) - ]; + const leave_day = this._leaves[ + this.get_base_date() + .date(day) + .format(this.default_date_format()) + ] - return this.is_leave(day) - || (leave_day && leave_day.is_afternoon_leave()); -}; + return this.is_leave(day) || (leave_day && leave_day.is_afternoon_leave()) +} -CalendarMonth.prototype.get_leave_obj = function(day){ - var leave_day = this._leaves[ - this.get_base_date().date(day).format(this.default_date_format()) - ]; +CalendarMonth.prototype.get_leave_obj = function(day) { + const leave_day = this._leaves[ + this.get_base_date() + .date(day) + .format(this.default_date_format()) + ] if (leave_day && leave_day.leave) { - return leave_day.leave; + return leave_day.leave } else { - return null; + return null } -}; - -CalendarMonth.prototype.is_new_leave = function(day){ - var leave_day = this._leaves[ - this.get_base_date().date(day).format(this.default_date_format()) - ]; +} - return leave_day && leave_day.leave && leave_day.leave.is_new_leave(); -}; +CalendarMonth.prototype.is_new_leave = function(day) { + const leave_day = this._leaves[ + this.get_base_date() + .date(day) + .format(this.default_date_format()) + ] -CalendarMonth.prototype.is_approved_leave = function(day){ - var leave_day = this._leaves[ - this.get_base_date().date(day).format(this.default_date_format()) - ]; + return leave_day && leave_day.leave && leave_day.leave.is_new_leave() +} - return leave_day && leave_day.leave && leave_day.leave.is_approved_leave(); -}; +CalendarMonth.prototype.is_approved_leave = function(day) { + const leave_day = this._leaves[ + this.get_base_date() + .date(day) + .format(this.default_date_format()) + ] -CalendarMonth.prototype.get_morning_leave_type_id = function(day){ - let - self = this, - leave_day = self._leaves[ - self.get_base_date().date(day).format(self.default_date_format()) - ]; + return leave_day && leave_day.leave && leave_day.leave.is_approved_leave() +} - if ( ! leave_day ) { - return null; +CalendarMonth.prototype.get_morning_leave_type_id = function(day) { + const self = this + const leave_day = + self._leaves[ + self + .get_base_date() + .date(day) + .format(self.default_date_format()) + ] + + if (!leave_day) { + return null } - return leave_day.get_morning_leave_type_id(); -}; - -CalendarMonth.prototype.get_afternoon_leave_type_id = function(day){ - let - self = this, - leave_day = self._leaves[ - self.get_base_date().date(day).format(self.default_date_format()) - ]; + return leave_day.get_morning_leave_type_id() +} - if ( ! leave_day ) { - return null; +CalendarMonth.prototype.get_afternoon_leave_type_id = function(day) { + const self = this + const leave_day = + self._leaves[ + self + .get_base_date() + .date(day) + .format(self.default_date_format()) + ] + + if (!leave_day) { + return null } - return leave_day.get_afternoon_leave_type_id(); -}; + return leave_day.get_afternoon_leave_type_id() +} -CalendarMonth.prototype.default_date_format = function(){ - return 'YYYY-MM-DD'; -}; +CalendarMonth.prototype.default_date_format = function() { + return 'YYYY-MM-DD' +} CalendarMonth.prototype.how_many_days = function() { - return this.date.daysInMonth(); -}; - -CalendarMonth.prototype.get_base_date = function(){ - return this.date.clone(); -}; - -CalendarMonth.prototype._week_day_map = function(){ - return { 0:7, 1:1, 2:2, 3:3, 4:4, 5:5, 6:6 }; -}; - -CalendarMonth.prototype.week_day = function(){ - return this._week_day_map()[ this.date.day() ]; -}; - -CalendarMonth.prototype.how_many_blanks_at_the_start = function(){ - return this.week_day() - 1; -}; - -CalendarMonth.prototype.how_many_blanks_at_the_end = function(){ - return 7 - this._week_day_map()[ this.get_base_date().endOf('month').day() ]; -}; - -CalendarMonth.prototype.is_weekend = function(day){ - return ! this._schedule.is_it_working_day({ - day : this.get_base_date().date(day), - }); -}; - -CalendarMonth.prototype.is_current_day = function(day){ - return this.get_base_date().date(day).format( this.default_date_format() ) - === - this.today.format( this.default_date_format() ); -}; - -CalendarMonth.prototype.as_for_template = function(){ - let - self = this, - weeks = [], - week = []; - - for( var i=0; i= 7) { - weeks.push( week ); - week = []; - } + if (self.is_current_day(i)) { + day.is_current_day = true } - for( var i=0; i= 7) { + weeks.push(week) + week = [] } + } - weeks.push(week); + for (let i = 0; i < self.how_many_blanks_at_the_end(); i++) { + week.push({ val: '' }) + } + + weeks.push(week) - return { - month : self.get_base_date().format('MMMM'), - moment: self.get_base_date(), - weeks : weeks, - }; -}; + return { + month: self.get_base_date().format('MMMM'), + moment: self.get_base_date(), + weeks + } +} -CalendarMonth.prototype.as_for_team_view = function(){ - var me = this, - for_calendar_structure = this.as_for_template(); +CalendarMonth.prototype.as_for_team_view = function() { + const me = this + const for_calendar_structure = this.as_for_template() // remove empty days, those staying for empty cells in calendar - var days = _.filter( + const days = _.filter( _.flatten(for_calendar_structure.weeks), - function(day){ - return !! day.val - } - ); - - _.each(days, function(day){ - day.moment = me.get_base_date().date(day.val); - }); + day => !!day.val + ) - return days; + _.each(days, day => { + day.moment = me.get_base_date().date(day.val) + }) -}; + return days +} -module.exports = CalendarMonth; +module.exports = CalendarMonth diff --git a/lib/model/comment.js b/lib/model/comment.js index a40da0c8f..706cfcf76 100644 --- a/lib/model/comment.js +++ b/lib/model/comment.js @@ -1,31 +1,27 @@ +'use strict' -'use strict'; +const Bluebird = require('bluebird') +const Models = require('./db') -const - Bluebird = require('bluebird'), - Models = require('./db'); - -const commentLeave = ({leave, comment, companyId}) => { - return Models.Comment.create({ - entityType: Models.Comment.getEntityTypeLeave(), - entityId: leave.id, +const commentLeave = ({ leave, comment, company_id }) => + Models.Comment.create({ + entity_type: Models.Comment.getEntityTypeLeave(), + entity_id: leave.id, comment, - companyId, - byUserId: leave.userId, - }); -}; + company_id, + by_user_id: leave.user_id + }) -const getCommentsForLeave = ({leave}) => { - return Models.Comment.findAll({ +const getCommentsForLeave = ({ leave }) => + Models.Comment.findAll({ raw: true, - where : { - entityType: Models.Comment.getEntityTypeLeave(), - entityId: leave.id, - }, - }); -}; + where: { + entity_type: Models.Comment.getEntityTypeLeave(), + entity_id: leave.id + } + }) module.exports = { commentLeave, - getCommentsForLeave, -}; + getCommentsForLeave +} diff --git a/lib/model/company/exporter/index.js b/lib/model/company/exporter/index.js index d8c10a7c2..6aedd082e 100644 --- a/lib/model/company/exporter/index.js +++ b/lib/model/company/exporter/index.js @@ -1,66 +1,64 @@ +'use strict' -'use strict'; +const Joi = require('joi') +const Promise = require('bluebird') +const CompanySummary = require('./summary') -const - Joi = require('joi'), - Promise = require('bluebird'), - CompanySummary = require('./summary'); - -const - constructor_schema = Joi.object().required() - .keys({ - dbSchema : Joi.object().required(), - }), - schemaPromiseCompanySummary = Joi.object().required() - .keys({ - company : Joi.object().required(), - }); +const constructor_schema = Joi.object() + .required() + .keys({ + dbSchema: Joi.object().required() + }) +const schemaPromiseCompanySummary = Joi.object() + .required() + .keys({ + company: Joi.object().required() + }) class CompanyExporter { constructor(args) { args = Joi.attempt( args, constructor_schema, - "Faled to instantiate new companyExporter due to arguments validation" - ); + 'Faled to instantiate new companyExporter due to arguments validation' + ) - this._db_model = args.dbSchema; + this._db_model = args.dbSchema } get dbModel() { - return this._db_model; + return this._db_model } promiseCompanySummary(args) { args = Joi.attempt( args, schemaPromiseCompanySummary, - "Failed to get company summary die to validation errors" - ); + 'Failed to get company summary die to validation errors' + ) - let - self = this, - company = args.company; + const self = this + const company = args.company - return Promise - .join( - self.dbModel.Company - .scope('with_simple_departments', 'with_leave_types') - .findOne({ - where : { id : company.id }, - }), - self.dbModel.User - .scope('with_simple_leaves') - .findAll({ - where : { companyId : company.id } - }), - (company, users) => Promise.resolve( new CompanySummary({ - company : company, - users : users, - })) - ); + return Promise.join( + self.dbModel.Company.scope( + 'with_simple_departments', + 'with_leave_types' + ).findOne({ + where: { id: company.id } + }), + self.dbModel.User.scope('with_simple_leaves').findAll({ + where: { company_id: company.id } + }), + (company, users) => + Promise.resolve( + new CompanySummary({ + company, + users + }) + ) + ) } - } -module.exports = CompanyExporter; +module.exports = CompanyExporter diff --git a/lib/model/company/exporter/summary.js b/lib/model/company/exporter/summary.js index 6eeeb5ff3..55cedece0 100644 --- a/lib/model/company/exporter/summary.js +++ b/lib/model/company/exporter/summary.js @@ -1,104 +1,119 @@ +'use strict' -'use strict'; +const Promise = require('bluebird') +const CSV = Promise.promisifyAll(require('csv')) +const moment = require('moment') +const Joi = require('joi') -const - Promise = require('bluebird'), - CSV = Promise.promisifyAll(require('csv')), - moment = require('moment'), - Joi = require('joi'); +const schema_constructor = Joi.object() + .required() + .keys({ + company: Joi.object().required(), + users: Joi.array().required() + }) -const - schema_constructor = Joi.object().required().keys({ - company : Joi.object().required(), - users : Joi.array().required(), - }); - -const { sorter } = require("../../../util"); +const { sorter } = require('../../../util') class CompanySummary { constructor(args) { args = Joi.attempt( args, schema_constructor, - "Failed to in stantiate companySummary due to validation" - ); + 'Failed to in stantiate companySummary due to validation' + ) - this._company = args.company; - this._users = args.users; + this._company = args.company + this._users = args.users } - get company() { return this._company } - get users() { return this._users } + get company() { + return this._company + } + + get users() { + return this._users + } as_csv_data() { - let - self = this, - results = [], - date_format = self.company.get_default_date_format(), - departmentsMap = {}, - leaveTypesMap = {}; + const self = this + const results = [] + const date_format = self.company.get_default_date_format() + const departmentsMap = {} + const leaveTypesMap = {} // Fill departments map - self.company.departments.forEach(d => departmentsMap[d.id] = d); + self.company.departments.forEach(d => (departmentsMap[d.id] = d)) // Fill leave types map - self.company.leave_types.forEach( lt => leaveTypesMap[ lt.id ] = lt ); + self.company.leave_types.forEach(lt => (leaveTypesMap[lt.id] = lt)) // Put headers results.push([ - 'Department', 'Last name', 'Name', 'Email address', - 'Type of absence', 'Started at', 'Date type', 'Ended at', 'Date type' - ]); + 'Department', + 'Last name', + 'Name', + 'Email address', + 'Type of absence', + 'Started at', + 'Date type', + 'Ended at', + 'Date type' + ]) self.users // Sort users by departments and by last names - .sort((a, b) => ( - sorter( - departmentsMap[ a.DepartmentId ].name, - departmentsMap[ b.DepartmentId ].name - ) - || - sorter(a.lastname, b.lastname) - )) + .sort( + (a, b) => + sorter( + departmentsMap[a.department_id].name, + departmentsMap[b.department_id].name + ) || sorter(a.lastname, b.lastname) + ) // Get a row per every leave - .forEach(u => u.my_leaves.forEach(l => { - - const start_date = moment(l.date_start).format(date_format); - const end_date = moment(l.date_end).format(date_format); - - const startDatePart = l.does_start_half_morning() ? 'Morning' - : l.does_start_half_afternoon() ? 'Afternoon' - : 'All Day'; - - const endDatePart = start_date === end_date ? startDatePart - : l.does_end_half_morning() ? 'Morning' - : l.does_end_half_afternoon() ? 'Afternoon' - : 'All Day'; - - results.push([ - departmentsMap[ u.DepartmentId ].name, - u.lastname, - u.name, - u.email, - leaveTypesMap[ l.leaveTypeId ].name, - start_date, - startDatePart, - end_date, - endDatePart, - ]) - })); - - return results; + .forEach(u => + u.my_leaves.forEach(l => { + const start_date = moment(l.date_start).format(date_format) + const end_date = moment(l.date_end).format(date_format) + + const startDatePart = l.does_start_half_morning() + ? 'Morning' + : l.does_start_half_afternoon() + ? 'Afternoon' + : 'All Day' + + const endDatePart = + start_date === end_date + ? startDatePart + : l.does_end_half_morning() + ? 'Morning' + : l.does_end_half_afternoon() + ? 'Afternoon' + : 'All Day' + + results.push([ + departmentsMap[u.department_id].name, + u.lastname, + u.name, + u.email, + leaveTypesMap[l.leave_type_id].name, + start_date, + startDatePart, + end_date, + endDatePart + ]) + }) + ) + + return results } promise_as_csv_string() { - const self = this; + const self = this - return Promise - .resolve( self.as_csv_data() ) - .then( data => CSV.stringifyAsync( data ) ) + return Promise.resolve(self.as_csv_data()).then(data => + CSV.stringifyAsync(data) + ) } - } -module.exports = CompanySummary; +module.exports = CompanySummary diff --git a/lib/model/company/remover.js b/lib/model/company/remover.js index 045595c5e..7a134e77a 100644 --- a/lib/model/company/remover.js +++ b/lib/model/company/remover.js @@ -1,79 +1,88 @@ +'use strict' -"use strict"; - -const - Joi = require('joi'), - Promise = require('bluebird'), - Exception = require('../../error'), - Models = require('../db'); - -const - schemaPromiseToRemove = Joi.object().required().keys({ - company : Joi.object().required(), //.type(Models.Company.constructor), - byUser : Joi.object().required(), //.type(Models.User.constructor), - confirmName : Joi.string().required().trim(), - }); +const Joi = require('joi') +const Promise = require('bluebird') +const Exception = require('../../error') +const Models = require('../db') +const schemaPromiseToRemove = Joi.object() + .required() + .keys({ + company: Joi.object().required(), // .type(Models.Company.constructor), + byUser: Joi.object().required(), // .type(Models.User.constructor), + confirmName: Joi.string() + .required() + .trim() + }) class CompanyRemover { - - static promiseToRemove(args){ - + static promiseToRemove(args) { args = Joi.attempt( args, schemaPromiseToRemove, - "Param validation failed for promiseToRemove" - ); + 'Param validation failed for promiseToRemove' + ) - const - company = args.company, - byUser = args.byUser, - confirmName = args.confirmName; + const company = args.company + const byUser = args.byUser + const confirmName = args.confirmName // Ensure that confirm name is correct - let normalizedNames = [company.name, confirmName] + const normalizedNames = [company.name, confirmName] .map(s => s.trim()) .map(s => s.replace(/\s+/g, '')) - .map(s => s.toUpperCase()); + .map(s => s.toUpperCase()) if (normalizedNames[0] !== normalizedNames[1]) { Exception.throw_user_error({ - system_error : `Confirmed name does not match one on company record: ${ normalizedNames.join(', ') }`, - user_error : `Provided name confirmation does not match company one`, - }); + system_error: `Confirmed name does not match one on company record: ${normalizedNames.join( + ', ' + )}`, + user_error: 'Provided name confirmation does not match company one' + }) } - return Models.User + return ( + Models.User - // Ensure user belongs to current combany and is admin - .count({ - where : { - id : byUser.id, - companyId : company.id, - admin : true, - } - }) - .then(count => { - if ( count === 0) { - Exception.throw_user_error({ - system_error : `An attempt to remove company [${company.id}] by unrelated user [${byUser.id }]`, - user_error : `User does not have permissions to remove company`, - }); - } - return Promise.resolve(1); - }) + // Ensure user belongs to current company and is admin + .count({ + where: { + id: byUser.id, + company_id: company.id, + admin: true + } + }) + .then(count => { + if (count === 0) { + Exception.throw_user_error({ + system_error: `An attempt to remove company [${ + company.id + }] by unrelated user [${byUser.id}]`, + user_error: 'User does not have permissions to remove company' + }) + } + return Promise.resolve(1) + }) - // Remove company record and all related records - // (we do not really remove all data, just the sensitive information) - // .. delete email audit - .then(() => Models.EmailAudit.destroy({ where : { company_id : company.id } })) - // Remove all leaves for related users - .then(() => company.getUsers().map(u => Models.Leave.destroy({ where : { userId : u.id }}))) - // Remove all users - .then(() => Models.User.destroy({where : {companyId : company.id} })) - // Remove company record - .then(() => company.destroy()); + // Remove company record and all related records + // (we do not really remove all data, just the sensitive information) + // .. delete email audit + .then(() => + Models.EmailAudit.destroy({ where: { company_id: company.id } }) + ) + // Remove all leaves for related users + .then(() => + company + .getUsers() + .map(u => Models.Leave.destroy({ where: { user_id: u.id } })) + ) + // Remove all users + .then(() => Models.User.destroy({ where: { company_id: company.id } })) + // Remove company record + .then(() => company.destroy()) + ) } } -module.exports = CompanyRemover; +module.exports = CompanyRemover diff --git a/lib/model/db/audit.js b/lib/model/db/audit.js index b484937dd..8ff59563b 100644 --- a/lib/model/db/audit.js +++ b/lib/model/db/audit.js @@ -1,57 +1,57 @@ +'use strict' -'use strict'; - -module.exports = function(sequelize, DataTypes){ - - const Audit = sequelize.define("Audit", { - entityType: { - type: DataTypes.STRING, - allowNull: false, - comment: 'Type of the entity which change is tracked. E.g. USER, LEAVE etc', - }, - entityId: { - type: DataTypes.INTEGER, - allowNull: false, - comment: 'ID of the entity defined by entityType', - }, - attribute: { - type: DataTypes.STRING, - allowNull: false, - comment: 'Attribute of the entity which chnage is to be recorded', - }, - oldValue: { - type: DataTypes.STRING, - allowNull: true, - comment: 'Old value converted to STRING', - }, - newValue: { - type: DataTypes.STRING, - allowNull: true, - comment: 'New value converted to STRING', - }, - }, { - underscored : true, - freezeTableName : true, - timestamps : true, - createdAt : 'at', - updatedAt : false, - tableName : 'audit', - - classMethods : { - associate : (models) => { - Audit.belongsTo(models.Company, { - as : 'company', - foreignKey : 'companyId', - }); - - Audit.belongsTo(models.User, { - as: 'byUser', - foreignKey: 'byUserId', - }); +module.exports = function(sequelize, DataTypes) { + const Audit = sequelize.define( + 'Audit', + { + entity_type: { + type: DataTypes.STRING, + allowNull: false, + comment: + 'Type of the entity which change is tracked. E.g. USER, LEAVE etc' + }, + entity_id: { + type: DataTypes.INTEGER, + allowNull: false, + comment: 'ID of the entity defined by entityType' }, + attribute: { + type: DataTypes.STRING, + allowNull: false, + comment: 'Attribute of the entity which change is to be recorded' + }, + old_value: { + type: DataTypes.STRING, + allowNull: true, + comment: 'Old value converted to STRING' + }, + new_value: { + type: DataTypes.STRING, + allowNull: true, + comment: 'New value converted to STRING' + } }, + { + underscored: true, + freezeTableName: true, + timestamps: true, + createdAt: 'at', + updatedAt: false, + tableName: 'audit' + } + ) + + Audit.associate = models => { + Audit.belongsTo(models.Company, { + as: 'company', + foreignKey: 'company_id' + }) - }); + Audit.belongsTo(models.User, { + as: 'byUser', + foreignKey: { name: 'by_user_id', allowNull: true } + }) + } - return Audit; -}; + return Audit +} diff --git a/lib/model/db/bank_holiday.js b/lib/model/db/bank_holiday.js index 46a20203f..ffa471184 100644 --- a/lib/model/db/bank_holiday.js +++ b/lib/model/db/bank_holiday.js @@ -1,72 +1,75 @@ -"use strict"; +'use strict' -var moment = require('moment'), -_ = require('underscore'), -config = require('../../config'); +const moment = require('moment') +const _ = require('underscore') +const config = require('../../config') module.exports = function(sequelize, DataTypes) { - var BankHoliday = sequelize.define("BankHoliday", { - // TODO add validators! - name : { - type : DataTypes.STRING, - allowNull : false - }, - date : { - type : DataTypes.DATE, - allowNull : false, - }, - }, { - indexes : [ - { - fields : ['companyId'], - } - ], - classMethods: { - associate : function( models ) { - BankHoliday.belongsTo(models.Company, {as : 'company'}); - }, + const BankHoliday = sequelize.define( + 'BankHoliday', + { + // TODO add validators! + name: { + type: DataTypes.STRING, + allowNull: false + }, + date: { + type: DataTypes.DATE, + allowNull: false + } + }, + { + underscored: true, + indexes: [ + { + fields: ['company_id'] + } + ] + } + ) - generate_bank_holidays : function(args){ - var company = args.company, - country_code = args.country_code; + BankHoliday.associate = function(models) { + BankHoliday.belongsTo(models.Company, { + as: 'company', + foreignKey: { name: 'company_id', allowNull: false } + }) + } - var bank_holidays = [ - { - name : 'Early May bank holiday', - date : '2015-05-04', - companyId : company.id, - }, - ]; + BankHoliday.generate_bank_holidays = function(args) { + const company = args.company + const country_code = args.country_code - var config_countries = config.get('countries'); + let bank_holidays = [ + { + name: 'Early May bank holiday', + date: '2015-05-04', + company_id: company.id + } + ] - if ( - config_countries.hasOwnProperty( country_code ) - && config_countries[ country_code ].hasOwnProperty('bank_holidays') - && config_countries[ country_code ].bank_holidays.length > 0 - ) { - bank_holidays = _.map( - config_countries[ country_code ].bank_holidays, - function(bh){ - return { - name : bh.name, - date : bh.date, - companyId : company.id, - }; - } - ); - } + const config_countries = config.get('countries') - return BankHoliday.bulkCreate(bank_holidays); - }, - }, + if ( + config_countries.country_code && + config_countries[country_code].bank_holidays && + config_countries[country_code].bank_holidays.length > 0 + ) { + bank_holidays = _.map( + config_countries[country_code].bank_holidays, + bh => ({ + name: bh.name, + date: bh.date, + company_id: company.id + }) + ) + } - instanceMethods : { - get_pretty_date : function(){ - return moment.utc(this.date).format('YYYY-MM-DD'); - }, - } - }); + return BankHoliday.bulkCreate(bank_holidays) + } + + BankHoliday.prototype.get_pretty_date = function() { + return moment.utc(this.date).format('YYYY-MM-DD') + } - return BankHoliday; -}; + return BankHoliday +} diff --git a/lib/model/db/comment.js b/lib/model/db/comment.js index 55e384556..ce360a7ab 100644 --- a/lib/model/db/comment.js +++ b/lib/model/db/comment.js @@ -1,46 +1,48 @@ - -'use strict'; +'use strict' module.exports = (sequelize, DataTypes) => { - const Comment = sequelize.define('Comment', { - entityType: { - type: DataTypes.STRING, - allowNull: false, - comment: 'Type of entity current comments belongs to', - }, - entityId: { - type: DataTypes.INTEGER, - allowNull: false, - comment: 'Reference ID for entity current comment belongs to', - }, - comment: { - type: DataTypes.STRING, - allowNull: false, - comment: 'The value of comment', + const Comment = sequelize.define( + 'Comment', + { + entity_type: { + type: DataTypes.STRING, + allowNull: false, + comment: 'Type of entity current comments belongs to' + }, + entity_id: { + type: DataTypes.INTEGER, + allowNull: false, + comment: 'Reference ID for entity current comment belongs to' + }, + comment: { + type: DataTypes.TEXT, + allowNull: false, + comment: 'The value of comment' + } }, - },{ - underscored : true, - freezeTableName : true, - timestamps : true, - createdAt : 'at', - updatedAt : false, - tableName : 'comment', + { + underscored: true, + freezeTableName: true, + timestamps: true, + createdAt: 'at', + updatedAt: false, + tableName: 'comments' + } + ) - classMethods : { - associate : (models) => { - Comment.belongsTo(models.Company, { - as : 'company', - foreignKey : 'companyId', - }); + Comment.associate = models => { + Comment.belongsTo(models.Company, { + as: 'company', + foreignKey: { name: 'company_id', allowNull: false } + }) - Comment.belongsTo(models.User, { - as: 'byUser', - foreignKey: 'byUserId', - }); - }, - getEntityTypeLeave: () => 'LEAVE', - }, - }); + Comment.belongsTo(models.User, { + as: 'byUser', + foreignKey: { name: 'by_user_id', allowNull: false } + }) + } + + Comment.getEntityTypeLeave = () => 'LEAVE' - return Comment; -}; + return Comment +} diff --git a/lib/model/db/company.js b/lib/model/db/company.js index 8eedceb92..7bda9adf4 100644 --- a/lib/model/db/company.js +++ b/lib/model/db/company.js @@ -1,429 +1,513 @@ -"use strict"; - -const - Promise = require("bluebird"), - LdapAuth = require('ldapauth-fork'), - moment = require('moment'), - moment_tz = require('moment-timezone'), - _ = require('underscore'), - uuidv4 = require('uuid/v4'); -const { sorter } = require("../../util"); +'use strict' +const Promise = require('bluebird') +const LdapAuth = require('ldapauth-fork') +const moment = require('moment') +const moment_tz = require('moment-timezone') +const _ = require('underscore') +const uuidv4 = require('uuid/v4') +const { sorter } = require('../../util') module.exports = function(sequelize, DataTypes) { - var Company = sequelize.define("Company", { - // TODO add validators! - name : { - type : DataTypes.STRING, - allowNull : false - }, - country : { - type : DataTypes.STRING, - allowNull : false - }, - start_of_new_year : { - type : DataTypes.INTEGER, - allowNull : false - }, - share_all_absences : { - type : DataTypes.BOOLEAN, - allowNull : false, - defaultValue : false, - }, - is_team_view_hidden : { - type : DataTypes.BOOLEAN, - allowNull : false, - defaultValue : false, - comment : "Determise if Team View is hidden for non-admin users", - }, - ldap_auth_enabled : { - type : DataTypes.BOOLEAN, - allowNull : false, - defaultValue : false, - }, - ldap_auth_config : { - type : DataTypes.STRING, - allowNull : true, - set : function(val){ - if (! val || typeof val !== 'object' ) { - val = JSON.stringify({}); + const Company = sequelize.define( + 'Company', + { + // TODO add validators! + name: { + type: DataTypes.STRING, + allowNull: false + }, + country: { + type: DataTypes.STRING, + allowNull: false + }, + start_of_new_year: { + type: DataTypes.INTEGER, + allowNull: false + }, + share_all_absences: { + type: DataTypes.BOOLEAN, + allowNull: false, + defaultValue: false + }, + is_team_view_hidden: { + type: DataTypes.BOOLEAN, + allowNull: false, + defaultValue: false, + comment: 'Determise if Team View is hidden for non-admin users' + }, + ldap_auth_enabled: { + type: DataTypes.BOOLEAN, + allowNull: false, + defaultValue: false + }, + ldap_auth_config: { + type: DataTypes.TEXT, + allowNull: true, + set: function(val) { + if (!val || typeof val !== 'object') { + val = JSON.stringify({}) } - this.setDataValue( 'ldap_auth_config', JSON.stringify(val) ); + this.setDataValue('ldap_auth_config', JSON.stringify(val)) }, - get : function(){ - var val = this.getDataValue('ldap_auth_config'); + get: function() { + let val = this.getDataValue('ldap_auth_config') try { - val = JSON.parse(val); - } catch(err) { + val = JSON.parse(val) + } catch (err) { console.error( 'Faled to parse the LDAP settings saved in company %s. Error: %s', - this.id, err - ); - val = {}; + this.id, + err + ) + val = {} } - return val; - }, - }, - date_format : { - type : DataTypes.STRING, - allowNull : false, - defaultValue : 'YYYY-MM-DD', - }, - company_wide_message : { - type : DataTypes.TEXT, - allowNull : true, - defaultValue : null, - comment : 'Message shown to all users that belong to current company', - }, - mode : { - type : DataTypes.INTEGER, - allowNull : false, - defaultValue : 1, - comment : "Indicate which mode the company account is in.", - }, - timezone : { - type : DataTypes.TEXT, - allowNull : true, - defaultValue : 'Europe/London', - comment : 'Timezone current company is located in', - }, - integration_api_enabled : { - type: DataTypes.BOOLEAN, - allowNull: false, - defaultValue: false, - }, - integration_api_token : { - type : DataTypes.UUID, - allowNull : false, - defaultValue : () => uuidv4(), - comment : "Indicate which mode the company account is in.", - }, - carry_over : { - type : DataTypes.INTEGER, - allowNull : false, - defaultValue : 0, - comment : "Defines how may remaining days from allowance are carried over to the next year.", - }, - }, { - - indexes : [ - { - fields : ['id'], - } - ], - - classMethods: { - - associate : models => { - Company.hasMany(models.Department, { - as : 'departments', - foreignKey : 'companyId', - }); - Company.hasMany(models.User, { - as : 'users', - foreignKey : 'companyId', - }); - Company.hasMany(models.BankHoliday, { - as : 'bank_holidays', - foreignKey : 'companyId', - }); - Company.hasMany(models.LeaveType, { - as : 'leave_types', - foreignKey : 'companyId', - }); - Company.hasMany(models.EmailAudit, { - as : 'audit_emails', - foreignKey : 'company_id', - }); - Company.hasMany(models.Audit, { - as: 'audit', - foreignKey: 'companyId', - }); - }, - - loadScope : function( models ) { - - Company.addScope( - 'with_all_users', - { - include : [ - { model : models.User, as : 'users' }, - ] - } - ); - - Company.addScope( - 'with_audit', - { - include : [{ model: models.Audit, as: 'audit' }], - } - ); - - Company.addScope( - 'with_active_users', - // The scope needs to be dynamic as the criteria for active users is based - // on current date, which could be buggy if left static - function() { - return { include : [{ - model : models.User, - as : 'users', - where : models.User.get_active_user_filter(), - }] - } - } - ); - - Company.addScope( - 'order_by_active_users', - { - order : [ - [{model : models.User, as : 'users'}, 'lastname'] - ] - } - ); - - Company.addScope( - 'with_simple_departments', - { - include : [ - { model : models.Department, as : 'departments' } - ] - } - ); - - Company.addScope( - 'with_bank_holidays', - { - include : [{ model : models.BankHoliday, as : 'bank_holidays' }], - } - ); - - Company.addScope( - 'order_by_bank_holidays', - { - order: [ - [{model: models.BankHoliday, as: 'bank_holidays'}, 'date'] - ] - } - ); - - Company.addScope( - 'with_leave_types', - { - include : [{ model : models.LeaveType, as : 'leave_types' }] - } - ); - }, - - scopeAssociate : function( models ) { - // Following code is here for reference only: to help declaring scopped - // associations in future. The approach is not suitable for active users - // bacause of its dynamic nature - we need to have up to date "now", which - // does not work nicely with accociations as they are installed once at the - // applicaiton start time, and if the app will be running for more than one - // day the active users association becomes wrong as it still remember the - // now as a date when the app was started - // -// Company.hasMany(models.User.scope('active'), { -// as : 'activeUsers', -// foreignKey : 'companyId', -// }); - }, - - // Return code for "read-only holidays" mode of company account. - // That means company only shows holidays/timeoff for emplyes and - // does not allow to create new ones. - // - get_mode_readonly_holidays : function(){ - return 2; + return val + } }, - - // Create new company based on default values - create_default_company : function(args){ - var country_code = args.country_code || 'UK', - timezone = args.timezone || 'Europe/London'; - - // Add new company record - return Company.create({ - name : args.name || 'New company', - country : country_code, - start_of_new_year : 1, - timezone : timezone, - }) - - // When new company is created - add default departments to it - .then(function(company){ - - return Promise.all([ - sequelize.models.Department - .create({ - name : 'Sales', - companyId : company.id, - }), - sequelize.models.BankHoliday - .generate_bank_holidays({ - company : company, - country_code : country_code, - }), - sequelize.models.LeaveType - .generate_leave_types({ company : company }) - ]) - .then(function(){ - - return Promise.resolve(company); - }); - }); - + date_format: { + type: DataTypes.STRING, + allowNull: false, + defaultValue: 'YYYY-MM-DD' }, - - getCompanyByApiToken: ({token}) => sequelize.models - .Company - .scope('with_active_users') - .findOne({ - where : { - integration_api_token: token, - integration_api_enabled: true, - } - }), - - }, // End of calss methods - - instanceMethods : { - /* - * Return name suitable to use for precessing by machines, - * actually it just remove spaces and replace them with "_" - * - * */ - name_for_machine : function(){ - return this.name.replace(/\s+/g, '_'); + company_wide_message: { + type: DataTypes.TEXT, + allowNull: true, + defaultValue: null, + comment: 'Message shown to all users that belong to current company' }, - - reload_with_bank_holidays : function(){ - var self = this; - - return self.getBank_holidays() - .then(function(bank_holidays){ - self.bank_holidays = bank_holidays; - - return Promise.resolve(self); - }); + mode: { + type: DataTypes.INTEGER, + allowNull: false, + defaultValue: 1, + comment: 'Indicate which mode the company account is in.' }, - - get_ldap_server : function(){ - - var config = this.get('ldap_auth_config'); - var tlsOptions = config.allow_unauthorized_cert ? { rejectUnauthorized: false } : {}; - - // When testing consider using TEST LDAP server - // http://www.forumsys.com/en/tutorials/integration-how-to/ldap/online-ldap-test-server/ - var ldap = new LdapAuth({ - url : config.url, - bindDn : config.binddn, - bindCredentials : config.bindcredentials, - searchBase : config.searchbase, - searchFilter : '(mail={{username}})', - cache : false, - tlsOptions : tlsOptions - }); - - return ldap; + timezone: { + type: DataTypes.STRING, + allowNull: true, + defaultValue: 'Europe/London', + comment: 'Timezone current company is located in' }, - - get_moment_to_datepicker_map : function() { - return { - "YYYY-MM-DD" : 'yyyy-mm-dd', - "YYYY/MM/DD" : 'yyyy/mm/dd', - "DD MMM, YY" : 'dd M, yy', - "DD/MM/YY" : "dd/mm/yy", - "DD/MM/YYYY" : "dd/mm/yyyy", - "MM/DD/YY" : 'mm/dd/yy', - }; + integration_api_enabled: { + type: DataTypes.BOOLEAN, + allowNull: false, + defaultValue: false }, - - get_default_date_format : function() { - return this.getDataValue('date_format'); + integration_api_token: { + type: DataTypes.UUID, + allowNull: true, + defaultValue: () => uuidv4(), + comment: 'Indicate which mode the company account is in.' }, + carry_over: { + type: DataTypes.INTEGER, + allowNull: true, + defaultValue: 0, + comment: + 'Defines how may remaining days from allowance are carried over to the next year.' + } + }, + { + underscored: true, + indexes: [ + { + fields: ['id'] + } + ] + } + ) + + Company.associate = function(models) { + Company.hasMany(models.Department, { + as: 'departments', + foreignKey: { name: 'company_id', allowNull: false } + }) + Company.hasMany(models.User, { + as: 'users', + foreignKey: { name: 'company_id', allowNull: false } + }) + Company.hasMany(models.BankHoliday, { + as: 'bank_holidays', + foreignKey: { name: 'company_id', allowNull: false } + }) + Company.hasMany(models.LeaveType, { + as: 'leave_types', + foreignKey: { name: 'company_id', allowNull: false } + }) + Company.hasMany(models.EmailAudit, { + as: 'audit_emails', + foreignKey: { name: 'company_id', allowNull: false } + }) + Company.hasMany(models.Audit, { + as: 'audit', + foreignKey: { name: 'company_id', allowNull: false } + }) + } + + Company.loadScope = function(models) { + Company.addScope('with_all_users', { + include: [{ model: models.User, as: 'users' }] + }) + + Company.addScope('with_audit', { + include: [{ model: models.Audit, as: 'audit' }] + }) + + Company.addScope( + 'with_active_users', + // The scope needs to be dynamic as the criteria for active users is based + // on current date, which could be buggy if left static + () => ({ + include: [ + { + model: models.User, + as: 'users', + where: models.User.get_active_user_filter() + } + ] + }) + ) + + Company.addScope('order_by_active_users', { + order: [[{ model: models.User, as: 'users' }, 'lastname']] + }) + + Company.addScope('with_simple_departments', { + include: [{ model: models.Department, as: 'departments' }] + }) + + Company.addScope('with_bank_holidays', { + include: [{ model: models.BankHoliday, as: 'bank_holidays' }] + }) + + Company.addScope('order_by_bank_holidays', { + order: [[{ model: models.BankHoliday, as: 'bank_holidays' }, 'date']] + }) + + Company.addScope('with_leave_types', { + include: [{ model: models.LeaveType, as: 'leave_types' }] + }) + } + + Company.scopeAssociate = function(models) { + // Following code is here for reference only: to help declaring scopped + // associations in future. The approach is not suitable for active users + // bacause of its dynamic nature - we need to have up to date "now", which + // does not work nicely with accociations as they are installed once at the + // applicaiton start time, and if the app will be running for more than one + // day the active users association becomes wrong as it still remember the + // now as a date when the app was started + // + // Company.hasMany(models.User.scope('active'), { + // as : 'activeUsers', + // foreignKey : 'company_id', + // }); + } + + // Return code for "read-only holidays" mode of company account. + // That means company only shows holidays/timeoff for emplyes and + // does not allow to create new ones. + // + Company.get_mode_readonly_holidays = function() { + return 2 + } + + // Create new company based on default values + Company.create_default_company = function(args) { + const country_code = args.country_code || 'UK' + const timezone = args.timezone || 'Europe/London' + + // Add new company record + return ( + Company.create({ + name: args.name || 'New company', + country: country_code, + start_of_new_year: 1, + timezone + }) - get_available_date_formats : function() { - var obj = this.get_moment_to_datepicker_map(); - return _.keys( obj ); - }, - - get_default_date_format_for_date_picker : function() { - var self = this; - - var moment_to_datepicker_map = self.get_moment_to_datepicker_map(); + // When new company is created - add default departments to it + .then(company => + Promise.all([ + sequelize.models.Department.create({ + name: 'Sales', + company_id: company.id + }), + sequelize.models.BankHoliday.generate_bank_holidays({ + company, + country_code + }), + sequelize.models.LeaveType.generate_leave_types({ + company + }) + ]).then(() => Promise.resolve(company)) + ) + ) + } + + Company.getCompanyByApiToken = ({ token }) => + sequelize.models.Company.scope('with_active_users').findOne({ + where: { + integration_api_token: token, + integration_api_enabled: true + } + }) + + Company.restore_from_dump = args => { + // The dump JSON object that is about to be imported + const dump_json = args.dump_json + // Dictionary that holds mapping between promary keys from original system + // and new one + const id_maps = { + company: {}, + bank_holiday: {}, + leave_type: {}, + department: {}, + user: {} + } - if ( moment_to_datepicker_map.hasOwnProperty( self.get_default_date_format() ) ) { - return moment_to_datepicker_map[ self.get_default_date_format() ]; + // Make sure that emails that are about to be migrated do not exist + // withing current database + return ( + sequelize.models.User.findAll({ + where: { + email: { + $in: _.map(dump_json.users, u => u.email) + } } + }) + .then(users => { + if (users.length > 0) { + throw new Error( + 'Users with following emails already exist in the system: ' + + _.map(users, u => u.email).join(', ') + ) + } - return 'yyyy-mm-dd'; - }, + return sequelize.models.Company.describe() + }) - // Takes date string in format specific for current company and produce string - // with date in generic format used internally within application - normalise_date : function(date_str) { - return moment.utc(date_str, this.get_default_date_format()).format('YYYY-MM-DD'); - }, + // Instert company + .then(company_definition => { + const company_json = _.omit( + dump_json, + (value, key, object) => + !(company_definition.hasOwnProperty(key) && key !== 'id') + ) + + return sequelize.models.Company.create(company_json).then(company => { + id_maps.company[dump_json.id] = company.id + return Promise.resolve(1) + }) + }) - // Returns moment UTC-ed object that takes into consideration company time zone - // (p to day's precision) - get_today : function() { - let self = this; + // Instert bank holidays and Leave types + // + .then(() => + Promise.join( + promise_to_restore_bank_holidays({ + dump_json, + id_maps, + model: sequelize.models + }), + promise_to_restore_leave_types({ + dump_json, + id_maps, + model: sequelize.models + }), + () => Promise.resolve(1) + ) + ) + + // Insert departments + // + .then(() => + promise_to_restore_departments({ + dump_json, + id_maps, + model: sequelize.models + }) + ) - return moment.utc( - moment_tz.utc().tz(self.timezone).format('YYYY-MM-DD') - ); - }, + // insert users + // + .then(() => + promise_to_restore_users({ + dump_json, + id_maps, + model: sequelize.models + }) + ) - regenerateIntegrationApiToken : function() { - const self = this; + // Update departments with correct user IDs for supervisor + // + .then(() => + Promise.all( + _.map(_.values(id_maps.department), department_id => + sequelize.models.Department.find({ + where: { id: department_id } + }) + ) + ).then(departments_to_update => + Promise.all( + _.map(departments_to_update, department => { + department.manager_id = id_maps.user[department.manager_id] + return department.save() + }) + ) + ) + ) + + // insert leaves + .then(() => + promise_to_restore_leaves({ + dump_json, + id_maps, + model: sequelize.models + }) + ) + ) + } // End of restore_from_dump + + /* + * Return name suitable to use for precessing by machines, + * actually it just remove spaces and replace them with "_" + * + * */ + Company.prototype.name_for_machine = function() { + return this.name.replace(/\s+/g, '_') + } + + Company.prototype.reload_with_bank_holidays = function() { + const self = this + + return self.getBank_holidays().then(bank_holidays => { + self.bank_holidays = bank_holidays + + return Promise.resolve(self) + }) + } + + Company.prototype.get_ldap_server = function() { + const config = this.get('ldap_auth_config') + const tlsOptions = config.allow_unauthorized_cert + ? { rejectUnauthorized: false } + : {} + + // defaults + if (!config.searchfilter) config.searchfilter = '(mail={{username}})' + // When testing consider using TEST LDAP server + // http://www.forumsys.com/en/tutorials/integration-how-to/ldap/online-ldap-test-server/ + const ldap = new LdapAuth({ + url: config.url, + bindDn: config.binddn, + bindCredentials: config.bindcredentials, + searchBase: config.searchbase, + searchFilter: config.searchfilter, + cache: false, + tlsOptions + }) + + return ldap + } + + Company.prototype.get_moment_to_datepicker_map = function() { + return { + 'YYYY-MM-DD': 'yyyy-mm-dd', + 'YYYY/MM/DD': 'yyyy/mm/dd', + 'DD MMM, YY': 'dd M, yy', + 'DD/MM/YY': 'dd/mm/yy', + 'DD/MM/YYYY': 'dd/mm/yyyy', + 'MM/DD/YY': 'mm/dd/yy' + } + } - self.set('integration_api_token', uuidv4()); + Company.prototype.get_default_date_format = function() { + return this.getDataValue('date_format') + } - return self.save(); - }, + Company.prototype.get_available_date_formats = function() { + const obj = this.get_moment_to_datepicker_map() + return _.keys(obj) + } - // Promise schedule object valid for current company, if it does not have such - // in databse, retulr default one - promise_schedule : function(){ - var self = this; + Company.prototype.get_default_date_format_for_date_picker = function() { + const self = this - return self.sequelize.models.Schedule - .findOne({ - where : { company_id : self.id }, - }) - .then(function(schedule){ + const moment_to_datepicker_map = self.get_moment_to_datepicker_map() - if ( schedule) { - return Promise.resolve( schedule ); - } + if ( + moment_to_datepicker_map.hasOwnProperty(self.get_default_date_format()) + ) { + return moment_to_datepicker_map[self.get_default_date_format()] + } - return self.sequelize.models.Schedule - .promise_to_build_default_for({ company_id : self.id }); - }); - }, + return 'yyyy-mm-dd' + } + + // Takes date string in format specific for current company and produce string + // with date in generic format used internally within application + Company.prototype.normalise_date = function(date_str) { + return moment + .utc(date_str, this.get_default_date_format()) + .format('YYYY-MM-DD') + } + + // Returns moment UTC-ed object that takes into consideration company time zone + // (p to day's precision) + Company.prototype.get_today = function() { + const self = this + + return moment.utc( + moment_tz + .utc() + .tz(self.timezone) + .format('YYYY-MM-DD') + ) + } + + Company.prototype.regenerateIntegrationApiToken = function() { + const self = this + + self.set('integration_api_token', uuidv4()) + + return self.save() + } + + // Promise schedule object valid for current company, if it does not have such + // in databse, retulr default one + Company.prototype.promise_schedule = function() { + const self = this + + return self.sequelize.models.Schedule.findOne({ + where: { company_id: self.id } + }).then(schedule => { + if (schedule) { + return Promise.resolve(schedule) + } - // Return TRUE if company has restrictio on ly to show hollidays for its - // employees and prevent them from adding new ones - // - is_mode_readonly_holidays : function(){ - return this.mode === Company.get_mode_readonly_holidays(); - }, + return self.sequelize.models.Schedule.promise_to_build_default_for({ + company_id: self.id + }) + }) + } - getSortedLeaveTypes: function() { - const self = this; + // Return TRUE if company has restrictio on ly to show hollidays for its + // employees and prevent them from adding new ones + // + Company.prototype.is_mode_readonly_holidays = function() { + return this.mode === Company.get_mode_readonly_holidays() + } - const leaveTypes = self.leave_types || []; + Company.prototype.getSortedLeaveTypes = function() { + const self = this - return leaveTypes.sort((a, b) => sorter(a.name, b.name)); - }, + const leaveTypes = self.leave_types || [] - } - }); + return leaveTypes.sort((a, b) => sorter(a.name, b.name)) + } - return Company; -}; + return Company +} diff --git a/lib/model/db/department.js b/lib/model/db/department.js index ae2254695..033e21200 100644 --- a/lib/model/db/department.js +++ b/lib/model/db/department.js @@ -1,261 +1,259 @@ -"use strict"; +'use strict' -const - moment = require('moment'), - _ = require('underscore'), - Promise = require('bluebird'), - Exception = require('../../error'), - CalendarMonth = require('../calendar_month'); +const moment = require('moment') +const _ = require('underscore') +const Promise = require('bluebird') +const Exception = require('../../error') +const CalendarMonth = require('../calendar_month') module.exports = function(sequelize, DataTypes) { - let Department = sequelize.define("Department", { - // TODO add validators! - name : { - type : DataTypes.STRING, - allowNull : false - }, - allowance : { - type : DataTypes.INTEGER, - allowNull : false, - defaultValue : 20, - }, - include_public_holidays : { - type : DataTypes.BOOLEAN, - allowNull : false, - defaultValue : true, - }, - is_accrued_allowance : { - type : DataTypes.BOOLEAN, - allowNull : false, - defaultValue : false, + const Department = sequelize.define( + 'Department', + { + // TODO add validators! + name: { + type: DataTypes.STRING, + allowNull: false + }, + allowance: { + type: DataTypes.INTEGER, + allowNull: false, + defaultValue: 20 + }, + include_public_holidays: { + type: DataTypes.BOOLEAN, + allowNull: false, + defaultValue: true + }, + is_accrued_allowance: { + type: DataTypes.BOOLEAN, + allowNull: false, + defaultValue: false + } }, - }, { - indexes : [ + { + underscored: true, + indexes: [ { - fields : ['companyId'], + fields: ['company_id'] }, { - fields : ['id'], + fields: ['id'] + } + ] + } + ) + + Department.loadScope = function(models) { + Department.addScope('with_simple_users', { + include: [{ model: models.User, as: 'users' }] + }) + + Department.addScope('with_manager', { + include: [{ model: models.User, as: 'manager' }] + }) + + Department.addScope('with_supervisors', { + include: [{ model: models.User, as: 'supervisors' }] + }) + } + + Department.associate = function(models) { + // We have constrains OFF as to prevent ORM complaining about + // cycle reference + Department.belongsTo(models.User, { + as: 'manager', + constraints: false, + foreignKey: { name: 'manager_id' } + }) + Department.belongsTo(models.Company, { + as: 'company', + foreignKey: { name: 'company_id', allowNull: false } + }) + Department.hasMany(models.User, { + as: 'users', + foreignKey: { name: 'department_id', allowNull: false } + }) + + Department.hasMany(models.DepartmentSupervisor, { + as: 'supervisors_link', + foreignKey: { name: 'department_id', allowNull: false } + }) + + Department.belongsToMany(models.User, { + as: 'supervisors', + foreignKey: 'department_id', + otherKey: 'user_id', + through: models.DepartmentSupervisor + }) + } + + Department.default_order_field = function() { + return 'name' + } + + // Return users related to current department and still active + Department.prototype.promise_active_users = function() { + return this.getUsers({ + where: sequelize.models.User.get_active_user_filter(), + scope: ['withDepartments'] + }) + } + + Department.prototype.promise_team_view_for_month = function(month) { + return this._promise_team_view({ start_date: month }) + } + + Department.prototype.promise_team_view_for_months_range = function( + start_month, + end_month + ) { + return this._promise_team_view({ + start_date: start_month, + end_date: end_month + }) + } + + Department.prototype._promise_team_view = function(args) { + const self = this + const model = sequelize.models + let start_date = args.start_date + let end_date = args.end_date + + const promise_users_and_leaves = Promise + + // First of all ensure that "start_date" is defined + .try(() => { + if (start_date) { + return Promise.resolve(start_date) } - ], - classMethods: { - loadScope : function( models ) { - - Department.addScope( - 'with_simple_users', - { - include : [ - { model : models.User, as : 'users' }, - ], - } - ); - - Department.addScope( - 'with_boss', - { - include : [ - { model : models.User, as : 'boss' }, - ] - } - ); - - Department.addScope( - 'with_supervisors', - { - include : [ - { model : models.User, as : 'supervisors' }, - ] - } - ); - }, - associate : function( models ) { - // We have constrains OFF as to prevent ORM complaining about - // cycle reference - Department.belongsTo ( models.User, { as : 'boss', constraints: false}); - Department.belongsTo ( models.Company, { as : 'company'}); - Department.hasMany ( models.User, { as : 'users'}); - - Department.hasMany( models.DepartmentSupervisor, { - as : 'supervisors_link', - foreignKey : {name: 'department_id', allowNull: false}, - }); - - Department.belongsToMany(models.User, { - as : 'supervisors', - foreignKey : 'department_id', - otherKey : 'user_id', - through : models.DepartmentSupervisor, - }); - }, - - default_order_field : function(){ - return 'name'; - }, - }, - - instanceMethods : { - - // Return users related to current department and still active - promise_active_users : function(){ - return this.getUsers({ - scope: ["withDepartments"], - where: sequelize.models.User.get_active_user_filter() - }); - }, - - promise_team_view_for_month : function( month ){ - return this._promise_team_view({ start_date : month }); - }, - - promise_team_view_for_months_range : function (start_month, end_month){ - return this._promise_team_view({ - start_date : start_month, - end_date : end_month, - }); - }, - - _promise_team_view : function(args){ - - let - self = this, - model = sequelize.models, - start_date = args.start_date, - end_date = args.end_date; + return self + .getCompany() + .then(company => Promise.resolve((start_date = company.get_today()))) + }) - var promise_users_and_leaves = Promise + // Ensure end_date is suitable if it was provided + .then(start_date => { + // If end_date was not provided: no need to validate it: set it to be equal to start date + if (!end_date) { + end_date = start_date - // First of all ensure that "start_date" is defined - .try(function(){ - if ( start_date ) { - return Promise.resolve(start_date); - } + return Promise.resolve() + } - return self.getCompany() - .then(company => Promise.resolve( start_date = company.get_today() ) ) + // If end date is provided... + // ... ensure start and end dates are from within same year + if ( + moment.utc(end_date).format('YYYY') !== + moment.utc(start_date).format('YYYY') + ) { + Exception.throw_user_error({ + user_error: 'Start and End dates should within single year', + system_error: + '_promise_team_view was called with start_date and end_date from different years.' }) + } - // Ensure end_date is suitable if it was provided - .then(() => { - - // If end_date was not provided: no need to validate it: set it to be equal to start date - if ( ! end_date ) { - - end_date = start_date; + // ... ensure that start date proceed end date + if ( + moment.utc(start_date).dayOfYear() > moment.utc(end_date).dayOfYear() + ) { + Exception.throw_user_error({ + user_error: 'Start date needs to be before end date', + system_error: + '_promise_team_view was called with end_date prior to start_date' + }) + } - return Promise.resolve(); - } + return Promise.resolve() + }) + + // Get users + .then(() => self.promise_active_users()) + .then( + users => + Promise.all( + _.map(users, user => + user + .promise_my_leaves_for_calendar({ + year: start_date + }) + .then(leaves => { + const leave_days = _.flatten( + _.map(leaves, leave => + _.map(leave.get_days(), leave_day => { + leave_day.leave = leave + return leave_day + }) + ) + ) + + return user.promise_schedule_I_obey().then(schedule => + Promise.resolve({ + user, + leave_days, + schedule + }) + ) + }) + ) // End of map + ) // End of promise_users_and_leaves + ) + + const promise_company = self.getCompany({ + include: [ + { model: model.BankHoliday, as: 'bank_holidays' }, + { model: model.LeaveType, as: 'leave_types' } + ] + }) + + return Promise.join( + promise_company, + promise_users_and_leaves, + (company, users_and_leaves) => { + const number_of_months = + moment.utc(end_date).month() - moment.utc(start_date).month() + + users_and_leaves.forEach(user_data => { + user_data.days = [] + + // Now iterate throw all monthes between start and end dates + // and get calendar months for each + // and then combined them all togather + for (let i = 0; i <= number_of_months; i++) { + const calendar_month = new CalendarMonth( + moment + .utc(start_date) + .clone() + .add(i, 'months'), + { + bank_holidays: self.include_public_holidays + ? _.map(company.bank_holidays, day => day.date) + : [], + leave_days: user_data.leave_days, + schedule: user_data.schedule, + today: company.get_today(), + leave_types: company.leave_types + } + ) - // If end date is privided... - // ... ensure start and end dates are from within same year - if (moment.utc(end_date).format('YYYY') !== moment.utc(start_date).format('YYYY')) { - Exception.throw_user_error({ - user_error : 'Start and End dates should within single year', - system_error : '_promise_team_view was called with start_date and end_date from different years.', - }); - } + user_data.days.push(calendar_month.as_for_team_view()) + } // end of for + user_data.days = _.flatten(user_data.days) + }) - // ... ensure that start date proceed end date - if (moment.utc(start_date).dayOfYear() > moment.utc(end_date).dayOfYear()) { - Exception.throw_user_error({ - user_error : 'Start date needs to be before end date', - system_error : '_promise_team_view was called with end_date prior to start_date', - }); - } + return Promise.resolve(users_and_leaves) + } + ) + } // End of promise_team_view - return Promise.resolve(); - }) + // Return new department object that is based on same ID but include all supervisors + Department.prototype.promise_me_with_supervisors = function() { + const self = this - // Get users - .then( () => self.promise_active_users() ) - .then(function(users){ - - return Promise.all( - _.map( - users, - function(user){ - return user.promise_my_leaves_for_calendar({ - year : start_date, - }) - .then(function(leaves){ - - var leave_days = _.flatten( _.map(leaves, function(leave){ - return _.map( leave.get_days(), function(leave_day){ - leave_day.leave = leave; - return leave_day; - }); - })); - - return user.promise_schedule_I_obey() - .then(function(schedule){ - return Promise.resolve({ - user : user, - leave_days : leave_days, - schedule : schedule, - }); - }); - }); - } - ) // End of map - ); // End of promise_users_and_leaves - }); - - var promise_company = self.getCompany({ - include:[ - { model : model.BankHoliday , as : 'bank_holidays' }, - { model : model.LeaveType , as : 'leave_types' }, - ] - }); - - return Promise.join( - promise_company, - promise_users_and_leaves, - function(company, users_and_leaves){ - - let number_of_months = moment.utc(end_date).month() - moment.utc(start_date).month(); - - users_and_leaves.forEach( user_data => { - - user_data.days = []; - - // Now iterate throw all monthes between start and end dates - // and get calendar months for each - // and then combined them all togather - for ( let i=0; i<=number_of_months; i++ ) { - - let calendar_month = new CalendarMonth( - moment.utc(start_date).clone().add(i, 'months'), - { - bank_holidays : - self.include_public_holidays - ? company.bank_holidays - : [], - leave_days : user_data.leave_days, - schedule : user_data.schedule, - today : company.get_today(), - leave_types: company.leave_types, - } - ); - - user_data.days.push( calendar_month.as_for_team_view()); - } // end of for - user_data.days = _.flatten( user_data.days ); - }); - - return Promise.resolve(users_and_leaves); - } - ); - - }, // End of promise_team_view - - // Return new department object that is based on same ID but include all supervisors - promise_me_with_supervisors : function() { - var self = this; - - return self.Model.scope('with_supervisors').findById( self.id ); - }, - } - }); + return self.Model.scope('with_supervisors').findByPk(self.id) + } - return Department; -}; + return Department +} diff --git a/lib/model/db/department_supervisor.js b/lib/model/db/department_supervisor.js index e6dee958e..92d0e62a1 100644 --- a/lib/model/db/department_supervisor.js +++ b/lib/model/db/department_supervisor.js @@ -1,35 +1,36 @@ +'use strict' -"use strict"; +module.exports = function(sequelize, DataTypes) { + const DepartmentSupervisor = sequelize.define( + 'DepartmentSupervisor', + {}, + { + underscored: true, + timestamps: true, + createdAt: 'created_at', + updatedAt: false, + indexes: [ + { + fields: ['department_id'] + }, + { + fields: ['user_id'] + } + ] + } + ) -module.exports = function(sequelize, DataTypes){ - var DepartmentSupervisor = sequelize.define("DepartmentSupervisor", {}, { - underscored : true, - freezeTableName : true, - timestamps : true, - createdAt : 'created_at', - updatedAt : false, - indexes : [{ - fields : [ 'department_id' ], - },{ - fields : [ 'user_id' ], - }], + DepartmentSupervisor.associate = function(models) { + DepartmentSupervisor.belongsTo(models.Department, { + as: 'department', + foreignKey: 'department_id' + }) - classMethods : { - associate : function(models) { + DepartmentSupervisor.belongsTo(models.User, { + as: 'user', + foreignKey: 'user_id' + }) + } - DepartmentSupervisor.belongsTo(models.Department, { - as : 'department', - foreignKey : 'department_id', - }); - - DepartmentSupervisor.belongsTo(models.User, { - as : 'user', - foreignKey : 'user_id', - }); - }, - }, - - }); - - return DepartmentSupervisor; -}; + return DepartmentSupervisor +} diff --git a/lib/model/db/email_audit.js b/lib/model/db/email_audit.js index 0868f2a30..b1d5705d8 100644 --- a/lib/model/db/email_audit.js +++ b/lib/model/db/email_audit.js @@ -1,60 +1,59 @@ +'use strict' -"use strict"; +const htmlToText = require('html-to-text') -const - htmlToText = require('html-to-text'); - -module.exports = function(sequelize, DataTypes){ - var EmailAudit = sequelize.define("EmailAudit", { - email : { - type : DataTypes.STRING, - allowNull : false, - }, - subject : { - type : DataTypes.TEXT, - allowNull : false, - }, - body : { - type : DataTypes.TEXT, - allowNull : false, - }, - },{ - underscored : true, - freezeTableName : true, - timestamps : true, - createdAt : 'created_at', - updatedAt : false, - indexes : [{ - fields : [ 'created_at' ], - },{ - fields : [ 'user_id' ], - }], - - classMethods : { - associate : function(models) { - - EmailAudit.belongsTo(models.Company, { - as : 'company', - foreignKey : 'company_id', - }); - - - EmailAudit.belongsTo(models.User, { - as : 'user', - foreignKey : 'user_id', - }); +module.exports = function(sequelize, DataTypes) { + const EmailAudit = sequelize.define( + 'EmailAudit', + { + email: { + type: DataTypes.STRING, + allowNull: false }, - }, - - instanceMethods : { - // Present the email body as a text, strips off any html tags etc - // - body_as_text : function(){ - return this.body.indexOf('DOCTYPE') > 0 ? htmlToText.fromString(this.body) : this.body; + subject: { + type: DataTypes.TEXT, + allowNull: false }, + body: { + type: DataTypes.TEXT, + allowNull: false + } }, - - }); - - return EmailAudit; -}; + { + underscored: true, + timestamps: true, + createdAt: 'created_at', + updatedAt: false, + indexes: [ + { + fields: ['created_at'] + }, + { + fields: ['user_id'] + } + ] + } + ) + + EmailAudit.associate = function(models) { + EmailAudit.belongsTo(models.Company, { + as: 'company', + foreignKey: { name: 'company_id', allowNull: false } + }) + + EmailAudit.belongsTo(models.User, { + as: 'user', + foreignKey: { name: 'user_id', allowNull: false } + }) + } + + // Present the email body as a text, strips off any html tags etc + // + EmailAudit.prototype.body_as_text = function() { + return this.body.indexOf('DOCTYPE') > 0 + ? htmlToText.fromString(this.body) + : this.body + } + + return EmailAudit +} diff --git a/lib/model/db/index.js b/lib/model/db/index.js index af125bba9..e6e1a1797 100644 --- a/lib/model/db/index.js +++ b/lib/model/db/index.js @@ -1,49 +1,64 @@ -"use strict"; - -var fs = require("fs"); -var path = require("path"); -var Sequelize = require("sequelize"); -var env = process.env.NODE_ENV || "development"; -var config = require(__dirname + '/../../../config/db.json')[env]; -var sequelize = new Sequelize(config.database, config.username, config.password, config); -var db = {}; - -fs - .readdirSync(__dirname) - .filter(function(file) { - return (file.indexOf(".") !== 0) - && (file !== "index.js"); +'use strict' + +const fs = require('fs') +const path = require('path') +const Sequelize = require('sequelize') +const env = process.env.NODE_ENV || 'development' + +const databaseConfig = { + host: process.env.DB_HOST, + database: process.env.DB_DATABASE, + username: process.env.DB_USERNAME, + password: process.env.DB_PASSWORD, + + dialect: process.env.DB_DIALECT || 'sqlite', + storage: process.env.DB_STORAGE || 'db.' + env + '.sqlite', + logging: (process.env.DB_LOGGING && console.log) || false, + pool: { + max: parseInt(process.env.DB_POOL_MAX) || 5, + min: parseInt(process.env.DB_POOL_MIN) || 0, + acquire: parseInt(process.env.DB_POOL_ACQUIRE) || 60000, + idle: parseInt(process.env.DB_POOL_IDLE) || 10000 + } +} + +const sequelize = process.env.DATABASE_URL + ? new Sequelize(process.env.DATABASE_URL, databaseConfig) + : new Sequelize(databaseConfig) +const db = {} + +fs.readdirSync(__dirname) + .filter(file => file.indexOf('.') !== 0 && file !== 'index.js') + .forEach(file => { + const model = sequelize.import(path.join(__dirname, file)) + db[model.name] = model }) - .forEach(function(file) { - var model = sequelize["import"](path.join(__dirname, file)); - db[model.name] = model; - }); // Link models according associations // -Object.keys(db).forEach(function(modelName) { - if ("associate" in db[modelName]) { - db[modelName].associate(db); +Object.keys(db).forEach(modelName => { + if ('associate' in db[modelName]) { + db[modelName].associate(db) } -}); +}) // Add scopes // -Object.keys(db).forEach(function(modelName) { +Object.keys(db).forEach(modelName => { if ('loadScope' in db[modelName]) { - db[modelName].loadScope(db); + db[modelName].loadScope(db) } -}); +}) // Link models based on associations that are based on scopes // -Object.keys(db).forEach(function(modelName) { +Object.keys(db).forEach(modelName => { if ('scopeAssociate' in db[modelName]) { - db[modelName].scopeAssociate(db); + db[modelName].scopeAssociate(db) } -}); +}) -db.sequelize = sequelize; -db.Sequelize = Sequelize; +db.sequelize = sequelize +db.Sequelize = Sequelize -module.exports = db; +module.exports = db diff --git a/lib/model/db/leave.js b/lib/model/db/leave.js index 25a67d928..5a2c776b8 100644 --- a/lib/model/db/leave.js +++ b/lib/model/db/leave.js @@ -1,423 +1,509 @@ +'use strict' -"use strict"; - -var - _ = require('underscore'), - moment = require('moment'), - Promise = require("bluebird"), - LeaveDay = require('../leave_day'); +const _ = require('underscore') +const moment = require('moment') +const Promise = require('bluebird') +const LeaveDay = require('../leave_day') module.exports = function(sequelize, DataTypes) { - var Leave = sequelize.define("Leave", { - // TODO add validators! - 'status' : { - type : DataTypes.INTEGER, - allowNull : false - }, - employee_comment : { - type : DataTypes.STRING, - allowNull : true, - }, - approver_comment : { - type : DataTypes.STRING, - allowNull : true, - }, - decided_at : { - type : DataTypes.DATE, - allowNull : true, - }, - - date_start : { - type : DataTypes.DATE, - allowNull : false, - defaultValue : sequelize.NOW, - }, - day_part_start : { - type : DataTypes.INTEGER, - allowNull : false, - defaultValue : 1, // VPP TODO replace with constant value - }, - date_end : { - type : DataTypes.DATE, - allowNull : false, - defaultValue : sequelize.NOW, - }, - day_part_end : { - type : DataTypes.INTEGER, - allowNull : false, - defaultValue : 1, // VPP TODO replace with constant value - }, - }, { + const Leave = sequelize.define( + 'Leave', + { + // TODO add validators! + status: { + type: DataTypes.INTEGER, + allowNull: false + }, + employee_comment: { + type: DataTypes.TEXT, + allowNull: true + }, + approver_comment: { + type: DataTypes.TEXT, + allowNull: true + }, + decided_at: { + type: DataTypes.DATE, + allowNull: true + }, - indexes : [ + date_start: { + type: DataTypes.DATE, + allowNull: false, + defaultValue: sequelize.NOW + }, + day_part_start: { + type: DataTypes.INTEGER, + allowNull: false, + defaultValue: 1 // VPP TODO replace with constant value + }, + date_end: { + type: DataTypes.DATE, + allowNull: false, + defaultValue: sequelize.NOW + }, + day_part_end: { + type: DataTypes.INTEGER, + allowNull: false, + defaultValue: 1 // VPP TODO replace with constant value + } + }, + { + underscored: true, + indexes: [ { - fields : ['userId'], + fields: ['user_id'] }, { - fields : ['leaveTypeId'], + fields: ['leave_type_id'] }, { - fields : ['approverId'], - }, - ], - classMethods : { - associate : function( models ){ - Leave.belongsTo(models.User, { as : 'user',foreignKey : 'userId' }); - Leave.belongsTo(models.User, { as : 'approver',foreignKey : 'approverId' }); - Leave.belongsTo(models.LeaveType, { as : 'leave_type' } ); - Leave.hasMany(models.Comment, { - as : 'comments', - foreignKey: 'companyId', - scope: { - entityType: models.Comment.getEntityTypeLeave(), - }, - }); - }, - - status_new : () => 1, - status_approved : () => 2, - status_rejected : () => 3, - status_pended_revoke : () => 4, - status_canceled : () => 5, + fields: ['approver_id'] + } + ] + } + ) - leave_day_part_all : () => 1, - leave_day_part_morning : () => 2, - leave_day_part_afternoon : () => 3, + Leave.associate = function(models) { + Leave.belongsTo(models.User, { + as: 'user', + foreignKey: { name: 'user_id', allowNull: false } + }) + Leave.belongsTo(models.User, { + as: 'approver', + foreignKey: 'approver_id' + }) + Leave.belongsTo(models.LeaveType, { + as: 'leave_type', + foreignKey: { name: 'leave_type_id', allowNull: false } + }) + Leave.hasMany(models.Comment, { + as: 'comments', + foreignKey: 'company_id', + scope: { + entity_type: models.Comment.getEntityTypeLeave() + } + }) + } - does_skip_approval: function( user, leave_type ) { - return user.is_auto_approve() || leave_type.is_auto_approve(); - } - }, + Leave.status_new = function() { + return 1 + } - instanceMethods : { + Leave.status_approved = function() { + return 2 + } -reloadWithAssociates : function() { - const self = this; + Leave.status_rejected = function() { + return 3 + } - return self.reload({ - include : [ - {model : self.sequelize.models.User, as : 'user'}, - {model : self.sequelize.models.User, as : 'approver'}, - {model : self.sequelize.models.LeaveType, as : 'leave_type'}, - ], - }); -}, + Leave.status_pended_revoke = function() { + return 4 + } -get_days : function() { + Leave.status_canceled = function() { + return 5 + } - var self = this, - start_date = moment.utc(this.date_start), - end_date = moment.utc(this.date_end), - days = [ start_date ]; + Leave.leave_day_part_all = function() { + return 1 + } - if (self.hasOwnProperty('_days')) { - return self._days; + Leave.leave_day_part_morning = function() { + return 2 } - if ( ! start_date.isSame( end_date, 'day') ){ + Leave.leave_day_part_afternoon = function() { + return 3 + } - var days_in_between = end_date.diff( start_date, 'days' ) - 1; + Leave.does_skip_approval = function(user, leave_type) { + return user.is_auto_approve() || leave_type.is_auto_approve() + } - for (var i=1; i<=days_in_between; i++) { - days.push( start_date.clone().add(i, 'days') ); + /* + * Create new leave for provided parameters. + * Returns promise that is resolved with newly created leave row + * */ + Leave.create_new_leave = function(args) { + // Make sure all required data is provided + _.each(['for_employee', 'of_type', 'with_parameters'], property => { + if (!_.has(args, property)) { + throw new Error('No mandatory ' + property + ' was provided') } + }) + + const employee = args.for_employee + const leave_type = args.of_type + const valide_attributes = args.with_parameters + + // Make sure that booking to be created is not going to ovelap with + // any existing bookings + return Promise.try(() => employee.validate_overlapping(valide_attributes)) + .then(() => employee.promise_manager()) + .then(main_supervisor => { + const start_date = moment.utc(valide_attributes.from_date) + const end_date = moment.utc(valide_attributes.to_date) + + // Check that start date is not bigger then end one + if (start_date.toDate() > end_date.toDate()) { + throw new Error('Start date is later than end date') + } - days.push( end_date ); + const new_leave_status = employee.is_auto_approve() + ? Leave.status_approved() + : Leave.status_new() + + // Following statement creates in memory only leave object + // it is not in database until .save() method is called + const leave_to_create = sequelize.models.Leave.build({ + user_id: employee.id, + leave_type_id: leave_type.id, + status: new_leave_status, + approver_id: main_supervisor.id, + employee_comment: valide_attributes.reason, + + date_start: start_date.format('YYYY-MM-DD'), + date_end: end_date.format('YYYY-MM-DD'), + day_part_start: valide_attributes.from_date_part, + day_part_end: valide_attributes.to_date_part + }) + + return employee + .validate_leave_fits_into_remaining_allowance({ + year: start_date, + leave_type, + leave: leave_to_create + }) + .then(() => leave_to_create.save()) + }) + } // End of create_new_leave + + Leave.prototype.reloadWithAssociates = function() { + const self = this + + return self.reload({ + include: [ + { model: self.sequelize.models.User, as: 'user' }, + { model: self.sequelize.models.User, as: 'approver' }, + { model: self.sequelize.models.LeaveType, as: 'leave_type' } + ] + }) } - days = _.map( - days, - function(day){ - return new LeaveDay({ - leave_type_id : self.leaveTypeId, - sequelize : sequelize, - date : day.format('YYYY-MM-DD'), - day_part : day.isSame(start_date, 'day') - ? self.day_part_start - : day.isSame(end_date, 'day') - ? self.day_part_end - : Leave.leave_day_part_all(), - }); + Leave.prototype.get_days = function() { + const self = this + const start_date = moment.utc(this.date_start) + const end_date = moment.utc(this.date_end) + let days = [start_date] + + if (self._days) { + return self._days + } + + if (!start_date.isSame(end_date, 'day')) { + const days_in_between = end_date.diff(start_date, 'days') - 1 + + for (let i = 1; i <= days_in_between; i++) { + days.push(start_date.clone().add(i, 'days')) } - ); - return self._days = days; -}, + days.push(end_date) + } -fit_with_leave_request : function(leave_request) { + days = _.map( + days, + day => + new LeaveDay({ + leave_type_id: self.leave_type_id, + sequelize, + date: day.format('YYYY-MM-DD'), + day_part: day.isSame(start_date, 'day') + ? self.day_part_start + : day.isSame(end_date, 'day') + ? self.day_part_end + : Leave.leave_day_part_all() + }) + ) + + return (self._days = days) + } + Leave.prototype.fit_with_leave_request = function(leave_request) { // If start and end dates are the same, check if one of them fit // into fist or last leave_days. if ( - leave_request.is_within_one_day() && ( - leave_request.does_fit_with_leave_day( _.last(this.get_days()) ) - || - leave_request.does_fit_with_leave_day( _.first(this.get_days()) ) - ) - ) { - return true; + leave_request.is_within_one_day() && + (leave_request.does_fit_with_leave_day(_.last(this.get_days())) || + leave_request.does_fit_with_leave_day(_.first(this.get_days()))) + ) { + return true } // If start and end dates are different, check if start date // fits into end leave_day or end date fits int start leave_date. if ( - (! leave_request.is_within_one_day()) && ( - leave_request.does_fit_with_leave_day_at_start( - _.last(this.get_days()) - ) - || - leave_request.does_fit_with_leave_day_at_end( - _.first(this.get_days()) - ) - ) + !leave_request.is_within_one_day() && + (leave_request.does_fit_with_leave_day_at_start( + _.last(this.get_days()) + ) || + leave_request.does_fit_with_leave_day_at_end(_.first(this.get_days()))) ) { - return true; + return true } - return false; -}, // End of fit_with_leave_request - -is_new_leave : function() { - return this.status === Leave.status_new(); -}, - -is_pended_revoke_leave : function(){ - return this.status === Leave.status_pended_revoke(); -}, - -// Leave is treated as "approved" one if it is in approved staus -// or if it is waiting decision on revoke action -// -is_approved_leave : function() { - return this.status === Leave.status_approved() || - this.status === Leave.status_pended_revoke() ; -}, - -is_auto_approve : function() { - return Leave.does_skip_approval(this.user, this.leave_type); -}, - -// Determine if leave starts with half day in the morning -// -does_start_half_morning : function() { - return this.day_part_start === Leave.leave_day_part_morning(); -}, - -does_start_half_afternoon : function() { - return this.day_part_start === Leave.leave_day_part_afternoon(); -}, - -// Determine if leave ends with half a day in the afternoon -// -does_end_half_afternoon : function() { - return this.day_part_end === Leave.leave_day_part_afternoon(); -}, - -does_end_half_morning : function() { - return this.day_part_end === Leave.leave_day_part_morning(); -}, - -get_start_leave_day : function(){ - return this.get_days()[0]; -}, - -get_end_leave_day : function(){ - return this.get_days()[ this.get_days().length - 1 ]; -}, - -get_deducted_days_number : function(args) { - var number_of_days = this.get_deducted_days(args).length; - - // leave spans via on working day only, pay attention only to the start date - if (number_of_days === 1 && !this.get_start_leave_day().is_all_day_leave()) { - number_of_days = number_of_days - 0.5; - } + return false + } // End of fit_with_leave_request - // case when leave spreads for more then one day, then check if both start and day - // are halfs - else if (number_of_days > 1) { - if ( ! this.get_start_leave_day().is_all_day_leave() ){ - number_of_days = number_of_days - 0.5; - } - if ( ! this.get_end_leave_day().is_all_day_leave() ) { - number_of_days = number_of_days - 0.5; - } + Leave.prototype.is_new_leave = function() { + return this.status === Leave.status_new() } - return number_of_days; -}, - -get_deducted_days : function(args) { - - var leave_days = [], - ignore_allowance = false, - leave_type = this.leave_type || args.leave_type, - year; + Leave.prototype.is_pended_revoke_leave = function() { + return this.status === Leave.status_pended_revoke() + } - if (args && args.hasOwnProperty('ignore_allowance')) { - ignore_allowance = args.ignore_allowance; + // Leave is treated as "approved" one if it is in approved staus + // or if it is waiting decision on revoke action + // + Leave.prototype.is_approved_leave = function() { + return ( + this.status === Leave.status_approved() || + this.status === Leave.status_pended_revoke() + ) } - if (args && args.hasOwnProperty('year')) { - year = moment.utc(args.year, 'YYYY'); + Leave.prototype.is_auto_approve = function() { + return Leave.does_skip_approval(this.user, this.leave_type) } - // If current Leave stands for type that does not use - // allowance, ignore rest of the code; - if (! ignore_allowance && !leave_type.use_allowance) return leave_days; + // Determine if leave starts with half day in the morning + // + Leave.prototype.does_start_half_morning = function() { + return this.day_part_start === Leave.leave_day_part_morning() + } - var user = this.user || this.approver || args.user; + Leave.prototype.does_start_half_afternoon = function() { + return this.day_part_start === Leave.leave_day_part_afternoon() + } - var bank_holiday_map = {}; + // Determine if leave ends with half a day in the afternoon + // + Leave.prototype.does_end_half_afternoon = function() { + return this.day_part_end === Leave.leave_day_part_afternoon() + } - user.company.bank_holidays.forEach(function(bank_holiday){ - bank_holiday_map[ bank_holiday.get_pretty_date() ] = 1; - }); + Leave.prototype.does_end_half_morning = function() { + return this.day_part_end === Leave.leave_day_part_morning() + } - // Because we currently in synchronos code we have to rely on cahed value - // rather then fetching it here, and prey that whoever called current - // method made sure that the cach is populated - var schedule = user.cached_schedule; + Leave.prototype.get_start_leave_day = function() { + return this.get_days()[0] + } - leave_days = _.filter( - _.map(this.get_days(), function(leave_day){ + Leave.prototype.get_end_leave_day = function() { + return this.get_days()[this.get_days().length - 1] + } - // Ignore bank holidays - if ( bank_holiday_map[ leave_day.get_pretty_date() ] ) return; + Leave.prototype.get_deducted_days_number = function(args) { + let number_of_days = this.get_deducted_days(args).length - // If it happenned that current leave day is from the year current - // call was made of, ignore that day - if (year && year.year() !== moment.utc(leave_day.date).year()) return; + // leave spans via on working day only, pay attention only to the start date + if ( + number_of_days === 1 && + !this.get_start_leave_day().is_all_day_leave() + ) { + number_of_days = number_of_days - 0.5 + } - // Ignore non-working days (weekends) - if ( ! schedule.is_it_working_day({ day : moment.utc(leave_day.date) }) ){ - return; + // case when leave spreads for more then one day, then check if both start and day + // are halfs + else if (number_of_days > 1) { + if (!this.get_start_leave_day().is_all_day_leave()) { + number_of_days = number_of_days - 0.5 + } + if (!this.get_end_leave_day().is_all_day_leave()) { + number_of_days = number_of_days - 0.5 } - - return leave_day; - }), - function(leave_day){ - return !! leave_day; } - ) || []; - return leave_days; -}, // End get_deducted_days + return number_of_days + } -promise_to_reject : function(args) { - let self = this; + Leave.prototype.get_deducted_days = function(args) { + let leave_days = [] + let ignore_allowance = false + const leave_type = this.get('leave_type') || args.leave_type + let year - if ( ! args ) { - args = {}; - } + if (args && args.ignore_allowance) { + ignore_allowance = args.ignore_allowance + } - if ( ! args.by_user ) { - throw new Error('promise_to_reject has to have by_user parameter'); - } + if (args && args.year) { + year = moment.utc(args.year, 'YYYY') + } - let by_user = args.by_user; + // If current Leave stands for type that does not use + // allowance, ignore rest of the code; + if (!ignore_allowance && !leave_type.use_allowance) return leave_days - // See explanation to promise_to_approve - self.status = self.is_pended_revoke_leave() ? - Leave.status_approved(): - Leave.status_rejected(); + const user = this.user || this.approver || args.user - self.approverId = by_user.id; + const bank_holiday_map = {} - return self.save(); -}, + user.company.bank_holidays.forEach(bank_holiday => { + bank_holiday_map[bank_holiday.get_pretty_date()] = 1 + }) -promise_to_approve : function(args) { - let self = this; + // Because we currently in synchronos code we have to rely on cahed value + // rather then fetching it here, and prey that whoever called current + // method made sure that the cach is populated + const schedule = user.cached_schedule + + leave_days = + _.filter( + _.map(this.get_days(), leave_day => { + // Ignore bank holidays + if (bank_holiday_map[leave_day.get_pretty_date()]) return + + // If it happenned that current leave day is from the year current + // call was made of, ignore that day + if (year && year.year() !== moment.utc(leave_day.date).year()) return + + // Ignore non-working days (weekends) + if ( + !schedule.is_it_working_day({ + day: moment.utc(leave_day.date) + }) + ) { + return + } + + return leave_day + }), + leave_day => !!leave_day + ) || [] + + return leave_days + } // End get_deducted_days + + Leave.prototype.promise_to_reject = function(args) { + const self = this + + if (!args) { + args = {} + } - if ( ! args ) { - args = {}; - } + if (!args.by_user) { + throw new Error('promise_to_reject has to have by_user parameter') + } - if ( ! args.by_user ) { - throw new Error('promise_to_approve has to have by_user parameter'); - } + const by_user = args.by_user - let by_user = args.by_user; + // See explanation to promise_to_approve + self.status = self.is_pended_revoke_leave() + ? Leave.status_approved() + : Leave.status_rejected() - // If current leave is one with requested revoke, then - // approve action set it into Rejected status - // otherwise it is approve action for new leave - // so put leave into Approved - self.status = self.is_pended_revoke_leave() ? - Leave.status_rejected(): - Leave.status_approved(); + self.approver_id = by_user.id - self.approverId = by_user.id; + return self.save() + } - return self.save(); -}, + Leave.prototype.promise_to_approve = function(args) { + const self = this -promise_to_revoke : function(){ - return this.reload({ - include : [ - { - model : sequelize.models.User, - as : 'user', - include: [ {model: sequelize.models.Department, as: 'department'} ] - }, - {model : sequelize.models.LeaveType, as : 'leave_type' }, - ], - }) - .then(function(leave){ + if (!args) { + args = {} + } - var new_leave_status = leave.is_auto_approve() - ? Leave.status_rejected() - : Leave.status_pended_revoke(); + if (!args.by_user) { + throw new Error('promise_to_approve has to have by_user parameter') + } - // By default it is user main boss is one who has to approve the revoked request - leave.approverId = leave.user.department.bossId; + const by_user = args.by_user - leave.status = new_leave_status; + // If current leave is one with requested revoke, then + // approve action set it into Rejected status + // otherwise it is approve action for new leave + // so put leave into Approved + self.status = self.is_pended_revoke_leave() + ? Leave.status_rejected() + : Leave.status_approved() - return leave.save(); - }); -}, + self.approver_id = by_user.id -promise_to_cancel : function(){ - var self = this; + return self.save() + } - if ( ! self.is_new_leave() ) { - throw new Error('An attempt to cancel non-new leave request id : '+self.id); + Leave.prototype.promise_to_revoke = function(args) { + const self = this + + return self + .getUser({ + include: [ + { + model: sequelize.models.Department, + as: 'department' + } + ] + }) + .then(user => { + const new_leave_status = user.is_auto_approve() + ? Leave.status_rejected() + : Leave.status_pended_revoke() + + // By default it is user main manager is one who has to approve the revoked request + self.approver_id = user.department.manager_id + + self.status = new_leave_status + + return self.save() + }) } - self.status = Leave.status_canceled(); + Leave.prototype.promise_to_cancel = function() { + const self = this - return self.save(); -}, + if (!self.is_new_leave()) { + throw new Error( + 'An attempt to cancel non-new leave request id : ' + self.id + ) + } -get_leave_type_name : function() { - var leave_type = this.get('leave_type'); + self.status = Leave.status_canceled() - if (! leave_type ) { - return ''; - } else { - return leave_type.name; + return self.save() } -}, -promise_approver : function() { - - return this.getApprover({ - include : [{ - model : sequelize.models.Company, - as : 'company', - include : [{ - model : sequelize.models.BankHoliday, - as : 'bank_holidays', - }], - }], - }) -}, + Leave.prototype.get_leave_type_name = function() { + const leave_type = this.get('leave_type') + if (!leave_type) { + return '' + } else { + return leave_type.name + } + } - }, - }); + Leave.prototype.promise_approver = function() { + return this.getApprover({ + include: [ + { + model: sequelize.models.Company, + as: 'company', + include: [ + { + model: sequelize.models.BankHoliday, + as: 'bank_holidays' + } + ] + } + ] + }) + } - return Leave; -}; + return Leave +} diff --git a/lib/model/db/leave_type.js b/lib/model/db/leave_type.js index 25153a287..105270c2a 100644 --- a/lib/model/db/leave_type.js +++ b/lib/model/db/leave_type.js @@ -1,79 +1,80 @@ -"use strict"; +'use strict' module.exports = function(sequelize, DataTypes) { - var LeaveType = sequelize.define("LeaveType", { - // TODO add validators! - name : { - type : DataTypes.STRING, - allowNull : false - }, - color : { - type : DataTypes.STRING, - allowNull : false, - defaultValue : '#ffffff', - }, - use_allowance : { - type : DataTypes.BOOLEAN, - allowNull : false, - defaultValue : true, - }, - limit : { - type : DataTypes.INTEGER, - allowNull : false, - defaultValue : 0, - }, - sort_order : { - type : DataTypes.INTEGER, - allowNull : false, - defaultValue : 0, - comment : "Is used to determine sorting order of leave types", - }, - auto_approve : { - type : DataTypes.BOOLEAN, - allowNull : false, - defaultValue : false, - }, - }, { - classMethods: { - associate : function( models ) { - LeaveType.belongsTo(models.Company, {as : 'company'}); - LeaveType.hasMany(models.Leave, {as : 'leaves', foreignKey : 'leaveTypeId'}); - }, + const LeaveType = sequelize.define( + 'LeaveType', + { + // TODO add validators! + name: { + type: DataTypes.STRING, + allowNull: false + }, + color: { + type: DataTypes.STRING, + allowNull: false, + defaultValue: '#ffffff' + }, + use_allowance: { + type: DataTypes.BOOLEAN, + allowNull: false, + defaultValue: true + }, + limit: { + type: DataTypes.INTEGER, + allowNull: false, + defaultValue: 0 + }, + sort_order: { + type: DataTypes.INTEGER, + allowNull: false, + defaultValue: 0, + comment: 'Is used to determine sorting order of leave types' + } + }, + { + underscored: true + } + ) - generate_leave_types : function(args){ - var company = args.company; + LeaveType.associate = function(models) { + LeaveType.belongsTo(models.Company, { + as: 'company', + foreignKey: 'company_id' + }) + LeaveType.hasMany(models.Leave, { + as: 'leaves', + foreignKey: { name: 'leave_type_id', allowNull: false } + }) + } - return LeaveType.bulkCreate([ - { - name : 'Holiday', - color : '#22AA66', - companyId : company.id, - }, - { - name : 'Sick Leave', - color : '#459FF3', - companyId : company.id, - limit : 10, - use_allowance : 0, - }, - ]) - }, - }, + LeaveType.generate_leave_types = function(args) { + const company = args.company - instanceMethods : { - get_color_class : function() { - let value_in_db = this.color || ''; + return LeaveType.bulkCreate([ + { + name: 'Holiday', + color: '#22AA66', + company_id: company.id + }, + { + name: 'Sick Leave', + color: '#459FF3', + company_id: company.id, + limit: 10, + use_allowance: 0 + } + ]) + } - return value_in_db.match(/^\s*\#/) - ? 'leave_type_color_1' - : value_in_db; - }, + LeaveType.prototype.get_color_class = function() { + const value_in_db = this.color || '' - is_auto_approve : function(){ - return this.auto_approve === true; - } - } - }); + return value_in_db.match(/^\s*\#/) ? 'leave_type_color_1' : value_in_db + } - return LeaveType; -}; + LeaveType.prototype.is_auto_approve = function() { + return this.auto_approve === true + } + + return LeaveType +} diff --git a/lib/model/db/schedule.js b/lib/model/db/schedule.js index fc371f851..947f26a02 100644 --- a/lib/model/db/schedule.js +++ b/lib/model/db/schedule.js @@ -1,158 +1,182 @@ +'use strict' -'use strict'; +const moment = require('moment') +const Promise = require('bluebird') -var moment = require('moment'), - Promise = require("bluebird"); - -function works_whole_day() { return 1 } -function works_none() { return 2 } -function works_morning() { return 3 } -function works_afternoon() { return 4 } +function works_whole_day() { + return 1 +} +function works_none() { + return 2 +} +function works_morning() { + return 3 +} +function works_afternoon() { + return 4 +} function week_day_flag_setter(flag_name) { - return function(v){ this.setDataValue(flag_name, v ? works_whole_day() : works_none()) }; + return function(v) { + this.setDataValue(flag_name, v ? works_whole_day() : works_none()) + } } -module.exports = function(sequelize, DataTypes){ - - var Schedule = sequelize.define("Schedule", { - monday : { - type : DataTypes.INTEGER, - allowNull : false, - defaultValue : works_whole_day(), - set : week_day_flag_setter('monday'), - }, - tuesday : { - type : DataTypes.INTEGER, - allowNull : false, - defaultValue : works_whole_day(), - set : week_day_flag_setter('tuesday'), - }, - wednesday : { - type : DataTypes.INTEGER, - allowNull : false, - defaultValue : works_whole_day(), - set : week_day_flag_setter('wednesday'), - }, - thursday : { - type : DataTypes.INTEGER, - allowNull : false, - defaultValue : works_whole_day(), - set : week_day_flag_setter('thursday'), - }, - friday : { - type : DataTypes.INTEGER, - allowNull : false, - defaultValue : works_whole_day(), - set : week_day_flag_setter('friday'), - }, - saturday : { - type : DataTypes.INTEGER, - allowNull : false, - defaultValue : works_none(), - set : week_day_flag_setter('saturday'), - }, - sunday : { - type : DataTypes.INTEGER, - allowNull : false, - defaultValue : works_none(), - set : week_day_flag_setter('sunday'), - }, - },{ - - underscored : true, - freezeTableName : true, - tableName : 'schedule', - - indexes : [ - { fields : ['user_id'] }, - { fields : ['company_id'] }, - ], - - classMethods: { - associate : function( models ) { - Schedule.belongsTo(models.Company, {as : 'company', foreignKey : 'company_id'}); - Schedule.belongsTo(models.User, {as : 'user', foreignKey : 'user_id'}); - }, - - promise_to_build_default_for : function(args){ - var company_id = args.company_id, - user_id = args.user_id; - - if ( ! company_id && ! user_id ) { - throw new Error('Needs to have either company_id or user_id'); - } - - var default_schedule = sequelize.models.Schedule.build({ - company_id : company_id, - user_id : user_id, - }); - - return Promise.resolve(default_schedule); - }, - }, - - validate : { - relatesToEitherUserOrCompanyButNotBoth : function(){ - if ( this.company_id && this.user_id ) { - console.error('company_id='+this.company_id+', user_id='+this.user_id); - throw new Error('Schedule should be connected either to company of to user but not to both'); - } +module.exports = function(sequelize, DataTypes) { + const Schedule = sequelize.define( + 'Schedule', + { + monday: { + type: DataTypes.INTEGER, + allowNull: false, + defaultValue: works_whole_day(), + set: week_day_flag_setter('monday') }, - - relatesToUserOrCompany : function(){ - if ( ! this.company_id && ! this.user_id ){ - console.error('company_id='+this.company_id+', user_id='+this.user_id); - throw new Error('Schedule needs to be related to eaither company or user'); - } + tuesday: { + type: DataTypes.INTEGER, + allowNull: false, + defaultValue: works_whole_day(), + set: week_day_flag_setter('tuesday') }, - }, - - instanceMethods : { - is_user_specific : function() { - return !! this.user_id; + wednesday: { + type: DataTypes.INTEGER, + allowNull: false, + defaultValue: works_whole_day(), + set: week_day_flag_setter('wednesday') }, - - is_it_working_day : function(args){ - var day = args.day; - - if ( ! day ) { - throw new Error('"is_it_working_day" requires to have "day" parameter'); - } - - return this[ moment.utc(day).format('dddd').toLowerCase() ] === works_whole_day(); - }, - - works_monday : function(){ - return this.monday === works_whole_day(); + thursday: { + type: DataTypes.INTEGER, + allowNull: false, + defaultValue: works_whole_day(), + set: week_day_flag_setter('thursday') }, - - works_tuesday : function(){ - return this.tuesday === works_whole_day(); + friday: { + type: DataTypes.INTEGER, + allowNull: false, + defaultValue: works_whole_day(), + set: week_day_flag_setter('friday') }, - - works_wednesday : function(){ - return this.wednesday === works_whole_day(); + saturday: { + type: DataTypes.INTEGER, + allowNull: false, + defaultValue: works_none(), + set: week_day_flag_setter('saturday') }, - - works_thursday : function(){ - return this.thursday === works_whole_day(); - }, - - works_friday : function(){ - return this.friday === works_whole_day(); - }, - - works_saturday : function(){ - return this.saturday === works_whole_day(); - }, - - works_sunday : function(){ - return this.sunday === works_whole_day(); - }, - + sunday: { + type: DataTypes.INTEGER, + allowNull: false, + defaultValue: works_none(), + set: week_day_flag_setter('sunday') + } }, - }); - - return Schedule; -}; + { + underscored: true, + freezeTableName: true, + tableName: 'schedules', + + indexes: [{ fields: ['user_id'] }, { fields: ['company_id'] }], + + validate: { + relatesToEitherUserOrCompanyButNotBoth: function() { + if (this.company_id && this.user_id) { + console.error( + 'company_id=' + this.company_id + ', user_id=' + this.user_id + ) + throw new Error( + 'Schedule should be connected either to company of to user but not to both' + ) + } + }, + + relatesToUserOrCompany: function() { + if (!this.company_id && !this.user_id) { + console.error( + 'company_id=' + this.company_id + ', user_id=' + this.user_id + ) + throw new Error( + 'Schedule needs to be related to eaither company or user' + ) + } + } + } + } + ) + + Schedule.associate = function(models) { + Schedule.belongsTo(models.Company, { + as: 'company', + foreignKey: { name: 'company_id', allowNull: true } + }) + Schedule.belongsTo(models.User, { + as: 'user', + foreignKey: { name: 'user_id', allowNull: true } + }) + } + + Schedule.promise_to_build_default_for = function(args) { + const company_id = args.company_id + const user_id = args.user_id + + if (!company_id && !user_id) { + throw new Error('Needs to have either company_id or user_id') + } + + const default_schedule = sequelize.models.Schedule.build({ + company_id, + user_id + }) + + return Promise.resolve(default_schedule) + } + + Schedule.prototype.is_user_specific = function() { + return !!this.user_id + } + + Schedule.prototype.is_it_working_day = function(args) { + const day = args.day + + if (!day) { + throw new Error('"is_it_working_day" requires to have "day" parameter') + } + + return ( + this[ + moment + .utc(day) + .format('dddd') + .toLowerCase() + ] === works_whole_day() + ) + } + + Schedule.prototype.works_monday = function() { + return this.monday === works_whole_day() + } + + Schedule.prototype.works_tuesday = function() { + return this.tuesday === works_whole_day() + } + + Schedule.prototype.works_wednesday = function() { + return this.wednesday === works_whole_day() + } + + Schedule.prototype.works_thursday = function() { + return this.thursday === works_whole_day() + } + + Schedule.prototype.works_friday = function() { + return this.friday === works_whole_day() + } + + Schedule.prototype.works_saturday = function() { + return this.saturday === works_whole_day() + } + + Schedule.prototype.works_sunday = function() { + return this.sunday === works_whole_day() + } + + return Schedule +} diff --git a/lib/model/db/user.js b/lib/model/db/user.js index c2d5279c9..dfebb5769 100644 --- a/lib/model/db/user.js +++ b/lib/model/db/user.js @@ -1,622 +1,684 @@ -"use strict"; - -const - crypto = require('crypto'), - _ = require('underscore'), - moment = require('moment'), - Promise = require("bluebird"), - config = require('../../config'), - - UserAllowance = require('../user_allowance'), - htmlToText = require('html-to-text'), - - // User mixins - withCompanyAwareness = require('../mixin/user/company_aware'), - withAbsenceAwareness = require('../mixin/user/absence_aware'); - -const { sorter } = require("../../util"); - -const LeaveCollectionUtil = require('../leave_collection')(); +'use strict' + +const crypto = require('crypto') +const _ = require('underscore') +const moment = require('moment') +const Promise = require('bluebird') +const config = require('../../config') +const UserAllowance = require('../user_allowance') +const htmlToText = require('html-to-text') +// User mixins +const withCompanyAwareness = require('../mixin/user/company_aware') +const withAbsenceAwareness = require('../mixin/user/absence_aware') +const Sequelize = require('sequelize') +const Op = Sequelize.Op +const { sorter } = require('../../util') + +const LeaveCollectionUtil = require('../leave_collection')() module.exports = function(sequelize, DataTypes) { + const instance_methods = get_instance_methods(sequelize) - var instance_methods = get_instance_methods(sequelize); + withCompanyAwareness.call(instance_methods, sequelize) + withAbsenceAwareness.call(instance_methods, sequelize) - withCompanyAwareness.call ( instance_methods, sequelize ) ; - withAbsenceAwareness.call ( instance_methods, sequelize ) ; + const class_methods = get_class_methods(sequelize) - var class_methods = get_class_methods(sequelize); + withAssociations.call(class_methods, sequelize) + withScopes.call(class_methods, sequelize) - withAssociations.call ( class_methods, sequelize ) ; - withScopes.call ( class_methods, sequelize ) ; - - var User = sequelize.define("User", { + const User = sequelize.define( + 'User', + { // TODO add validators! - email : { - type : DataTypes.STRING, - allowNull : false + email: { + type: DataTypes.STRING, + allowNull: false }, - password : { - type : DataTypes.STRING, - allowNull : false + slack_username: { + type: DataTypes.STRING, + defaultValue: '', // Migration will not run without a default value. I don't understand why. + allowNull: true }, - name : { - type : DataTypes.STRING, - allowNull : false + password: { + type: DataTypes.STRING, + allowNull: false }, - lastname : { - type : DataTypes.STRING, - allowNull : false + name: { + type: DataTypes.STRING, + allowNull: false }, - activated : { - type : DataTypes.BOOLEAN, - allowNull : false, - defaultValue : false, - comment : 'This flag means that user account was activated, e.g. login', + lastname: { + type: DataTypes.STRING, + allowNull: false }, - admin : { - type : DataTypes.BOOLEAN, - allowNull : false, - defaultValue : false, - comment : 'Indicate if account can edit company wide settings', + activated: { + type: DataTypes.BOOLEAN, + allowNull: false, + defaultValue: false, + comment: 'This flag means that user account was activated, e.g. login' }, - auto_approve : { - type : DataTypes.BOOLEAN, - allowNull : false, - defaultValue : false, - comment : 'Indicate if leave request from current employee are auto approved', + admin: { + type: DataTypes.BOOLEAN, + allowNull: false, + defaultValue: false, + comment: 'Indicate if account can edit company wide settings' }, - start_date : { - type : DataTypes.DATE, - allowNull : false, - defaultValue : DataTypes.NOW, - comment : 'Date employee start to work for company', - get: function(){ - return moment.utc(this.getDataValue('start_date')).format('YYYY-MM-DD'); - }, + auto_approve: { + type: DataTypes.BOOLEAN, + allowNull: false, + defaultValue: false, + comment: + 'Indicate if leave request from current employee are auto approved' }, - end_date : { - type : DataTypes.DATE, - allowNull : true, - defaultValue : null, - comment : 'Date emplyee stop working for company', - get: function(){ - const endDate = this.getDataValue('end_date'); - if ( ! endDate ) { - return endDate; - } - - return moment.utc(endDate).format('YYYY-MM-DD'); - }, + start_date: { + type: DataTypes.DATE, + allowNull: false, + defaultValue: DataTypes.NOW, + comment: 'Date employee start to work for company', + get: function() { + return moment + .utc(this.getDataValue('start_date')) + .format('YYYY-MM-DD') + } }, - }, { - indexes : [ + end_date: { + type: DataTypes.DATE, + allowNull: true, + defaultValue: null, + comment: 'Date emplyee stop working for company', + get: function() { + const endDate = this.getDataValue('end_date') + if (!endDate) { + return endDate + } + + return moment.utc(endDate).format('YYYY-MM-DD') + } + } + }, + { + underscored: true, + indexes: [ { - fields : ['companyId'], + fields: ['company_id'] }, { - fields : ['lastname'], + fields: ['department_id'] }, + { + fields: ['lastname'] + } ], - classMethods: class_methods, - - instanceMethods : instance_methods, - }); - - return User; -}; - - -/* - * Convenience method that returns an object with definition of User's instance methods. - * - * */ -function get_instance_methods(sequelize) { - - return { - - is_my_password : function( password ) { - return sequelize.models.User.hashify_password( password ) === this.password; - }, - - /* - * Activate user only when it is inactive. - * Return promise that gets user's object. - * */ - maybe_activate : function(){ - if ( ! this.activated ) { - this.activated = true; + hooks: { + beforeDestroy(user, options) { + sequelize.models.DepartmentSupervisor.destroy({ + where: { user_id: user.id } + }) + sequelize.models.Leave.destroy({ where: { user_id: user.id } }) + sequelize.models.Schedule.destroy({ where: { user_id: user.id } }) + sequelize.models.Comment.destroy({ where: { by_user_id: user.id } }) + sequelize.models.UserFeed.destroy({ where: { user_id: user.id } }) + sequelize.models.UserAllowanceAdjustment.destroy({ + where: { user_id: user.id } + }) + sequelize.models.EmailAudit.destroy({ where: { user_id: user.id } }) + } } - return this.save(); - }, + } + ) + + Object.assign(User, class_methods) + Object.assign(User.prototype, instance_methods) + + /* + * Convenience method that returns an object with definition of User's instance methods. + * + * */ + function get_instance_methods(sequelize) { + return { + is_my_password: function(password) { + return ( + sequelize.models.User.hashify_password(password) === this.password + ) + }, - is_admin : function() { - return this.admin === true; - }, + /* + * Activate user only when it is inactive. + * Return promise that gets user's object. + */ + maybe_activate: function() { + if (!this.activated) { + this.activated = true + } + return this.save() + }, - /* - * Indicates is leave requests from current user are automatically approved - * */ - is_auto_approve : function(){ - return this.auto_approve === true; - }, + is_admin: function() { + return this.admin === true + }, - full_name : function() { - return this.name + ' ' + this.lastname; - }, + /* + * Indicates is leave requests from current user are automatically approved + */ + is_auto_approve: function() { + return this.auto_approve === true + }, - /* - * Indicates if the user is active - * */ - is_active : function(){ - return this.end_date === null || moment(this.end_date).isAfter(moment()); - }, + full_name: function() { + return this.name + ' ' + this.lastname + }, - // TODO VPP: rename this method as its name misleading: it returns all users - // managed by current users + user itself, so it should be something like - // "promise_all_supervised_users_plus_me" - // In fact this method probably have to be ditched in favour of more granular ones - // - promise_users_I_can_manage : async function(){ - const self = this; + /* + * Indicates if the user is active + */ + is_active: function() { + return this.end_date === null || moment(this.end_date).isAfter(moment()) + }, - let users = []; + // TODO VPP: rename this method as its name misleading: it returns all users + // managed by current users + user itself, so it should be something like + // "promise_all_supervised_users_plus_me" + // In fact this method probably have to be ditched in favour of more granular ones + // + promise_users_I_can_manage: async function() { + const self = this + + let users = [] + + if (self.is_admin()) { + // Check if current user is admin, then fetch all users form company + const company = await self.getCompany({ + scope: ['with_all_users'] + }) + + users = company.users + } else { + // If current user has any departments under supervision then get + // all users from those departments plus user himself, + // if no supervised users an array with only current user is returned + const departments = await self.promise_supervised_departments() + + users = departments.map(({ users }) => users).flat() + } - if ( self.is_admin() ) { - // Check if current user is admin, then fetch all users form company - const company = await self.getCompany({ - scope : ['with_all_users'], - }); + // Make sure current user is considered as well + users.push(self) - users = company.users; + // Remove duplicates + users = _.uniq(users, ({ id }) => id) - } else { - // If current user has any departments under supervision then get - // all users from those departments plus user himself, - // if no supervised users an array with only current user is returned - const departments = await self.promise_supervised_departments(); + // Order by last name + users = users.sort((a, b) => sorter(a.lastname, b.lastname)) - users = departments.map(({users}) => users).flat(); - } + return users + }, - // Make sure current user is considered as well - users.push(self); + /* + * Return user's manager, the head of department user belongs to + * + * */ + promise_manager: function() { + return this.getDepartment({ + scope: ['with_manager'] + }).then(department => Promise.resolve(department.manager)) + }, - users = _.uniq(users, ({id}) => id); - users = users.sort((a, b) => sorter(a.lastname, b.lastname)); + /* + * Return users who could supervise current user, that is those who could + * approve its leave requests and who can create leave requests on behalf of + * those user. + * + * */ + promise_supervisors: function() { + return this.getDepartment({ + scope: ['with_manager', 'with_supervisors'] + }).then(department => + Promise.resolve( + _.flatten([department.manager, department.supervisors]) + ) + ) + }, - return users; - }, + promise_supervised_departments: function() { + const self = this - /* - * Return user's boss, the head of department user belongs to - * - * */ - promise_boss : function(){ - return this.getDepartment({ - scope : ['with_boss'], - }) - .then(department => Promise.resolve( department.boss )); - }, + return ( + sequelize.models.DepartmentSupervisor.findAll({ + where: { user_id: self.id } + }) + // Obtain departments current user supervises as secondary supervisor + .then(department_supervisors => + department_supervisors.map(obj => obj.department_id) + ) + .then(department_ids => { + if (!department_ids) { + department_ids = [] + } + + return sequelize.models.Department.scope( + 'with_simple_users' + ).findAll({ + where: { + [Op.or]: [ + { id: { [Op.in]: department_ids } }, + { manager_id: self.id } + ] + } + }) + }) + .catch(error => { + console.error( + 'Unable to retrieve DepartmentSupervisor for user_id=' + + self.id + + ' : ' + + error, + error.stack + ) + return error + }) + ) + }, - /* - * Return users who could supervise current user, that is those who could - * approve its leave requests and who can create leave requests on behalf of - * those user. - * - * */ - promise_supervisors : function(){ - return this.getDepartment({ - scope : ['with_boss', 'with_supervisors'], - }) - .then( department => Promise.resolve( _.flatten([ department.boss, department.supervisors ]) ) ); - }, + promise_supervised_users: function() { + const self = this - promise_supervised_departments : function() { - let self = this; + return self.promise_supervised_departments().then(departments => + self.sequelize.models.User.findAll({ + where: { department_id: departments.map(d => d.id) } + }) + ) + }, - return sequelize.models.DepartmentSupervisor.findAll({ where : { user_id : self.id } }) - // Obtain departments current user supervises as secondary supervisor - .then(department_supervisors => department_supervisors.map( obj => obj.department_id )) - .then( department_ids => { + // Generate object that represent Employee allowance + promise_allowance: function(args) { + args = args || {} + // Override user to be current one + args.user = this + return UserAllowance.promise_allowance(args) + }, - if ( ! department_ids ) { - department_ids = []; + reload_with_leave_details: function(args) { + const self = this + const dbModel = self.sequelize.models + + return Promise.join( + self + .promise_my_active_leaves(args) + .then(leaves => + LeaveCollectionUtil.enrichLeavesWithComments({ leaves, dbModel }) + ), + self.getDepartment(), + self.promise_schedule_I_obey(), + (leaves, department, schedule) => { + self.my_leaves = leaves + self.department = department + + // Note: we do not do anything with scheduler as "promise_schedule_I_obey" + // sets the "cached_schedule" attribute under the hood, which is used in + // synchronous code afterwards. Yes... itaza`z is silly, but it is where we are + // at thi moment after mixing non blocking and blocking code together... + // + return Promise.resolve(self) } - - return sequelize.models.Department.scope('with_simple_users').findAll({ - where : { - $or : [ - { id : department_ids }, - { bossId : self.id }, - ] - } - }); - }); - }, - - promise_supervised_users : function () { - let self = this; - - return self - .promise_supervised_departments() - .then(departments => { - return self.Model.findAll({ where : { DepartmentId : departments.map(d => d.id ) } }); + ).catch(error => { + console.error( + 'Unable to load leaves details for user ' + + self.email + + ' : ' + + error, + error.stack + ) + return Promise.reject(error) }) - }, + }, + // This method reload user object to have all necessary information to render + // each page + reload_with_session_details: function() { + const self = this + + return Promise.join( + self.promise_users_I_can_manage(), + self.get_company_with_all_leave_types(), + self.promise_schedule_I_obey(), + (users, company, schedule) => { + self.supervised_users = users || [] + self.company = company + + // Note: we do not do anything with scheduler as "promise_schedule_I_obey" + // sets the "cached_schedule" attribute under the hood, which is used in + // synchronous code afterwards. Yes... it is silly, but it is where we are + // at thi moment after mixing non blocking and blocking code together... + + return Promise.resolve(self) + } + ).catch(error => { + console.error( + 'Unable to load session details for user ' + + self.email + + ' : ' + + error, + error.stack + ) + return Promise.reject(error) + }) + }, - // Generate object that represent Employee allowance - promise_allowance : function(args) { - args = args || {}; - // Override user to be current one - args.user = this; - return UserAllowance.promise_allowance(args); - }, + remove: function() { + const self = this - reload_with_leave_details : function(args){ - const self = this; - const dbModel = self.sequelize.models; - - return Promise.join( - self.promise_my_active_leaves(args) - .then(leaves => LeaveCollectionUtil.enrichLeavesWithComments({leaves, dbModel})), - self.getDepartment(), - self.promise_schedule_I_obey(), - function(leaves, department, schedule){ - self.my_leaves = leaves; - self.department = department; - - // Note: we do not do anything with scheduler as "promise_schedule_I_obey" - // sets the "cached_schedule" attribute under the hood, which is used in - // synchronous code afterwards. Yes... itaza`z is silly, but it is where we are - // at thi moment after mixing non blocking and blocking code together... - // - return Promise.resolve(self); + // make sure I am not admin, otherwise throw an error + if (self.is_admin()) { + throw new Error('Cannot remove administrator user') } - ); - - }, - // This method reload user object to have all necessary information to render - // each page - reload_with_session_details : function(){ - var self = this; - return Promise.join( - self.promise_users_I_can_manage(), - self.get_company_with_all_leave_types(), - self.promise_schedule_I_obey(), - function(users, company, schedule){ - self.supervised_users = users || []; - self.company = company; - - // Note: we do not do anything with scheduler as "promise_schedule_I_obey" - // sets the "cached_schedule" attribute under the hood, which is used in - // synchronous code afterwards. Yes... it is silly, but it is where we are - // at thi moment after mixing non blocking and blocking code together... - - return Promise.resolve(self); - }); - }, + // make sure I am not supervisor, otherwise throw an error + return ( + self + .promise_supervised_departments() + .then(departments => { + if (departments.length > 0) { + throw new Error('Cannot remove supervisor') + } + + return self.getMy_leaves() + }) + .then(leaves => + // remove all leaves + Promise.all(_.map(leaves, leave => leave.destroy())) + ) + // remove user record + .then(() => self.destroy()) + ) + }, - remove : function() { - var self = this; + get_reset_password_token: function() { + const self = this - // make sure I am not admin, otherwise throw an error - if (self.is_admin()) { - throw new Error('Cannot remove administrator user'); - } - - // make sure I am not supervisor, otherwise throw an error - return self.promise_supervised_departments() - .then(departments => { - if (departments.length > 0){ - throw new Error("Cannot remove supervisor"); - } + return Buffer.from( + self.email + + ' ' + + this.sequelize.models.User.hashify_password(self.password) + ).toString('base64') + }, - return self.getMy_leaves(); - }) - .then(function(leaves){ - // remove all leaves - return Promise.all( - _.map( leaves, function(leave){ return leave.destroy(); }) - ); - }) + // Accept an object that represent email to be sent to current user and + // record it into the corresponding audit table + // + record_email_addressed_to_me: function(email_obj) { + // validate email object to contain all necessary fields + if ( + !email_obj || + !email_obj.hasOwnProperty('subject') || + !email_obj.subject || + !email_obj.hasOwnProperty('body') || + !email_obj.body + ) { + throw new Error( + 'Got incorrect parameters. There should be an object ' + + 'to represent and email and contain subject and body' + ) + } - // remove user record - .then(function(){ - return self.destroy(); + const promise_action = this.sequelize.models.EmailAudit.create({ + email: this.email, + subject: htmlToText.fromString(email_obj.subject), + body: htmlToText.fromString(email_obj.body), + user_id: this.id, + company_id: this.company_id }) - }, - - get_reset_password_token : function(){ - var self = this; - - return new Buffer( self.email + ' ' + self.Model.hashify_password( self.password ) ).toString('base64'); - }, - - // Accept an object that represent email to be sent to current user and - // record it into the corresponding audit table - // - record_email_addressed_to_me : function(email_obj) { - - // validate email object to contain all necessary fields - if ( ! email_obj || - ! email_obj.hasOwnProperty('subject') || - ! email_obj.subject || - ! email_obj.hasOwnProperty('body') || - ! email_obj.body - ) { - throw new Error( - 'Got incorrect parameters. There should be an object '+ - 'to represent and email and contain subject and body' - ); - } - - const promise_action = this.sequelize.models.EmailAudit.create({ - email : this.email, - subject : htmlToText.fromString(email_obj.subject), - body : htmlToText.fromString(email_obj.body), - user_id : this.id, - company_id : this.companyId, - }); - - return promise_action; - }, + return promise_action + }, - promise_schedule_I_obey : function(){ - var self = this; + promise_schedule_I_obey: function() { + const self = this - if ( self.cached_schedule ) { - return Promise.resolve( self.cached_schedule ); - } + if (self.cached_schedule) { + return Promise.resolve(self.cached_schedule) + } - return self.sequelize.models.Schedule - .findAll({ - where : { - $or : [ - { user_id : self.id }, - { company_id : self.companyId }, - ] + return self.sequelize.models.Schedule.findAll({ + where: { + [Op.or]: [{ user_id: self.id }, { company_id: self.company_id }] } - }) - .then(function(schedules){ - + }).then(schedules => { // no schedules for current user in DB, return default one if (schedules.length === 0) { - return self.sequelize.models.Schedule - .promise_to_build_default_for({ company_id : self.companyId }) - .then(function(sch){ self.cached_schedule = sch; return Promise.resolve(sch) }); + return self.sequelize.models.Schedule.promise_to_build_default_for({ + company_id: self.company_id + }).then(sch => { + self.cached_schedule = sch + return Promise.resolve(sch) + }) } // there are two schedules, presumably one company wide and another // is user specific, return later one if (schedules.length === 2) { return Promise.resolve( - _.find(schedules, function(sch){ return sch.is_user_specific() }) - ) - .then(function(sch){ self.cached_schedule = sch; return Promise.resolve(sch) }); + _.find(schedules, sch => sch.is_user_specific()) + ).then(sch => { + self.cached_schedule = sch + return Promise.resolve(sch) + }) } // single schedule means it is company wide one - return Promise.resolve( schedules.pop() ) - .then(function(sch){ self.cached_schedule = sch; return Promise.resolve(sch) }); - }); - }, - - }; - -}; - -function get_class_methods(sequelize) { - return { - - /* hashify_password( password_string ) : string - * - * For provided string return hashed string. - * - * */ - hashify_password : function( password ) { - return crypto - .createHash('md5') - .update( - password + config.get('crypto_secret'), - (config.get('crypto_hash_encoding') || 'binary') - ) - .digest('hex'); - }, - - - get_user_by_reset_password_token : function(token) { - var self = this, - unpacked_token = new Buffer(token, 'base64').toString('ascii'), - email_and_hashed_password = unpacked_token.split(/\s/); - - return self.find_by_email(email_and_hashed_password[0]) - .then(function(user){ - if (user && self.hashify_password(user.password) === email_and_hashed_password[1]) { - return Promise.resolve(user); - } else { - return Promise.resolve(); - } + return Promise.resolve(schedules.pop()).then(sch => { + self.cached_schedule = sch + return Promise.resolve(sch) + }) }) - }, - - // Get active user by provided email address - find_by_email : function( email ) { - - // TODO validate email - - var condition = { email : email }; - var active_users_filter = this.get_active_user_filter(); - for (var attrname in active_users_filter) { - condition[attrname] = active_users_filter[attrname]; } + } + } + + function get_class_methods(sequelize) { + return { + /* hashify_password( password_string ) : string + * + * For provided string return hashed string. + * + * */ + hashify_password: function(password) { + return crypto + .createHash('md5') + .update( + password + config.get('crypto_secret'), + config.get('crypto_hash_encoding') || 'binary' + ) + .digest('hex') + }, - return this.find({ where : condition }); - }, - - find_by_id : function(id) { - return this.find({ where : {id : id}}); - }, - - /* - * Create new admin user within new environment - company etc - * */ - register_new_admin_user : function(attributes){ - - // TODO add parameters validation - - // Make sure we hash the password before storing it to DB - attributes.password = this.hashify_password(attributes.password); - - var new_departments, - new_user, - country_code = attributes.country_code, - timezone = attributes.timezone, - company_name = attributes.company_name; - - delete attributes.company_name; - delete attributes.country_code; - - return sequelize.models.User.find_by_email( attributes.email ) - .then(function(existing_user){ - if (existing_user) { - const error = new Error('Email is already used') - error.show_to_user = true; - throw error; - } - - if (attributes.name.toLowerCase().indexOf('http') >= 0) { - const error = new Error('Name cannot have links'); - error.show_to_user = true; - throw error; + get_user_by_reset_password_token: function(token) { + const self = this + const unpacked_token = Buffer.from(token, 'base64').toString('ascii') + const email_and_hashed_password = unpacked_token.split(/\s/) + + return self.find_by_email(email_and_hashed_password[0]).then(user => { + if ( + user && + self.hashify_password(user.password) === + email_and_hashed_password[1] + ) { + return Promise.resolve(user) + } else { + return Promise.resolve() } - - return sequelize.models.Company - .create_default_company({ - name : company_name, - country_code : country_code, - timezone : timezone, - }); - }) - - // Make sure new user is going to be linked with a company - .then(function(company){ - - attributes.companyId = company.id; - attributes.admin = true; - - return company.getDepartments(); - }) - - // Make sure new user is linked with department - .then(function(departments){ - - new_departments = departments; - - attributes.DepartmentId = departments[0].id; - - return sequelize.models.User.create( attributes ); - }) - - // Make sure new departments know who is their boss - .then(function(user){ - new_user = user; - - return Promise.all(_.map(new_departments, function(department){ - department.bossId = user.id; - return department.save(); - })); }) + }, - // Return promise with newly created user - .then(function(){ - return Promise.resolve(new_user); - }); - }, + // Get active user by provided email address + find_by_email: function(email) { + // TODO validate email - get_active_user_filter : function(){ - return { - $or : [ - { end_date : {$eq : null}}, - { end_date : {$gte : moment.utc().startOf('day').format('YYYY-MM-DD') }}, - ], - }; - }, - - }; -}; // END of class methods - - -// Mixin-like function that injects definition of User's associations into supplied object. -// (Define relations between User class and other entities in the domain). -// -function withAssociations() { - - this.associate = function(models){ - - models.User.belongsTo(models.Company, { - as : 'company', - }); - models.User.belongsTo(models.Department, { - as : 'department', - foreignKey : 'DepartmentId', - }); - models.User.hasMany(models.Leave, { - as : 'my_leaves', - foreignKey : 'userId', - }); - models.User.hasMany(models.UserFeed, { - as : 'feeds', - foreignKey : 'userId', - }); - models.User.hasMany(models.UserAllowanceAdjustment, { - as : 'adjustments', - foreignKey : 'user_id', - }); - }; -} + const condition = { email } + const active_users_filter = this.get_active_user_filter() + for (const attrname in active_users_filter) { + condition[attrname] = active_users_filter[attrname] + } + return this.findOne({ where: condition }) + }, -function withScopes() { + find_by_id: function(id) { + return this.findOne({ where: { id } }) + }, - this.loadScope = function(models) { + /* + * Create new admin user within new environment - company etc + * */ + register_new_admin_user: function(attributes) { + // TODO add parameters validation + + // Make sure we hash the password before storing it to DB + attributes.password = this.hashify_password(attributes.password) + + let new_departments + let new_user + const country_code = attributes.country_code + const timezone = attributes.timezone + const company_name = attributes.company_name + + delete attributes.company_name + delete attributes.country_code + + return ( + sequelize.models.User.find_by_email(attributes.email) + .then(existing_user => { + if (existing_user) { + const error = new Error('Email is already used') + error.show_to_user = true + throw error + } + + if (attributes.name.toLowerCase().indexOf('http') >= 0) { + const error = new Error('Name cannot have links') + error.show_to_user = true + throw error + } + + return sequelize.models.Company.create_default_company({ + name: company_name, + country_code, + timezone + }) + }) + + // Make sure new user is going to be linked with a company + .then(company => { + attributes.company_id = company.id + attributes.admin = true + + return company.getDepartments() + }) + + // Make sure new user is linked with department + .then(departments => { + new_departments = departments + + attributes.department_id = departments[0].id + + return sequelize.models.User.create(attributes) + }) + + // Make sure new departments know who is their manager + .then(user => { + new_user = user + + return Promise.all( + _.map(new_departments, department => { + department.manager_id = user.id + return department.save() + }) + ) + }) + + // Return promise with newly created user + .then(() => Promise.resolve(new_user)) + ) + }, - models.User.addScope( - 'active', - function () { - return { where : models.User.get_active_user_filter() }; + get_active_user_filter: function() { + return { + [Op.or]: [ + { end_date: { [Op.eq]: null } }, + { + end_date: { + [Op.gte]: moment + .utc() + .startOf('day') + .format('YYYY-MM-DD') + } + } + ] + } } - ); - - models.User.addScope( - 'withDepartments', - () => ({ - include: [{ - model: models.Department, - as: 'department', - }], + } + } // END of class methods + + // Mixin-like function that injects definition of User's associations into supplied object. + // (Define relations between User class and other entities in the domain). + // + function withAssociations() { + this.associate = function(models) { + models.User.belongsTo(models.Company, { + as: 'company', + foreignKey: { name: 'company_id', allowNull: false } + }) + models.User.belongsTo(models.Department, { + as: 'department', + foreignKey: { name: 'department_id', allowNull: false } + }) + models.User.hasMany(models.Leave, { + as: 'my_leaves', + foreignKey: { name: 'user_id', allowNull: false } + }) + models.User.hasMany(models.UserFeed, { + as: 'feeds', + foreignKey: { name: 'user_id', allowNull: false } }) - ); - - models.User.addScope( - 'with_simple_leaves', - () => ({ - include : [{ - model : models.Leave, - as : 'my_leaves', - where : { - $and : [ - { status : { $ne : models.Leave.status_rejected() } }, - { status : { $ne : models.Leave.status_canceled() } }, - ], - }, - }], + models.User.hasMany(models.UserAllowanceAdjustment, { + as: 'adjustments', + foreignKey: { name: 'user_id', allowNull: false } }) - ); + } + } + + function withScopes() { + this.loadScope = function(models) { + models.User.addScope('active', () => ({ + where: models.User.get_active_user_filter() + })) + + models.User.addScope('withDepartments', () => ({ + include: [ + { + model: models.Department, + as: 'department' + } + ] + })) + + models.User.addScope('with_simple_leaves', () => ({ + include: [ + { + model: models.Leave, + as: 'my_leaves', + where: { + $and: [ + { status: { $ne: models.Leave.status_rejected() } }, + { status: { $ne: models.Leave.status_canceled() } } + ] + } + } + ] + })) + } + } - }; + return User } diff --git a/lib/model/db/user_allowance_adjustment.js b/lib/model/db/user_allowance_adjustment.js index 3ead47679..a68c87b49 100644 --- a/lib/model/db/user_allowance_adjustment.js +++ b/lib/model/db/user_allowance_adjustment.js @@ -1,50 +1,53 @@ +'use strict' -"use strict"; +const moment = require('moment') -const moment = require('moment'); - -module.exports = function(sequelize, DataTypes){ - let UserAllowanceAdjustment = sequelize.define("UserAllowanceAdjustment", { - year : { - type : DataTypes.INTEGER, - allowNull : false, - defaultValue : moment.utc().format('YYYY'), - comment : 'Year when adjustment is applied', - }, - adjustment : { - type : DataTypes.INTEGER, - allowNull : false, - defaultValue : 0, - comment : 'Adjustment to allowance in current year', - }, - carried_over_allowance : { - type : DataTypes.INTEGER, - allowNull : false, - defaultValue : 0, - comment : 'Additional allowance to use based on un-used holidays in previous year', - }, - }, { - underscored : true, - freezeTableName : true, - timestamps : true, - createdAt : 'created_at', - updatedAt : false, - tableName : 'user_allowance_adjustment', - indexes : [{ - fields : [ 'user_id', 'year' ], - unique : true, - }], - - classMethods : { - associate : function(models) { - UserAllowanceAdjustment.belongsTo(models.User, { - as : 'user', - foreignKey : 'user_id', - }); +module.exports = function(sequelize, DataTypes) { + const UserAllowanceAdjustment = sequelize.define( + 'UserAllowanceAdjustment', + { + year: { + type: DataTypes.INTEGER, + allowNull: false, + defaultValue: moment.utc().format('YYYY'), + comment: 'Year when adjustment is applied' + }, + adjustment: { + type: DataTypes.INTEGER, + allowNull: false, + defaultValue: 0, + comment: 'Adjustment to allowance in current year' }, + carried_over_allowance: { + type: DataTypes.INTEGER, + allowNull: false, + defaultValue: 0, + comment: + 'Additional allowance to use based on un-used holidays in previous year' + } }, + { + underscored: true, + freezeTableName: true, + timestamps: true, + createdAt: 'created_at', + updatedAt: false, + tableName: 'user_allowance_adjustment', + indexes: [ + { + fields: ['user_id', 'year'], + unique: true + } + ] + } + ) - }); + UserAllowanceAdjustment.associate = function(models) { + UserAllowanceAdjustment.belongsTo(models.User, { + as: 'user', + foreignKey: { name: 'user_id', allowNull: false } + }) + } - return UserAllowanceAdjustment; -}; + return UserAllowanceAdjustment +} diff --git a/lib/model/db/user_feed.js b/lib/model/db/user_feed.js index 3f7f45c45..027b63645 100644 --- a/lib/model/db/user_feed.js +++ b/lib/model/db/user_feed.js @@ -1,66 +1,66 @@ -"use strict"; +'use strict' -var - uuid = require('node-uuid'); +const uuid = require('node-uuid') module.exports = function(sequelize, DataTypes) { - var UserFeed = sequelize.define("UserFeed", { - name : { - type : DataTypes.STRING, - allowNull : false, - }, - feed_token : { - type : DataTypes.STRING, - allowNull : false, - }, - type : { - // NOTE: 'wallchart' and 'teamview' are essentially the same thing - // later one used to be know as former, from now on use 'teamview' - // and keep old what for data compatibility - type : DataTypes.ENUM('calendar', 'wallchart', 'teamview', 'company'), - allowNull : false, + const UserFeed = sequelize.define( + 'UserFeed', + { + name: { + type: DataTypes.STRING, + allowNull: false + }, + feed_token: { + type: DataTypes.STRING, + allowNull: false + }, + type: { + // NOTE: 'wallchart' and 'teamview' are essentially the same thing + // later one used to be know as former, from now on use 'teamview' + // and keep old what for data compatibility + type: DataTypes.ENUM('calendar', 'wallchart', 'teamview', 'company'), + allowNull: false + } }, - }, { + { + underscored: true + } + ) - classMethods: { - associate : function( models ) { - UserFeed.belongsTo(models.User, {as : 'user'}); - }, + UserFeed.associate = function(models) { + UserFeed.belongsTo(models.User, { + as: 'user', + foreignKey: { name: 'user_id', allowNull: false } + }) + } - promise_new_feed : function(args){ - var self = this, - user = args.user, - type = args.type; + UserFeed.promise_new_feed = function(args) { + const self = this + const user = args.user + const type = args.type - return self - .find({ where : {userId : user.id, type : type} }) - .then(function(feed){ - if ( feed ) { - feed.feed_token = uuid.v4(); - return feed.save(); - } else { - return self.create({ - name : "Calendar Feed", - feed_token : uuid.v4(), - type : type, - userId : user.id, - }); - } - }) - }, + return self.findOne({ where: { user_id: user.id, type } }).then(feed => { + if (feed) { + feed.feed_token = uuid.v4() + return feed.save() + } else { + return self.create({ + name: 'Calendar Feed', + feed_token: uuid.v4(), + type, + user_id: user.id + }) + } + }) + } - }, - - instanceMethods : { - is_calendar : function() { - return this.type === 'calendar'; - }, + UserFeed.prototype.is_calendar = function() { + return this.type === 'calendar' + } - is_team_view : function(){ - return this.type === 'wallchart' || this.type === 'teamview'; - }, - }, - }); + UserFeed.prototype.is_team_view = function() { + return this.type === 'wallchart' || this.type === 'teamview' + } - return UserFeed; -}; + return UserFeed +} diff --git a/lib/model/leave/index.js b/lib/model/leave/index.js index 5cb4cc5e3..febfb4d9a 100644 --- a/lib/model/leave/index.js +++ b/lib/model/leave/index.js @@ -1,144 +1,148 @@ - -"use strict" - -const - Promise = require('bluebird'), - Joi = require('joi'), - moment = require('moment'), - Exception = require('../../error'), - {commentLeave} = require('../comment'), - Models = require('../db'); - -const - schemaCreateNewLeave = Joi.object().required().keys({ - for_employee : Joi.object().required(), - of_type : Joi.object().required(), - with_parameters : Joi.object().required(), - }); +'use strict' + +const Promise = require('bluebird') +const Joi = require('joi') +const moment = require('moment') +const Exception = require('../../error') +const { commentLeave } = require('../comment') +const Models = require('../db') + +const schemaCreateNewLeave = Joi.object() + .required() + .keys({ + for_employee: Joi.object().required(), + of_type: Joi.object().required(), + with_parameters: Joi.object().required() + }) /* * Create new leave for provided parameters. * Returns promise that is resolved with newly created leave row * */ -function createNewLeave(args){ - - args = Joi.attempt( - args, - schemaCreateNewLeave, - "Failed to validate arguments" - ); +function createNewLeave(args) { + args = Joi.attempt(args, schemaCreateNewLeave, 'Failed to validate arguments') - const - employee = args.for_employee, - leave_type = args.of_type, - valide_attributes = args.with_parameters; + const employee = args.for_employee + const leave_type = args.of_type + const valide_attributes = args.with_parameters - const - start_date = moment.utc(valide_attributes.from_date), - end_date = moment.utc(valide_attributes.to_date); + const start_date = moment.utc(valide_attributes.from_date) + const end_date = moment.utc(valide_attributes.to_date) // Check that start date is not bigger then end one - if ( start_date.toDate() > end_date.toDate() ) { + if (start_date.toDate() > end_date.toDate()) { Exception.throwUserError({ - user_error : "Start date is later than end date", - system_error : `Failed to add new Leave for user ${ employee.id } ` - `because start date ${ start_date } happnned to be after end date ${ end_date }`, - }); + user_error: 'Start date is later than end date', + system_error: `Failed to add new Leave for user ${ + employee.id + } ``because start date ${start_date} happnned to be after end date ${end_date}` + }) } - const comment = valide_attributes.reason, - companyId = employee.companyId; + const comment = valide_attributes.reason + const company_id = employee.company_id // Make sure that booking to be created is not going to ovelap with // any existing bookings - return Promise - - .try(() => employee.validate_overlapping(valide_attributes)) - .then(() => employee.promise_boss()) + return Promise.try(() => employee.validate_overlapping(valide_attributes)) + .then(() => employee.promise_manager()) .then(main_supervisor => { - - const new_leave_status = Models.Leave.does_skip_approval(employee, leave_type) + const new_leave_status = Models.Leave.does_skip_approval( + employee, + leave_type + ) ? Models.Leave.status_approved() - : Models.Leave.status_new(); + : Models.Leave.status_new() // Following statement creates in memory only leave object // it is not in database until .save() method is called - return Promise.resolve(Models.Leave.build({ - userId : employee.id, - leaveTypeId : leave_type.id, - status : new_leave_status, - approverId : main_supervisor.id, - employee_comment : valide_attributes.reason, - - date_start : start_date.format('YYYY-MM-DD'), - date_end : end_date.format('YYYY-MM-DD'), - day_part_start : valide_attributes.from_date_part, - day_part_end : valide_attributes.to_date_part, - })); + return Promise.resolve( + Models.Leave.build({ + user_id: employee.id, + leave_type_id: leave_type.id, + status: new_leave_status, + approver_id: main_supervisor.id, + employee_comment: valide_attributes.reason, + + date_start: start_date.format('YYYY-MM-DD'), + date_end: end_date.format('YYYY-MM-DD'), + day_part_start: valide_attributes.from_date_part, + day_part_end: valide_attributes.to_date_part + }) + ) }) - .then(leave_to_create => employee - .validate_leave_fits_into_remaining_allowance({ - year : start_date, - leave_type : leave_type, - leave : leave_to_create, - }) - .then(() => leave_to_create.save()) + .then(leave_to_create => + employee + .validate_leave_fits_into_remaining_allowance({ + year: start_date, + leave_type, + leave: leave_to_create + }) + .then(() => leave_to_create.save()) ) - .then(leave => commentLeaveIfNeeded({leave,comment,companyId}).then(() => leave)) - .then(leave => Promise.resolve(leave)); + .then(leave => + commentLeaveIfNeeded({ leave, comment, company_id }).then(() => leave) + ) + .then(leave => Promise.resolve(leave)) } -const commentLeaveIfNeeded = ({leave,comment, companyId}) => { - return comment ? commentLeave({leave,comment,companyId}) : Promise.resolve(); -}; - -const getLeaveForUserView = async ({actingUser, leaveId, dbModel}) => { +const commentLeaveIfNeeded = ({ leave, comment, company_id }) => + comment ? commentLeave({ leave, comment, company_id }) : Promise.resolve() +const getLeaveForUserView = async ({ actingUser, leaveId, dbModel }) => { const [leave] = await dbModel.Leave.findAll({ where: { - id: leaveId, + id: leaveId }, - include: [{ - model: dbModel.User, - as: 'user', - where: { - companyId: actingUser.companyId, + include: [ + { + model: dbModel.User, + as: 'user', + where: { + company_id: actingUser.company_id + } } - }], - }); + ] + }) if (!leave) { - throw new Error(`User [${actingUser.id}] tried to access leave [${leaveId}] which does not belong to the same company.`); + throw new Error( + `User [${ + actingUser.id + }] tried to access leave [${leaveId}] which does not belong to the same company.` + ) } - return leave; -}; + return leave +} -const doesUserHasExtendedViewOfLeave = async ({user, leave}) => { - if (user.companyId !== (await leave.getUser()).companyId) { - throw new Error(`User [${user.id}] and leave [${leave.id}] do not share company.`); +const doesUserHasExtendedViewOfLeave = async ({ user, leave }) => { + if (user.company_id !== (await leave.getUser()).company_id) { + throw new Error( + `User [${user.id}] and leave [${leave.id}] do not share company.` + ) } - let extendedView = false; + let extendedView = false if (user.is_admin()) { - extendedView = true; + extendedView = true } - if (! extendedView) { - const reports = await user.promise_supervised_users(); + if (!extendedView) { + const reports = await user.promise_supervised_users() - if (reports.filter(u => `${u.id}` === `${leave.userId}`).length > 0) { - extendedView = true; + if (reports.filter(u => `${u.id}` === `${leave.user_id}`).length > 0) { + extendedView = true } } - return extendedView; -}; + return extendedView +} module.exports = { createNewLeave, doesUserHasExtendedViewOfLeave, - getLeaveForUserView, + getLeaveForUserView } diff --git a/lib/model/leave_collection.js b/lib/model/leave_collection.js index f73a669c1..717959363 100644 --- a/lib/model/leave_collection.js +++ b/lib/model/leave_collection.js @@ -1,38 +1,35 @@ +'use strict' -"use strict"; - -var - Promise = require('bluebird'), - moment = require('moment'), - _ = require('underscore'), - config = require('../config'); +const Promise = require('bluebird') +const moment = require('moment') +const _ = require('underscore') +const { Op } = require('sequelize') function promise_to_group_leaves(leaves) { - - if ( ! leaves ) { - throw new Error('Did not get "leaves" in promise_to_group_leaves'); + if (!leaves) { + throw new Error('Did not get "leaves" in promise_to_group_leaves') } - let grouped_leaves = {}; + let grouped_leaves = {} // Group leaves by years leaves.forEach(leave => { - let year = moment.utc(leave.get_start_leave_day().date).format('YYYY'); + const year = moment.utc(leave.get_start_leave_day().date).format('YYYY') - if ( ! grouped_leaves[year]) { - grouped_leaves[ year ] = { - year : year, - leaves : [], - }; + if (!grouped_leaves[year]) { + grouped_leaves[year] = { + year, + leaves: [] + } } - grouped_leaves[ year ].leaves.push(leave); - }); + grouped_leaves[year].leaves.push(leave) + }) // Sort year groups - grouped_leaves = _ - .values( grouped_leaves ) - .sort((a,b) => a.year > b.year ? -1 : a.year < b.year ? 1 : 0); + grouped_leaves = _.values(grouped_leaves).sort((a, b) => + a.year > b.year ? -1 : a.year < b.year ? 1 : 0 + ) // Calculate total allowance deduction per group grouped_leaves.forEach(group => { @@ -40,10 +37,10 @@ function promise_to_group_leaves(leaves) { group.leaves.map(leave => leave.get_deducted_days_number()), (memo, number) => memo + number, 0 - ); - }); + ) + }) - return Promise.resolve(grouped_leaves); + return Promise.resolve(grouped_leaves) } /* @@ -52,33 +49,38 @@ function promise_to_group_leaves(leaves) { * */ function promise_to_sort_leaves(leaves) { - return Promise.resolve( leaves.sort( - (a,b) => a.date_start > b.date_start - ? -1 : a.date_start < b.date_start - ? 1 : 0 - )); + return Promise.resolve( + leaves.sort((a, b) => + a.date_start > b.date_start ? -1 : a.date_start < b.date_start ? 1 : 0 + ) + ) } -const enrichLeavesWithComments = async ({leaves, dbModel}) => { - const comments = await dbModel.Comment.findAll({where: { - entityId: { $in: leaves.map(l => l.id)}, - entityType: dbModel.Comment.getEntityTypeLeave(), - }}); +const enrichLeavesWithComments = async ({ leaves, dbModel }) => { + const comments = await dbModel.Comment.findAll({ + where: { + entity_id: { [Op.in]: leaves.map(l => l.id) }, + entity_type: dbModel.Comment.getEntityTypeLeave() + } + }) // Map comments by Leave ID - const commentMap = comments.reduce((acc, c) => {acc[c.entityId]=c; return acc}, {}); + const commentMap = comments.reduce((acc, c) => { + acc[c.entity_id] = c + return acc + }, {}) leaves .filter(l => commentMap[l.id] !== undefined) - .forEach(l => l.comment = commentMap[l.id]); + .forEach(l => (l.comment = commentMap[l.id])) - return leaves; -}; + return leaves +} -module.exports = function(){ +module.exports = function() { return { enrichLeavesWithComments, promise_to_group_leaves, - promise_to_sort_leaves, - }; -}; + promise_to_sort_leaves + } +} diff --git a/lib/model/leave_day.js b/lib/model/leave_day.js index 59da8453d..b94cf48c3 100644 --- a/lib/model/leave_day.js +++ b/lib/model/leave_day.js @@ -9,59 +9,63 @@ * * */ -"use strict"; +'use strict' -var - _ = require('underscore'), - moment = require('moment'); +const _ = require('underscore') +const moment = require('moment') function LeaveDay(args) { - // Make sure all required data is provided - _.each( - ['date', 'day_part', 'sequelize', 'leave_type_id'], - function(property){ - if (! _.has(args, property)) { - throw new Error('No mandatory '+property+' was provided'); - } + _.each(['date', 'day_part', 'sequelize', 'leave_type_id'], property => { + if (!_.has(args, property)) { + throw new Error('No mandatory ' + property + ' was provided') } - ); + }) - this.date = args.date; - this.day_part = args.day_part; - this.sequelize = args.sequelize; - this.morning_leave_type_id = this.afternoon_leave_type_id = args.leave_type_id; -}; + this.date = args.date + this.day_part = args.day_part + this.sequelize = args.sequelize + this.morning_leave_type_id = this.afternoon_leave_type_id = args.leave_type_id +} -LeaveDay.prototype.is_all_day_leave = function(){ - return String(this.day_part) === String(this.sequelize.models.Leave.leave_day_part_all()); -}; +LeaveDay.prototype.is_all_day_leave = function() { + return ( + String(this.day_part) === + String(this.sequelize.models.Leave.leave_day_part_all()) + ) +} -LeaveDay.prototype.is_morning_leave = function(){ - return String(this.day_part) === String(this.sequelize.models.Leave.leave_day_part_morning()); -}; +LeaveDay.prototype.is_morning_leave = function() { + return ( + String(this.day_part) === + String(this.sequelize.models.Leave.leave_day_part_morning()) + ) +} -LeaveDay.prototype.is_afternoon_leave = function(){ - return String(this.day_part) === String(this.sequelize.models.Leave.leave_day_part_afternoon()); -}; +LeaveDay.prototype.is_afternoon_leave = function() { + return ( + String(this.day_part) === + String(this.sequelize.models.Leave.leave_day_part_afternoon()) + ) +} -LeaveDay.prototype.get_morning_leave_type_id = function(){ - return String(this.morning_leave_type_id); -}; +LeaveDay.prototype.get_morning_leave_type_id = function() { + return String(this.morning_leave_type_id) +} -LeaveDay.prototype.get_afternoon_leave_type_id = function(){ - return String(this.afternoon_leave_type_id); -}; +LeaveDay.prototype.get_afternoon_leave_type_id = function() { + return String(this.afternoon_leave_type_id) +} // Set current object to be as one for All day leave, but the state is not // saved into database. It is used when showing calendar to user and // there are two half days that fit into one whole day LeaveDay.prototype.pretend_to_be_full_day = function() { - return this.day_part = this.sequelize.models.Leave.leave_day_part_all(); -}; + return (this.day_part = this.sequelize.models.Leave.leave_day_part_all()) +} -LeaveDay.prototype.get_pretty_date = function(){ - return moment.utc(this.date).format('YYYY-MM-DD'); -}; +LeaveDay.prototype.get_pretty_date = function() { + return moment.utc(this.date).format('YYYY-MM-DD') +} -module.exports = LeaveDay; +module.exports = LeaveDay diff --git a/lib/model/leave_request_parameters.js b/lib/model/leave_request_parameters.js index 1fde7796d..5254b41f0 100644 --- a/lib/model/leave_request_parameters.js +++ b/lib/model/leave_request_parameters.js @@ -1,105 +1,120 @@ +'use strict' -'use strict'; - -var - _ = require('underscore'), - model = require('../model/db'), - moment = require('moment'); +const _ = require('underscore') +const model = require('../model/db') +const moment = require('moment') function LeaveRequest(args) { - var me = this; - - // Make sure all required data is provided - _.each( - [ - 'leave_type','from_date','from_date_part', - 'to_date', 'to_date_part', 'reason' - ], - function(property){ - if (! _.has(args, property)) { - throw new Error('No mandatory '+property+' was provided to LeaveRequest constructor'); - } - } - ); - - // From date should not be bigger then to - if (moment.utc(args.from_date).toDate() > moment.utc(args.to_date).toDate()){ - throw new Error( 'From date should be before To date at LeaveRequest constructor' ); + const me = this + + // Make sure all required data is provided + _.each( + [ + 'leave_type', + 'from_date', + 'from_date_part', + 'to_date', + 'to_date_part', + 'reason' + ], + property => { + if (!_.has(args, property)) { + throw new Error( + 'No mandatory ' + + property + + ' was provided to LeaveRequest constructor' + ) + } } - - _.each( - [ - 'leave_type','from_date','from_date_part', - 'to_date', 'to_date_part', 'reason', 'user' - ], - function(property){ me[property] = args[property]; } - ); + ) + + // From date should not be bigger then to + if (moment.utc(args.from_date).toDate() > moment.utc(args.to_date).toDate()) { + throw new Error( + 'From date should be before To date at LeaveRequest constructor' + ) + } + + _.each( + [ + 'leave_type', + 'from_date', + 'from_date_part', + 'to_date', + 'to_date_part', + 'reason', + 'user' + ], + property => { + me[property] = args[property] + } + ) } -LeaveRequest.prototype.as_data_object = function(){ - var obj = {}, - me = this; - - _.each( - [ - 'leave_type','from_date','from_date_part', - 'to_date', 'to_date_part', 'reason', 'user' - ], - function(property){ obj[property] = me[property]; } - ); - - return obj; -}; - -LeaveRequest.prototype.is_within_one_day = function(){ - return moment.utc(this.from_date).format('YYYY-MM-DD') - === - moment.utc(this.to_date).format('YYYY-MM-DD'); -}; - -LeaveRequest.prototype._does_fit_with_point = function(leave_day, point_name){ - var return_val = false; - - if ( - ( - moment.utc(leave_day.date).format('YYYY-MM-DD') - === - moment.utc(this[point_name]).format('YYYY-MM-DD') - ) - && - (! leave_day.is_all_day_leave()) - && - (String(this[point_name+'_part']) !== String(model.Leave.leave_day_part_all())) - && - (String(leave_day.day_part) !== String(this[point_name+'_part'])) - ) { - return_val = true; +LeaveRequest.prototype.as_data_object = function() { + const obj = {} + const me = this + + _.each( + [ + 'leave_type', + 'from_date', + 'from_date_part', + 'to_date', + 'to_date_part', + 'reason', + 'user' + ], + property => { + obj[property] = me[property] } + ) - return return_val; -}; + return obj +} + +LeaveRequest.prototype.is_within_one_day = function() { + return ( + moment.utc(this.from_date).format('YYYY-MM-DD') === + moment.utc(this.to_date).format('YYYY-MM-DD') + ) +} + +LeaveRequest.prototype._does_fit_with_point = function(leave_day, point_name) { + let return_val = false + + if ( + moment.utc(leave_day.date).format('YYYY-MM-DD') === + moment.utc(this[point_name]).format('YYYY-MM-DD') && + !leave_day.is_all_day_leave() && + String(this[point_name + '_part']) !== + String(model.Leave.leave_day_part_all()) && + String(leave_day.day_part) !== String(this[point_name + '_part']) + ) { + return_val = true + } + + return return_val +} // Check if start date or end date of current object fits with provided leave_day // instance. // By fitting I mean days are the same and both of them are // halfs of different types. // -LeaveRequest.prototype.does_fit_with_leave_day = function(leave_day){ - - return this._does_fit_with_point(leave_day, 'from_date') - || - this._does_fit_with_point(leave_day, 'to_date'); -}; - -LeaveRequest.prototype.does_fit_with_leave_day_at_start = function(leave_day){ - - return this._does_fit_with_point(leave_day, 'from_date'); -}; - -LeaveRequest.prototype.does_fit_with_leave_day_at_end = function(leave_day){ +LeaveRequest.prototype.does_fit_with_leave_day = function(leave_day) { + return ( + this._does_fit_with_point(leave_day, 'from_date') || + this._does_fit_with_point(leave_day, 'to_date') + ) +} - return this._does_fit_with_point(leave_day, 'to_date'); -}; +LeaveRequest.prototype.does_fit_with_leave_day_at_start = function(leave_day) { + return this._does_fit_with_point(leave_day, 'from_date') +} +LeaveRequest.prototype.does_fit_with_leave_day_at_end = function(leave_day) { + return this._does_fit_with_point(leave_day, 'to_date') +} -module.exports = LeaveRequest; +module.exports = LeaveRequest diff --git a/lib/model/mixin/user/absence_aware.js b/lib/model/mixin/user/absence_aware.js index cc1a20665..b12599186 100644 --- a/lib/model/mixin/user/absence_aware.js +++ b/lib/model/mixin/user/absence_aware.js @@ -1,610 +1,653 @@ - /* * Mixin that inject to user model object consumer set of methods necessary for * dealing with absences. * * */ -'use strict'; +'use strict' -const { sorter } = require('../../../util'); +const { sorter } = require('../../../util') -var - _ = require('underscore'), - Promise = require("bluebird"), - CalendarMonth = require('../../calendar_month'), - LeaveCollectionUtil = require('../../leave_collection')(), - moment = require('moment'); +const _ = require('underscore') +const Promise = require('bluebird') +const CalendarMonth = require('../../calendar_month') +const LeaveCollectionUtil = require('../../leave_collection')() +const moment = require('moment') -module.exports = function(sequelize){ +const Sequelize = require('sequelize') +const Op = Sequelize.Op - this._get_calendar_months_to_show = function(args){ - var - self = this, - year = args.year, - show_full_year = args.show_full_year; +module.exports = function(sequelize) { + this._get_calendar_months_to_show = function(args) { + const self = this + const year = args.year + const show_full_year = args.show_full_year if (show_full_year) { - return _.map([1,2,3,4,5,6,7,8,9,10,11,12], function(i){ - return moment.utc(year.format('YYYY')+'-'+i+'-01'); - }); + return _.map([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12], i => + moment.utc(year.format('YYYY') + '-' + i + '-01') + ) } - return _.map([0,1,2,3], function(delta){ - return self.company.get_today().add(delta, 'months').startOf('month'); - }) - }; - + return _.map([0, 1, 2, 3], delta => + self.company + .get_today() + .add(delta, 'months') + .startOf('month') + ) + } this.promise_calendar = function(args) { - var - this_user = this, - year = args.year || this_user.company.get_today(), - show_full_year = args.show_full_year || false, - model = sequelize.models, - // Find out if we need to show multi year calendar - is_multi_year = this_user.company.get_today().month() > 8; - - var months_to_show = this_user._get_calendar_months_to_show({ - year : year.clone(), - show_full_year : show_full_year - }); + const this_user = this + const year = args.year || this_user.company.get_today() + const show_full_year = args.show_full_year || false + const model = sequelize.models + // Find out if we need to show multi year calendar + const is_multi_year = this_user.company.get_today().month() > 8 + + const months_to_show = this_user._get_calendar_months_to_show({ + year: year.clone(), + show_full_year + }) return Promise.join( - Promise.try(() => this_user.getDepartment()), - Promise.try(() => this_user.getCompany({ - scope : ['with_bank_holidays', 'with_leave_types'] - })), + Promise.try(() => + this_user.getCompany({ + scope: ['with_bank_holidays', 'with_leave_types'] + }) + ), - Promise.try(function(){ - return this_user.getMy_leaves({ - where : { - $and : [ - { status : { $ne : sequelize.models.Leave.status_rejected() } }, - { status : { $ne : sequelize.models.Leave.status_canceled() } }, + Promise.try(() => + this_user.getMy_leaves({ + where: { + [Op.and]: [ + { status: { [Op.ne]: sequelize.models.Leave.status_rejected() } }, + { status: { [Op.ne]: sequelize.models.Leave.status_canceled() } } ], - $or : { - date_start : { - $between : [ - moment.utc(year).startOf('year').format('YYYY-MM-DD'), - moment.utc( - year.clone().add((is_multi_year ? 1 : 0), 'years') - ).endOf('year').format('YYYY-MM-DD HH:mm'), + [Op.or]: { + date_start: { + [Op.between]: [ + moment + .utc(year) + .startOf('year') + .format('YYYY-MM-DD'), + moment + .utc(year.clone().add(is_multi_year ? 1 : 0, 'years')) + .endOf('year') + .format('YYYY-MM-DD HH:mm') ] }, - date_end : { - $between : [ - moment.utc( year ).startOf('year').format('YYYY-MM-DD'), - moment.utc( - year.clone().add((is_multi_year ? 1 : 0), 'years') - ).endOf('year').format('YYYY-MM-DD HH:mm'), + date_end: { + [Op.between]: [ + moment + .utc(year) + .startOf('year') + .format('YYYY-MM-DD'), + moment + .utc(year.clone().add(is_multi_year ? 1 : 0, 'years')) + .endOf('year') + .format('YYYY-MM-DD HH:mm') ] } } - }, - }); - }), + } + }) + ), Promise.try(() => this_user.promise_schedule_I_obey()), - function(department, company, leaves, schedule){ - var leave_days = _.flatten( _.map(leaves, function(leave){ - return _.map( leave.get_days(), function(leave_day){ - leave_day.leave = leave; - return leave_day; - }); - })); + (department, company, leaves, schedule) => { + const leave_days = _.flatten( + _.map(leaves, leave => + _.map(leave.get_days(), leave_day => { + leave_day.leave = leave + return leave_day + }) + ) + ) return Promise.resolve( - _.map(months_to_show, function(month){ - return new CalendarMonth( - month, - { - bank_holidays : - department.include_public_holidays - ? company.bank_holidays - : [], - leave_days : leave_days, - schedule : schedule, - today : company.get_today(), - leave_types: company.leave_types, - } - ); - }) - ); + _.map( + months_to_show, + month => + new CalendarMonth(month, { + bank_holidays: department.include_public_holidays + ? company.bank_holidays + : [], + leave_days, + schedule, + today: company.get_today(), + leave_types: company.leave_types + }) + ) + ) } - - ); // End of join - }; - + ) // End of join + } this.validate_overlapping = function(new_leave_attributes) { - var this_user = this; + const this_user = this - var days_filter = { - $between : [ + const days_filter = { + [Op.between]: [ new_leave_attributes.from_date, - moment.utc(new_leave_attributes.to_date) - .add(1,'days').format('YYYY-MM-DD'), - ], - }; - - return this_user.getMy_leaves({ - where : { - $and : [ - { status : { $ne : sequelize.models.Leave.status_rejected() } }, - { status : { $ne : sequelize.models.Leave.status_canceled() } }, - ], - - $or : { - date_start : days_filter, - date_end : days_filter, - }, - }, - }) - - .then(function(overlapping_leaves){ - - // Check there are overlapping leaves - if (overlapping_leaves.length === 0){ - return Promise.resolve(1); - } + moment + .utc(new_leave_attributes.to_date) + .endOf('day') + .format('YYYY-MM-DD') + ] + } - var overlapping_leave = overlapping_leaves[0]; + return this_user + .getMy_leaves({ + where: { + [Op.and]: [ + { status: { [Op.ne]: sequelize.models.Leave.status_rejected() } }, + { status: { [Op.ne]: sequelize.models.Leave.status_canceled() } } + ], + + [Op.or]: { + date_start: days_filter, + date_end: days_filter + } + } + }) - if (overlapping_leave.fit_with_leave_request( - new_leave_attributes - )){ - return Promise.resolve(1); - } + .then(overlapping_leaves => { + // Check there are overlapping leaves + if (overlapping_leaves.length === 0) { + return Promise.resolve(1) + } - // Otherwise it is overlapping! - var error = new Error('Overlapping booking!'); - error.user_message = 'Overlapping booking!'; - throw error; + const overlapping_leave = overlapping_leaves[0] - }); - }; // end of validate_overlapping + if (overlapping_leave.fit_with_leave_request(new_leave_attributes)) { + return Promise.resolve(1) + } + // Otherwise it is overlapping! + const error = new Error('Overlapping booking!') + error.user_message = 'Overlapping booking!' + throw error + }) + } // end of validate_overlapping // Promise all leaves requested by current user, regardless // their statuses // - this.promise_my_leaves = function(args){ + this.promise_my_leaves = function(args) { + const self = this + // Time zone does not really matter here, although there could be issues + // around New Year (but we can tolerate that) + const year = args.year || moment.utc() - var self = this, - where_clause = args.filter || {}, - // Time zone does not really matter here, although there could be issues - // around New Year (but we can tolerate that) - year = args.year || moment.utc(); + const where_clause = [] if (args && args.filter_status) { - where_clause = { status : args.filter_status }; + where_clause.push({ status: args.filter_status }) } - if (args && ! args.ignore_year) { - where_clause['$or'] = { - date_start : { - $between : [ - moment.utc(year).startOf('year').format('YYYY-MM-DD'), - moment.utc(year).endOf('year').format('YYYY-MM-DD HH:mm'), - ] - }, - date_end : { - $between : [ - moment.utc(year).startOf('year').format('YYYY-MM-DD'), - moment.utc(year).endOf('year').format('YYYY-MM-DD HH:mm'), - ] + if (args && !args.ignore_year) { + where_clause.push({ + [Op.or]: { + date_start: { + [Op.between]: [ + moment() + .year(year) + .startOf('year') + .format('YYYY-MM-DD'), + moment() + .year(year) + .endOf('year') + .format('YYYY-MM-DD HH:mm') + ] + }, + date_end: { + [Op.between]: [ + moment() + .year(year) + .startOf('year') + .format('YYYY-MM-DD'), + moment() + .year(year) + .endOf('year') + .format('YYYY-MM-DD HH:mm') + ] + } } - }; - + }) + } // Case when there are start and end date defined - } else if (args && args.dateStart && args.dateEnd) { - const {dateStart, dateEnd} = args; - - where_clause['$or'] = { - date_start : { - $between : [ - moment.utc(dateStart).startOf('day').format('YYYY-MM-DD'), - moment.utc(dateEnd).endOf('day').format('YYYY-MM-DD HH:mm'), - ] - }, - date_end : { - $between : [ - moment.utc(dateStart).startOf('day').format('YYYY-MM-DD'), - moment.utc(dateEnd).endOf('day').format('YYYY-MM-DD HH:mm'), - ] - }, - // Case when given data range is within existing leave - $and: { - date_start: {$lte: moment.utc(dateStart).startOf('day').format('YYYY-MM-DD')}, - date_end: {$gte: moment.utc(dateEnd).endOf('day').format('YYYY-MM-DD')}, + else if (args && args.dateStart && args.dateEnd) { + const { dateStart, dateEnd } = args + + where_clause.push({ + [Op.or]: { + date_start: { + $between: [ + moment + .utc(dateStart) + .startOf('day') + .format('YYYY-MM-DD'), + moment + .utc(dateEnd) + .endOf('day') + .format('YYYY-MM-DD HH:mm') + ] + }, + date_end: { + $between: [ + moment + .utc(dateStart) + .startOf('day') + .format('YYYY-MM-DD'), + moment + .utc(dateEnd) + .endOf('day') + .format('YYYY-MM-DD HH:mm') + ] + }, + // Case when given data range is within existing leave + $and: { + date_start: { + $lte: moment + .utc(dateStart) + .startOf('day') + .format('YYYY-MM-DD') + }, + date_end: { + $gte: moment + .utc(dateEnd) + .endOf('day') + .format('YYYY-MM-DD') + } + } } - }; + }) } - var promise_my_leaves = this.getMy_leaves({ + const promise_my_leaves = this.getMy_leaves({ // TODO here is cartesian product between leave types and users, // needs to be split - include : [{ - model : sequelize.models.LeaveType, - as : 'leave_type', - },{ - model : sequelize.models.User, - as : 'user', - include : [{ - model : sequelize.models.Company, - as : 'company', - include : [{ - model : sequelize.models.BankHoliday, - as : 'bank_holidays', - }], - }], - }], - where : where_clause, + include: [ + { + model: sequelize.models.LeaveType, + as: 'leave_type' + }, + { + model: sequelize.models.User, + as: 'user', + include: [ + { + model: sequelize.models.Company, + as: 'company', + include: [ + { + model: sequelize.models.BankHoliday, + as: 'bank_holidays' + } + ] + } + ] + } + ], + where: { [Op.and]: where_clause } }) - // Fetch approvers for each leave in separate query, to avoid cartesian - // products. - .then(function(leaves){ - - leaves.forEach(function(leave){ leave.user.cached_schedule = self.cached_schedule; }); - - return Promise.resolve(leaves) - .map( - function(leave){ - return leave.promise_approver() - .then(function(approver){ - leave.approver = approver; - return Promise.resolve(leave); - }); - }, { - concurrency : 10, - } - ); - }) + // Fetch approvers for each leave in separate query, to avoid cartesian + // products. + .then(leaves => { + leaves.forEach(leave => { + leave.user.cached_schedule = self.cached_schedule + }) - .then(async (leaves) => { - const department = await self.getDepartment(); - leaves.forEach(l => l.user.department = department); - return leaves; - }) + return Promise.resolve(leaves).map( + leave => + leave.promise_approver().then(approver => { + leave.approver = approver + return Promise.resolve(leave) + }), + { + concurrency: 10 + } + ) + }) - .then(leaves => LeaveCollectionUtil.promise_to_sort_leaves(leaves)); + .then(async leaves => { + const department = await self.getDepartment() + leaves.forEach(l => (l.user.department = department)) + return leaves + }) - return promise_my_leaves; - }; + .then(leaves => LeaveCollectionUtil.promise_to_sort_leaves(leaves)) + return promise_my_leaves + } this.promise_my_active_leaves = function(args) { - var year = args.year || moment.utc(); + const year = args.year || moment.utc() return this.promise_my_leaves({ - year : year, - filter_status : [ + year, + filter_status: [ sequelize.models.Leave.status_approved(), sequelize.models.Leave.status_new(), - sequelize.models.Leave.status_pended_revoke(), - ], - }) - .then(leaves => LeaveCollectionUtil.promise_to_sort_leaves(leaves)); - }; + sequelize.models.Leave.status_pended_revoke() + ] + }).then(leaves => LeaveCollectionUtil.promise_to_sort_leaves(leaves)) + } - this.getMyActiveLeavesForDateRange = async function({dateStart, dateEnd}) { - const self = this; + this.getMyActiveLeavesForDateRange = async function({ dateStart, dateEnd }) { + const self = this const rawLeaves = await self.promise_my_leaves({ ignore_year: true, dateStart, dateEnd, - filter_status : [ + filter_status: [ sequelize.models.Leave.status_approved(), sequelize.models.Leave.status_new(), - sequelize.models.Leave.status_pended_revoke(), - ], - }); + sequelize.models.Leave.status_pended_revoke() + ] + }) - const leaves = await LeaveCollectionUtil.promise_to_sort_leaves(rawLeaves); + const leaves = await LeaveCollectionUtil.promise_to_sort_leaves(rawLeaves) - return leaves; - }; + return leaves + } // Promises leaves ever booked for current user this.promise_my_active_leaves_ever = function() { - return this.promise_my_leaves({ - ignore_year : true, - filter_status : [ + ignore_year: true, + filter_status: [ sequelize.models.Leave.status_approved(), sequelize.models.Leave.status_new(), - sequelize.models.Leave.status_pended_revoke(), - ], - }) - .then(leaves => LeaveCollectionUtil.promise_to_sort_leaves(leaves)); - }; - + sequelize.models.Leave.status_pended_revoke() + ] + }).then(leaves => LeaveCollectionUtil.promise_to_sort_leaves(leaves)) + } // Promise leaves that are needed to be Approved/Rejected // - this.promise_leaves_to_be_processed = function(){ - let self = this; + this.promise_leaves_to_be_processed = function() { + const self = this return self .promise_supervised_users() - .then(users => { - return sequelize.models.Leave.findAll({ - include : [{ - model : sequelize.models.LeaveType, - as : 'leave_type', - },{ - model : sequelize.models.User, - as : 'user', - include : [{ - model : sequelize.models.Company, - as : 'company', - include : [{ - model : sequelize.models.BankHoliday, - as : 'bank_holidays', - }], - },{ - model : sequelize.models.Department, - as : 'department', - }], - }], - where : { - status : [ + .then(users => + sequelize.models.Leave.findAll({ + include: [ + { + model: sequelize.models.LeaveType, + as: 'leave_type' + }, + { + model: sequelize.models.User, + as: 'user', + include: [ + { + model: sequelize.models.Company, + as: 'company', + include: [ + { + model: sequelize.models.BankHoliday, + as: 'bank_holidays' + } + ] + }, + { + model: sequelize.models.Department, + as: 'department' + } + ] + } + ], + where: { + status: [ sequelize.models.Leave.status_new(), sequelize.models.Leave.status_pended_revoke() ], - userId : users.map(u => u.id), - }, + user_id: users.map(u => u.id) + } }) - }) - .then( leaves => Promise - .resolve(leaves) - .map( - leave => leave.user.promise_schedule_I_obey(), - { concurrency : 10 } - ) - .then( () => Promise.resolve(leaves) ) - .then(leaves => LeaveCollectionUtil.promise_to_sort_leaves(leaves)) - ); - }; // END of promise_leaves_to_be_processed + ) + .then(leaves => + Promise.resolve(leaves) + .map(leave => leave.user.promise_schedule_I_obey(), { + concurrency: 10 + }) + .then(() => Promise.resolve(leaves)) + .then(leaves => LeaveCollectionUtil.promise_to_sort_leaves(leaves)) + ) + } // END of promise_leaves_to_be_processed - this.promise_cancelable_leaves = function(){ - var self = this; + this.promise_cancelable_leaves = function() { + const self = this - return self.promise_my_leaves({ - ignore_year : true, - filter_status : [ sequelize.models.Leave.status_new() ], - }) - .then(function(leaves){ - return Promise.map(leaves, function(leave){ - return leave.user.promise_schedule_I_obey(); - },{ - concurrency : 10, + return self + .promise_my_leaves({ + ignore_year: true, + filter_status: [sequelize.models.Leave.status_new()] }) - .then(function(){ return Promise.resolve(leaves) }) - .then(leaves => LeaveCollectionUtil.promise_to_sort_leaves(leaves)); - }); - }; - - - this.calculate_number_of_days_taken_from_allowance = function(args){ - var self = this, - leave_type = args ? args.leave_type : null, - leaves_to_traverse = this.my_leaves || []; - - - leaves_to_traverse.forEach(function(leave){ leave.user.cached_schedule = self.cached_schedule; }); + .then(leaves => + Promise.map(leaves, leave => leave.user.promise_schedule_I_obey(), { + concurrency: 10 + }) + .then(() => Promise.resolve(leaves)) + .then(leaves => LeaveCollectionUtil.promise_to_sort_leaves(leaves)) + ) + } + + this.calculate_number_of_days_taken_from_allowance = function(args) { + const self = this + const leave_type = args ? args.leave_type : null + let leaves_to_traverse = this.my_leaves || [] + + leaves_to_traverse.forEach(leave => { + leave.user.cached_schedule = self.cached_schedule + }) // If leave_type was provided, we care only about leaves of that type if (leave_type) { leaves_to_traverse = _.filter( leaves_to_traverse, - function(leave){ return leave.leaveTypeId === leave_type.id; } - ); + leave => leave.leave_type_id === leave_type.id + ) } - return _.reduce( - _.map( - _.filter( - leaves_to_traverse, - function (leave){ return leave.is_approved_leave(); } + return ( + _.reduce( + _.map( + _.filter(leaves_to_traverse, leave => leave.is_approved_leave()), + leave => leave.get_deducted_days_number(args) ), - function(leave){ return leave.get_deducted_days_number(args); } - ), - function(memo, num){ return memo + num }, - 0 - ) || 0; - }; - + (memo, num) => memo + num, + 0 + ) || 0 + ) + } // Based on leaves attached to the current user object, // the method does not perform any additional queries // - this.get_leave_statistics_by_types = function(args){ - - if (! args ) args = {}; + this.get_leave_statistics_by_types = function(args) { + if (!args) args = {} - var statistics = {}, - limit_by_top = args.limit_by_top || false; + const statistics = {} + const limit_by_top = args.limit_by_top || false - this.company.leave_types.forEach(function(leave_type){ - var initial_stat = { - leave_type : leave_type, - days_taken : 0, - }; + this.company.leave_types.forEach(leave_type => { + const initial_stat = { + leave_type, + days_taken: 0 + } if (leave_type.limit && leave_type.limit > 0) { - initial_stat.limit = leave_type.limit; + initial_stat.limit = leave_type.limit } - statistics[leave_type.id] = initial_stat; - }); + statistics[leave_type.id] = initial_stat + }) // Calculate statistics as an object - _.filter( - this.my_leaves, - function (leave){ return leave.is_approved_leave() } - ) - .forEach( - function(leave){ - - var stat_obj = statistics[leave.leave_type.id]; + _.filter(this.my_leaves, leave => leave.is_approved_leave()).forEach( + leave => { + const stat_obj = statistics[leave.leave_type.id] - stat_obj.days_taken = stat_obj.days_taken + leave.get_deducted_days_number({ - ignore_allowance : true, - }); + stat_obj.days_taken = + stat_obj.days_taken + + leave.get_deducted_days_number({ + ignore_allowance: true + }) } - ); + ) - var statistic_arr = _.map( - _.pairs(statistics), - function(pair){ - return pair[1]; - } - ); + let statistic_arr = _.map(_.pairs(statistics), pair => pair[1]) statistic_arr = statistic_arr - .sort((a,b) => sorter(a.days_taken, b.days_taken)) - .reverse(); - + .sort((a, b) => sorter(a.days_taken, b.days_taken)) + .reverse() if (limit_by_top) { - statistic_arr = _.first(statistic_arr, 4); + statistic_arr = _.first(statistic_arr, 4) } - return statistic_arr.sort((a,b) => sorter(a.leave_type.name, b.leave_type.name)); - }, - + return statistic_arr.sort((a, b) => + sorter(a.leave_type.name, b.leave_type.name) + ) + } - this.promise_adjustment_and_carry_over_for_year = function(year){ - let self = this; + this.promise_adjustment_and_carry_over_for_year = function(year) { + const self = this - year = year || moment.utc(); - year = moment.utc(year).format('YYYY'); + year = year || moment.utc() + year = moment.utc(year).format('YYYY') return self .getAdjustments({ - where : { year : year } + where: { year } }) .then(adjustment_records => { - // By deafault there is not adjustments - let result = { - adjustment : 0, - carried_over_allowance : 0, - }; + const result = { + adjustment: 0, + carried_over_allowance: 0 + } if (adjustment_records.length === 1) { - result.adjustment = adjustment_records[0].adjustment; - result.carried_over_allowance = adjustment_records[0].carried_over_allowance; + result.adjustment = adjustment_records[0].adjustment + result.carried_over_allowance = + adjustment_records[0].carried_over_allowance } - return Promise.resolve(result); - }); - }; + return Promise.resolve(result) + }) + } - this.promise_adjustmet_for_year = function(year){ - let self = this; + this.promise_adjustmet_for_year = function(year) { + const self = this return self .promise_adjustment_and_carry_over_for_year(year) - .then(combined_record => Promise.resolve(combined_record.adjustment)); - }; + .then(combined_record => Promise.resolve(combined_record.adjustment)) + } - this.promise_carried_over_allowance_for_year = function(year){ - let self = this; + this.promise_carried_over_allowance_for_year = function(year) { + const self = this return self .promise_adjustment_and_carry_over_for_year(year) - .then(combined_record => Promise.resolve(combined_record.carried_over_allowance)); - }; + .then(combined_record => + Promise.resolve(combined_record.carried_over_allowance) + ) + } this.promise_to_update_adjustment = function(args) { - let - self = this, - year = args.year || moment.utc().format('YYYY'), - adjustment = args.adjustment; + const self = this + const year = args.year || moment.utc().format('YYYY') + const adjustment = args.adjustment // Update related allowance adjustement record - return sequelize.models.UserAllowanceAdjustment - .findOrCreate({ - where : { - user_id : self.id, - year : year, - }, - defaults : { adjustment : adjustment }, - }) - .spread((record, created) => { - - if ( created ) { - return Promise.resolve(); - } + return sequelize.models.UserAllowanceAdjustment.findOrCreate({ + where: { + user_id: self.id, + year + }, + defaults: { adjustment } + }).spread((record, created) => { + if (created) { + return Promise.resolve() + } - record.set('adjustment', adjustment); + record.set('adjustment', adjustment) - return record.save(); - }); - }; + return record.save() + }) + } this.promise_to_update_carried_over_allowance = function(args) { - let - self = this, - year = args.year || moment.utc().format('YYYY'), - carried_over_allowance = args.carried_over_allowance; + const self = this + const year = args.year || moment.utc().format('YYYY') + const carried_over_allowance = args.carried_over_allowance // Update related allowance adjustement record - return sequelize.models.UserAllowanceAdjustment - .findOrCreate({ - where : { - user_id : self.id, - year : year, - }, - defaults : { carried_over_allowance : carried_over_allowance }, - }) - .spread((record, created) => { - - if ( created ) { - return Promise.resolve(); - } - - record.set('carried_over_allowance', carried_over_allowance); + return sequelize.models.UserAllowanceAdjustment.findOrCreate({ + where: { + user_id: self.id, + year + }, + defaults: { carried_over_allowance } + }).spread((record, created) => { + if (created) { + return Promise.resolve() + } - return record.save(); - }); - }; + record.set('carried_over_allowance', carried_over_allowance) + return record.save() + }) + } - this.promise_my_leaves_for_calendar = function(args){ - var year = args.year || this.company.get_today(); + this.promise_my_leaves_for_calendar = function(args) { + const year = args.year || this.company.get_today() return this.getMy_leaves({ - where : { - - $and : [ - { status : { $ne : sequelize.models.Leave.status_rejected() } }, - { status : { $ne : sequelize.models.Leave.status_canceled() } }, + where: { + [Op.and]: [ + { status: { [Op.ne]: sequelize.models.Leave.status_rejected() } }, + { status: { [Op.ne]: sequelize.models.Leave.status_canceled() } } ], - $or : { - date_start : { - $between : [ - moment.utc(year).startOf('year').format('YYYY-MM-DD'), - moment.utc(year).endOf('year').format('YYYY-MM-DD HH:mm'), + [Op.or]: { + date_start: { + [Op.between]: [ + moment + .utc(year) + .startOf('year') + .format('YYYY-MM-DD'), + moment + .utc(year) + .endOf('year') + .format('YYYY-MM-DD HH:mm') ] }, - date_end : { - $between : [ - moment.utc(year).startOf('year').format('YYYY-MM-DD'), - moment.utc(year).endOf('year').format('YYYY-MM-DD HH:mm'), + date_end: { + [Op.between]: [ + moment + .utc(year) + .startOf('year') + .format('YYYY-MM-DD'), + moment + .utc(year) + .endOf('year') + .format('YYYY-MM-DD HH:mm') ] } } - }, - }); // End of MyLeaves - }; + } + }) // End of MyLeaves + } // For given leave object (not necessary one with corresponding record in DB) // check if current user is capable to have it, that is if user's remaining @@ -612,88 +655,96 @@ module.exports = function(sequelize){ // // If validation fails an exceptionis thrown. // - this.validate_leave_fits_into_remaining_allowance = function(args){ - var self = this, - leave_type = args.leave_type, - leave = args.leave, + this.validate_leave_fits_into_remaining_allowance = function(args) { + const self = this + const leave_type = args.leave_type + const leave = args.leave // Derive year from Leave object - year = args.year || moment.utc(leave.date_start); + const year = args.year || moment.utc(leave.date_start) // Make sure object contain all necessary data for that check - return self.reload_with_leave_details({ - year : year.clone(), - }) - .then( employee => employee.reload_with_session_details() ) - .then(employee => employee.company.reload_with_bank_holidays() - .then(() => Promise.resolve(employee)) - ) - .then(employee => - employee.promise_allowance({year}) - .then(allowance_obj => Promise.resolve([allowance_obj.number_of_days_available_in_allowance, employee])) - ) - .then(function(args){ - let days_remaining_in_allowance = args[0], - employee = args[1]; - - let deducted_days = leave.get_deducted_days_number({ - year : year.format('YYYY'), - user : employee, - leave_type : leave_type, - }); - - // Throw an exception when less than zero vacation would remain - // if we add currently requested absence - if ( - days_remaining_in_allowance - deducted_days < 0 - ) { - - var error = new Error('Requested absence is longer than remaining allowance'); - error.user_message = error.toString(); - throw error; - } - - return Promise.resolve(employee); - }) - - // Check that adding new leave of this type will not exceed maximum limit of - // that type (if it is defined) - .then(function(employee){ - if ( - // There is a limit for current type - leave_type.limit - // ... and lemit is bigger than zero - && leave_type.limit > 0 - ) { - - // ... sum of used dayes for this limit is going to be bigger then limit - var would_be_used = employee.calculate_number_of_days_taken_from_allowance({ - year : year.format('YYYY'), - leave_type : leave_type, - ignore_allowance : true, + return ( + self + .reload_with_leave_details({ + year: year.clone() + }) + .then(employee => employee.reload_with_session_details()) + .then(employee => + employee.company + .reload_with_bank_holidays() + .then(() => Promise.resolve(employee)) + ) + .then(employee => + employee + .promise_allowance({ year }) + .then(allowance_obj => + Promise.resolve([ + allowance_obj.number_of_days_available_in_allowance, + employee + ]) + ) + ) + .then(args => { + const days_remaining_in_allowance = args[0] + const employee = args[1] + + const deducted_days = leave.get_deducted_days_number({ + year: year.format('YYYY'), + user: employee, + leave_type }) - + - leave.get_deducted_days_number({ - year : year.format('YYYY'), - user : employee, - leave_type : leave_type, - ignore_allowance : true, - }); - - if (would_be_used > leave_type.limit) { - var error = new Error('Adding requested '+leave_type.name - +" absence would exceed maximum allowed for such type by " - +(would_be_used - leave_type.limit) - ); - - error.user_message = error.toString(); - throw error; - } - } + // Throw an exception when less than zero vacation would remain + // if we add currently requested absence + if (days_remaining_in_allowance - deducted_days < 0) { + const error = new Error( + 'Requested absence is longer than remaining allowance' + ) + error.user_message = error.toString() + throw error + } - return Promise.resolve(); - }); - }; + return Promise.resolve(employee) + }) -}; + // Check that adding new leave of this type will not exceed maximum limit of + // that type (if it is defined) + .then(employee => { + if ( + // There is a limit for current type + leave_type.limit && + // ... and lemit is bigger than zero + leave_type.limit > 0 + ) { + // ... sum of used dayes for this limit is going to be bigger then limit + const would_be_used = + employee.calculate_number_of_days_taken_from_allowance({ + year: year.format('YYYY'), + leave_type, + ignore_allowance: true + }) + + leave.get_deducted_days_number({ + year: year.format('YYYY'), + user: employee, + leave_type, + ignore_allowance: true + }) + + if (would_be_used > leave_type.limit) { + const error = new Error( + 'Adding requested ' + + leave_type.name + + ' absence would exceed maximum allowed for such type by ' + + (would_be_used - leave_type.limit) + ) + + error.user_message = error.toString() + throw error + } + } + return Promise.resolve() + }) + ) + } +} diff --git a/lib/model/mixin/user/company_aware.js b/lib/model/mixin/user/company_aware.js index 4c01f70ba..e1881268e 100644 --- a/lib/model/mixin/user/company_aware.js +++ b/lib/model/mixin/user/company_aware.js @@ -1,4 +1,3 @@ - /* * This is a role to be applied to user model that injects getters necessary * for fetching related company object with different level of details. @@ -8,16 +7,16 @@ * * */ -'use strict'; - -var - Promise = require("bluebird"), - moment = require('moment'); +'use strict' -const { sorter } = require("../../../util"); +const Promise = require('bluebird') +const moment = require('moment') +const Sequelize = require('sequelize') +const Op = Sequelize.Op -module.exports = function(sequelize){ +const { sorter } = require('../../../util') +module.exports = function(sequelize) { /* Fetch company object associated with current user, the company object * includes all necessary associations for building user detail page * for user determined by user_id. @@ -27,120 +26,147 @@ module.exports = function(sequelize){ // TODO: Query below needs to be revisited as it is slow for users // with many leaves // - this.get_company_for_user_details = function(args){ - var user_id = args.user_id, - year = args.year || moment.utc(), - current_user = this; - - return this.getCompany({ - include : [ - { - model : sequelize.models.User, - as : 'users', - where : { id : user_id }, - include : [ - - // Following is needed to be able to calculate how many days were - // taken from allowance - { - model : sequelize.models.Leave, - as : 'my_leaves', - required : false, - where : { - $or : { - date_start : { - $between : [ - moment.utc().startOf('year').format('YYYY-MM-DD'), - moment.utc().endOf('year').format('YYYY-MM-DD HH:mm'), - ] + this.get_company_for_user_details = function(args) { + const user_id = args.user_id + const year = args.year || moment.utc() + const current_user = this + + return ( + this.getCompany({ + include: [ + { + model: sequelize.models.User, + as: 'users', + where: { id: user_id }, + include: [ + // Following is needed to be able to calculate how many days were + // taked from allowance + { + model: sequelize.models.Leave, + as: 'my_leaves', + required: false, + where: { + [Op.or]: { + date_start: { + [Op.between]: [ + moment + .utc() + .startOf('year') + .format('YYYY-MM-DD'), + moment + .utc() + .endOf('year') + .format('YYYY-MM-DD HH:mm') + ] + }, + date_end: { + [Op.between]: [ + moment + .utc() + .startOf('year') + .format('YYYY-MM-DD'), + moment + .utc() + .endOf('year') + .format('YYYY-MM-DD HH:mm') + ] + } + } + }, + include: [ + { + model: sequelize.models.LeaveType, + as: 'leave_type' }, - date_end : { - $between : [ - moment.utc().startOf('year').format('YYYY-MM-DD'), - moment.utc().endOf('year').format('YYYY-MM-DD HH:mm'), + { + model: sequelize.models.User, + as: 'user', + include: [ + { + model: sequelize.models.Company, + as: 'company', + include: [ + { + model: sequelize.models.BankHoliday, + as: 'bank_holidays' + } + ] + } ] } - } + ] // End of my_leaves include }, - include : [{ - model : sequelize.models.LeaveType, - as : 'leave_type', - },{ - model : sequelize.models.User, - as : 'user', - include : [{ - model : sequelize.models.Company, - as : 'company', - include : [{ - model : sequelize.models.BankHoliday, - as : 'bank_holidays', - }], - }], - }] // End of my_leaves include - },{ - model : sequelize.models.Department, - as : 'department', + { + model: sequelize.models.Department, + as: 'department' + } + ] + }, + { + model: sequelize.models.Department, + as: 'departments', + include: { + model: sequelize.models.User, + as: 'manager' } - ], - },{ - model : sequelize.models.Department, - as : 'departments', - include : { - model : sequelize.models.User, - as : 'boss', } - } - ], - order : [ - [ - {model : sequelize.models.Department, as : 'departments'}, - sequelize.models.Department.default_order_field(), + ], + order: [ + [ + { model: sequelize.models.Department, as: 'departments' }, + sequelize.models.Department.default_order_field() + ] ] - ], - }) - - // Make sure that company got only one user associated with for - // provided user_id - .then(function(company){ - - if (!company || company.users.length !== 1) { - throw new Error( - 'User '+current_user.id+' tried to edit user '+user_id - +' but they do not share a company' - ); - } - - return Promise.resolve(company); - }); - }; + }) + + // Make sure that company got only one user associated with for + // provided user_id + .then(company => { + if (!company || company.users.length !== 1) { + throw new Error( + 'User ' + + current_user.id + + ' tried to edit user ' + + user_id + + ' but they do not share a company' + ) + } + return Promise.resolve(company) + }) + ) + } this.get_company_for_add_user = function() { - var model = sequelize.models; + const model = sequelize.models return this.getCompany({ - include : [ - {model : model.Department, as : 'departments'} - ], - order : [ + include: [{ model: model.Department, as: 'departments' }], + order: [ [ - {model : model.Department, as : 'departments'}, - model.Department.default_order_field(), + { model: model.Department, as: 'departments' }, + model.Department.default_order_field() ] - ], - }); - }; - - - this.get_company_with_all_leave_types = async function() { - const company = await this.getCompany({ - scope: ['with_leave_types'], - }); - - company.leave_types = company.leave_types - .sort((a, b) => b.sort_order - a.sort_order || sorter(a.name, b.name)); - - return company; - }; + ] + }) + } -}; + this.get_company_with_all_leave_types = function() { + return this.getCompany({ + include: [ + { + model: sequelize.models.LeaveType, + as: 'leave_types' + } + ], + order: [ + [ + { model: sequelize.models.LeaveType, as: 'leave_types' }, + 'sort_order', + 'DESC' + ], + [{ model: sequelize.models.LeaveType, as: 'leave_types' }, 'name'] + ] + }) + } +} diff --git a/lib/model/team_view.js b/lib/model/team_view.js index a319be503..3ce3108e1 100644 --- a/lib/model/team_view.js +++ b/lib/model/team_view.js @@ -1,19 +1,14 @@ +'use strict' -'use strict'; - -const - moment = require('moment'), - Promise = require('bluebird'), - Joi = require('joi'), - Exception = require('../error'), - _ = require('underscore'); -const { sorter } = require('../util'); +const Promise = require('bluebird') +const Joi = require('joi') +const Exception = require('../error') +const _ = require('underscore') +const { sorter } = require('../util') function TeamView(args) { - var me = this; - - this.user = args.user; - this.base_date = args.base_date || this.user.company.get_today(); + this.user = args.user + this.base_date = args.base_date || this.user.company.get_today() // Optional parameters that override base date specify months range // Team view is going to represent. @@ -24,113 +19,115 @@ function TeamView(args) { // If those two parameters are missed - base_date is used to determine with month // Team view would represent. // - this.start_date = args.start_date; - this.end_date = args.end_date; + this.start_date = args.start_date + this.end_date = args.end_date if (args.start_date && args.end_date && args.base_date) { Exception.throw_user_error({ - user_error : 'Failed to calculate team view', - system_error : 'TeamView could not be instanciated with start_date, end_data and base_date all defined.' - }); + user_error: 'Failed to calculate team view', + system_error: + 'TeamView could not be instanciated with start_date, end_data and base_date all defined.' + }) } } -TeamView.prototype.promise_team_view_details = function(args){ - +TeamView.prototype.promise_team_view_details = function(args) { // Handle case when no parameters were provided - if ( ! args ) { - args = {}; + if (!args) { + args = {} } - let - self = this, - user = this.user, - current_department_id = args.department_id, // optional parameter - related_departments = [], - current_department, - base_date = this.base_date; - - var promise_departments; + const self = this + const user = this.user + const current_department_id = args.department_id // optional parameter + let related_departments = [] + let current_department + const base_date = this.base_date - var normalise_departments_func = function(my_department, supervised_departments){ + let promise_departments + function normalise_departments_func(my_department, supervised_departments) { if (my_department) { // Get all related departments by combining supervised ones with // one current user belongs to - supervised_departments.push(my_department); + supervised_departments.push(my_department) } - supervised_departments = _.uniq(supervised_departments, function(item){ return item.id }); + supervised_departments = _.uniq(supervised_departments, item => item.id) // Copy all available departments for current user into closured variable // to pass it into template - related_departments = supervised_departments.sort((a, b) => sorter(a.name, b.name)) + related_departments = supervised_departments.sort((a, b) => + sorter(a.name, b.name) + ) // Find out what particular department is active now if (current_department_id) { - current_department = _.findWhere(supervised_departments, { id : Number(current_department_id) }); + current_department = _.findWhere(supervised_departments, { + id: Number(current_department_id) + }) } - return Promise.resolve(current_department ? [current_department] : supervised_departments); + return Promise.resolve( + current_department ? [current_department] : supervised_departments + ) } if (user.is_admin() || user.company.share_all_absences) { - // For admin users or if current company allows all users to see everybody's // time offs promise all departments for current company - promise_departments = user.company.getDepartments() - .then(function(departments){ - return normalise_departments_func(null, departments); - }); - + promise_departments = user.company + .getDepartments() + .then(departments => normalise_departments_func(null, departments)) } else { // Promise departments either supervised by current user or one that she belongs to promise_departments = Promise.join( user.getDepartment(), user.promise_supervised_departments(), normalise_departments_func - ); + ) } // Calculate users and leaves for every department - var promise_users_and_leaves = promise_departments - .map(department => self.start_date && self.end_date - ? department.promise_team_view_for_months_range( self.start_date, self.end_date ) - : department.promise_team_view_for_month( base_date ) - ); + const promise_users_and_leaves = promise_departments.map(department => + self.start_date && self.end_date + ? department.promise_team_view_for_months_range( + self.start_date, + self.end_date + ) + : department.promise_team_view_for_month(base_date) + ) return promise_users_and_leaves.then(users_and_leaves => { - users_and_leaves = users_and_leaves .flat(Infinity) - .sort((a,b) => sorter( - a.user.lastname + a.user.name, - b.user.lastname + b.user.name - )); + .sort((a, b) => + sorter(a.user.lastname + a.user.name, b.user.lastname + b.user.name) + ) return Promise.resolve({ - users_and_leaves : users_and_leaves, - related_departments : related_departments, - current_department : current_department, - }); - }); - -}; + users_and_leaves, + related_departments, + current_department + }) + }) +} // Experimenting with parameter validation done with Joi.js -const inject_statistics_args_schema = Joi.object() - .keys({ - leave_types : Joi.array().items( - Joi.object().keys({ - id : Joi.number().required(), - use_allowance : Joi.boolean().required(), - }) - ), - team_view_details : Joi.object().required().keys({ - users_and_leaves : Joi.array().required().items( - Joi.object().keys() - ) - }), - }); +const inject_statistics_args_schema = Joi.object().keys({ + leave_types: Joi.array().items( + Joi.object().keys({ + id: Joi.number().required(), + use_allowance: Joi.boolean().required() + }) + ), + team_view_details: Joi.object() + .required() + .keys({ + users_and_leaves: Joi.array() + .required() + .items(Joi.object().keys()) + }) +}) /* * Takes "team view details" and enrich them with statistics about absences @@ -138,85 +135,93 @@ const inject_statistics_args_schema = Joi.object() * * */ -TeamView.prototype.inject_statistics = function(args){ - +TeamView.prototype.inject_statistics = function(args) { // Validate parameters - let param_validation = Joi.validate(args, inject_statistics_args_schema, { allowUnknown : true }); + const param_validation = Joi.validate(args, inject_statistics_args_schema, { + allowUnknown: true + }) if (param_validation.error) { - console.log('An error occured when trying to validate args in inject_statistics.'); - console.dir(param_validation.error); - throw new Error('Failed to validate parameters in TeamView.inject_statistics'); + console.log( + 'An error occured when trying to validate args in inject_statistics.' + ) + console.dir(param_validation.error) + throw new Error( + 'Failed to validate parameters in TeamView.inject_statistics' + ) } - let - team_view_details = args.team_view_details, - leave_types = args.leave_types || []; + const team_view_details = args.team_view_details + const leave_types = args.leave_types || [] // Convert leave types array into look-up map - let leave_types_map = {}; - leave_types.forEach( lt => leave_types_map[lt.id] = lt ); - - team_view_details - .users_and_leaves - .forEach(node => { - - let deducted_days = 0; - - // Set statistics by leave type to zeros - let leave_type_stat = {}; - leave_types.forEach( lt => leave_type_stat[lt.id] = 0 ); - - node - .days - // Consider only those days that have any leave objects - .filter( day => !! day.leave_obj ) - // Ignore those days which were not approved yet - .filter( day => !! day.leave_obj.is_approved_leave() ) - // Ignore weekends - .filter( day => ! day.is_weekend ) - // Ignore bank holidays - .filter( day => ! day.is_bank_holiday ) - .forEach( day => { - - if (day.is_leave_morning) { - - leave_type_stat[ day.morning_leave_type_id ] = leave_type_stat[ day.morning_leave_type_id ] + 0.5; - - if ( leave_types_map[ day.morning_leave_type_id ] && leave_types_map[ day.morning_leave_type_id ].use_allowance ) { - deducted_days = deducted_days + 0.5; - } + const leave_types_map = {} + leave_types.forEach(lt => (leave_types_map[lt.id] = lt)) + + team_view_details.users_and_leaves.forEach(node => { + let deducted_days = 0 + + // Set statistics by leave type to zeros + const leave_type_stat = {} + leave_types.forEach(lt => (leave_type_stat[lt.id] = 0)) + + node.days + // Consider only those days that have any leave objects + .filter(day => !!day.leave_obj) + // Ignore those days which were not approved yet + .filter(day => !!day.leave_obj.is_approved_leave()) + // Ignore weekends + .filter(day => !day.is_weekend) + // Ignore bank holidays + .filter(day => !day.is_bank_holiday) + .forEach(day => { + if (day.is_leave_morning) { + leave_type_stat[day.morning_leave_type_id] = + leave_type_stat[day.morning_leave_type_id] + 0.5 + + if ( + leave_types_map[day.morning_leave_type_id] && + leave_types_map[day.morning_leave_type_id].use_allowance + ) { + deducted_days = deducted_days + 0.5 } + } - if (day.is_leave_afternoon) { - - if ( leave_types_map[ day.afternoon_leave_type_id ] && leave_types_map[ day.afternoon_leave_type_id ].use_allowance ) { - deducted_days = deducted_days + 0.5; - } - - leave_type_stat[ day.afternoon_leave_type_id ] = leave_type_stat[ day.afternoon_leave_type_id ] + 0.5; + if (day.is_leave_afternoon) { + if ( + leave_types_map[day.afternoon_leave_type_id] && + leave_types_map[day.afternoon_leave_type_id].use_allowance + ) { + deducted_days = deducted_days + 0.5 } - }); - - let statistics = { - deducted_days : deducted_days, - // Shows statistics by leave type - leave_type_break_down : { - // format for machine using - lite_version : leave_type_stat, - // format for rendering to end users - pretty_version : leave_types - // Sort by name - .sort((a,b) => sorter(a.name, b.name)) - .map(lt => ({ name : lt.name, stat : leave_type_stat[ lt.id ], id : lt.id })), + leave_type_stat[day.afternoon_leave_type_id] = + leave_type_stat[day.afternoon_leave_type_id] + 0.5 } - }; + }) - node.statistics = statistics; - }); + const statistics = { + deducted_days, + // Shows statistics by leave type + leave_type_break_down: { + // format for machine using + lite_version: leave_type_stat, + // format for rendering to end users + pretty_version: leave_types + // Sort by name + .sort((a, b) => sorter(a.name, b.name)) + .map(lt => ({ + name: lt.name, + stat: leave_type_stat[lt.id], + id: lt.id + })) + } + } - return Promise.resolve( team_view_details ); -}; + node.statistics = statistics + }) + + return Promise.resolve(team_view_details) +} /* * Take "team view details" and user for whom them were generated @@ -225,26 +230,22 @@ TeamView.prototype.inject_statistics = function(args){ * * */ -TeamView.prototype.restrainStatisticsForUser = function(args){ - +TeamView.prototype.restrainStatisticsForUser = function(args) { // TODO Consider parameters validation in the same fashion as in inject_statistics method - let - team_view_details = args.team_view_details, - observer_user = args.user; + const team_view_details = args.team_view_details + const observer_user = args.user - let supervised_user_map = {}; - observer_user.supervised_users.forEach( u => supervised_user_map[ u.id ] = u); + const supervised_user_map = {} + observer_user.supervised_users.forEach(u => (supervised_user_map[u.id] = u)) - team_view_details - .users_and_leaves - .forEach(item => { - if (item.statistics && ! supervised_user_map[ item.user.id ]) { - delete item.statistics; - } - }); + team_view_details.users_and_leaves.forEach(item => { + if (item.statistics && !supervised_user_map[item.user.id]) { + delete item.statistics + } + }) - return Promise.resolve( team_view_details ); -}; + return Promise.resolve(team_view_details) +} -module.exports = TeamView; +module.exports = TeamView diff --git a/lib/model/user_allowance.js b/lib/model/user_allowance.js index f9a4b4d5f..195a96667 100644 --- a/lib/model/user_allowance.js +++ b/lib/model/user_allowance.js @@ -1,4 +1,3 @@ - /* * This class represent Employee's allowance. * @@ -8,58 +7,51 @@ * * */ -"use strict"; +'use strict' -const - moment = require('moment'), - Promise= require('bluebird'), - Joi = require('joi'); +const moment = require('moment') +const Promise = require('bluebird') +const Joi = require('joi') /* * Section where we declare interfaces used in methods for this class. * */ -const - - schema_user = Joi - .object() - .required(), - - schema_year = Joi - .object() - .type(moment) - // Consider removing defaults - .default(() => moment.utc(), 'Default year is current one'), - - schema_now = Joi - .object() - .type(moment) - // Consider removing defaults - // Note on this line: once it used to derive now from user's company - // get_now() method, but Joi.js has high penalty on defaults which - // use function with 'context' so I have removed it. - // Yes it is less precise but much more faster code. - .default(() => moment.utc(), 'Default is UTC one not from company specific'), - - schema_promise_allowance = Joi.object().required().keys({ - year : schema_year, - user : schema_user, - now : schema_now, +const schema_user = Joi.object().required() +const schema_year = Joi.object() + .type(moment) + // Consider removing defaults + .default(() => moment.utc(), 'Default year is current one') +const schema_now = Joi.object() + .type(moment) + // Consider removing defaults + // Note on this line: once it used to derive now from user's company + // get_now() method, but Joi.js has high penalty on defaults which + // use function with 'context' so I have removed it. + // Yes it is less precise but much more faster code. + .default(() => moment.utc(), 'Default is UTC one not from company specific') +const schema_promise_allowance = Joi.object() + .required() + .keys({ + year: schema_year, + user: schema_user, + now: schema_now, /** * If TRUE now is not going to be changed. */ - forceNow: Joi.boolean().default(false), - }), - - scheme_constructor = Joi.object().required().keys({ - user : schema_user, - - number_of_days_taken_from_allowance : Joi.number().required(), - manual_adjustment : Joi.number().required(), - carry_over : Joi.number().required(), - nominal_allowance : Joi.number().required(), - now : schema_now, - }); + forceNow: Joi.boolean().default(false) + }) +const scheme_constructor = Joi.object() + .required() + .keys({ + user: schema_user, + + number_of_days_taken_from_allowance: Joi.number().required(), + manual_adjustment: Joi.number().required(), + carry_over: Joi.number().required(), + nominal_allowance: Joi.number().required(), + now: schema_now + }) /* * Class definition. @@ -67,101 +59,109 @@ const * */ class UserAllowance { - constructor(args) { - // Validate provided parameters args = Joi.attempt( args, scheme_constructor, 'Failed parameters validation for UserAllowance constructor' - ); + ) - const self = this; + const self = this // Private properties (not to be accessed directly) - self._user = args.user; - self._number_of_days_taken_from_allowance = args.number_of_days_taken_from_allowance; - self._manual_adjustment = args.manual_adjustment; - self._carry_over = args.carry_over; - self._nominal_allowance = args.nominal_allowance; - self._now = args.now; + self._user = args.user + self._number_of_days_taken_from_allowance = + args.number_of_days_taken_from_allowance + self._manual_adjustment = args.manual_adjustment + self._carry_over = args.carry_over + self._nominal_allowance = args.nominal_allowance + self._now = args.now } get total_number_of_days_in_allowance() { - const self = this; + const self = this - return (self.nominal_allowance + + return ( + self.nominal_allowance + self.carry_over + self.manual_adjustment + - self.employement_range_adjustment); + self.employement_range_adjustment + ) } get number_of_days_taken_from_allowance() { - return this._number_of_days_taken_from_allowance; + return this._number_of_days_taken_from_allowance } get manual_adjustment() { - return this._manual_adjustment; + return this._manual_adjustment } get carry_over() { - return this._carry_over; + return this._carry_over } get nominal_allowance() { - return this._nominal_allowance; + return this._nominal_allowance } get number_of_days_available_in_allowance() { - const self = this; + const self = this // Check case when user started after "now", then even so she has // nominal allowance derived from general settings, she could not // use it as it is valid for time she was not here - if (self.user.start_date && + if ( + self.user.start_date && moment.utc(self.user.start_date).year() > self._now.year() ) { - return 0; + return 0 } return ( - self.total_number_of_days_in_allowance - - self.number_of_days_taken_from_allowance - + (self.is_accrued_allowance ? self.accrued_adjustment : 0) - ); + self.total_number_of_days_in_allowance - + self.number_of_days_taken_from_allowance + + (self.is_accrued_allowance ? self.accrued_adjustment : 0) + ) } get is_accrued_allowance() { - return !! this.user.department.is_accrued_allowance; + return !!this.user.department.is_accrued_allowance } get user() { - return this._user; + return this._user } get employement_range_adjustment() { - let - self = this, - now = self._now.clone(); + const self = this + const now = self._now.clone() if ( - now.year() !== moment.utc(self.user.start_date).year() - && ( ! self.user.end_date || moment.utc(self.user.end_date).year() > now.year() ) - ){ - return 0; + now.year() !== moment.utc(self.user.start_date).year() && + (!self.user.end_date || + moment.utc(self.user.end_date).year() > now.year()) + ) { + return 0 } - let start_date = moment.utc(self.user.start_date).year() === now.year() - ? moment.utc(self.user.start_date) - : now.clone().startOf('year'), - end_date = self.user.end_date && moment.utc(self.user.end_date).year() <= now.year() - ? moment.utc(self.user.end_date) - : now.clone().endOf('year'); + const start_date = + moment.utc(self.user.start_date).year() === now.year() + ? moment.utc(self.user.start_date) + : now.clone().startOf('year') + const end_date = + self.user.end_date && moment.utc(self.user.end_date).year() <= now.year() + ? moment.utc(self.user.end_date) + : now.clone().endOf('year') - return -1*(self.nominal_allowance - Math.round( - self.nominal_allowance * end_date.diff(start_date, 'days') / 365 - )); + return ( + -1 * + (self.nominal_allowance - + Math.round( + (self.nominal_allowance * end_date.diff(start_date, 'days')) / 365 + )) + ) } /* @@ -170,9 +170,8 @@ class UserAllowance { * * */ get accrued_adjustment() { - const - self = this, - now = self._now.clone(); + const self = this + const now = self._now.clone() // Consider only following parts of allowance when calculating accrual // adjustment: @@ -182,67 +181,75 @@ class UserAllowance { // Other components do not make sense, e.g.: // * carried over part - it could be immediately used as employee // already worked on them last year - const allowance = self.nominal_allowance - + self.manual_adjustment - + self.employement_range_adjustment; + const allowance = + self.nominal_allowance + + self.manual_adjustment + + self.employement_range_adjustment - const period_starts_at = moment.utc(self.user.start_date).year() === now.year() - ? moment.utc(self.user.start_date) - : now.clone().startOf('year'); + const period_starts_at = + moment.utc(self.user.start_date).year() === now.year() + ? moment.utc(self.user.start_date) + : now.clone().startOf('year') - const period_ends_at = self.user.end_date && moment.utc(self.user.end_date).year() <= now.year() - ? moment.utc(self.user.end_date) - : now.clone().endOf('year'); + const period_ends_at = + self.user.end_date && moment.utc(self.user.end_date).year() <= now.year() + ? moment.utc(self.user.end_date) + : now.clone().endOf('year') - let days_in_period = period_ends_at.diff( period_starts_at, 'days' ); + const days_in_period = period_ends_at.diff(period_starts_at, 'days') - let delta = allowance * period_ends_at.diff( now, 'days' ) / days_in_period; + const delta = + (allowance * period_ends_at.diff(now, 'days')) / days_in_period - return -1 * (Math.round(delta * 2) / 2).toFixed(1); + return -1 * (Math.round(delta * 2) / 2).toFixed(1) } - /* * The idea of this static method is to be constructor for UserAllowance class. * It takes parameters and perform all necessary (and costly) actions to fetch * all info required for allowance calculation for given user and year. * */ static promise_allowance(args) { - args = Joi.attempt( args, schema_promise_allowance, 'Failed to validate parameters for promise_allowance' - ); + ) - let - user = args.user, - year = args.year, - number_of_days_taken_from_allowance, - manual_adjustment, - carried_over_allowance; + const user = args.user + const year = args.year + let number_of_days_taken_from_allowance + let manual_adjustment + let carried_over_allowance - const {forceNow, now} = args; + const { forceNow, now } = args - let flow = Promise.resolve(); + let flow = Promise.resolve() - if ( user.my_leaves === undefined ) { - flow = flow.then(() => user.reload_with_leave_details({year})); + if (user.my_leaves === undefined) { + flow = flow.then(() => user.reload_with_leave_details({ year })) } // Fetch adjustment and Carry over allowance - flow = flow.then(() => user.promise_adjustment_and_carry_over_for_year(year)); + flow = flow.then(() => + user.promise_adjustment_and_carry_over_for_year(year) + ) flow = flow.then(adjustment_and_coa => { - manual_adjustment = adjustment_and_coa.adjustment; - carried_over_allowance = adjustment_and_coa.carried_over_allowance; - return Promise.resolve(); - }); - - flow = flow.then(() => Promise.resolve( - number_of_days_taken_from_allowance = user.calculate_number_of_days_taken_from_allowance({year : year.format('YYYY')}) - )); - + manual_adjustment = adjustment_and_coa.adjustment + carried_over_allowance = adjustment_and_coa.carried_over_allowance + return Promise.resolve() + }) + + flow = flow.then(() => + Promise.resolve( + (number_of_days_taken_from_allowance = user.calculate_number_of_days_taken_from_allowance( + { + year: year.format('YYYY') + } + )) + ) + ) // Got all necessary data for UserAllowance object so build it! flow = flow.then(() => { @@ -250,21 +257,21 @@ class UserAllowance { user, manual_adjustment, number_of_days_taken_from_allowance, - carry_over: carried_over_allowance, - nominal_allowance: user.department.allowance, - }; + carry_over: carried_over_allowance, + nominal_allowance: user.department.allowance + } if (forceNow && now) { - args.now = now; - } else if ( year && year.year() !== moment.utc().year()) { - args.now = year.startOf('year'); + args.now = now + } else if (year && year.year() !== moment.utc().year()) { + args.now = year.startOf('year') } - return new UserAllowance(args); - }); + return new UserAllowance(args) + }) - return flow; + return flow } } -module.exports = UserAllowance; +module.exports = UserAllowance diff --git a/lib/model/user_importer.js b/lib/model/user_importer.js index 78a24e618..289b7c90a 100644 --- a/lib/model/user_importer.js +++ b/lib/model/user_importer.js @@ -1,211 +1,242 @@ - -"use strict"; - -const - Joi = require('joi'), - uuid = require('node-uuid'), - Promise = require('bluebird'), - _ = require('underscore'), - Exception = require('../error'), - Models = require('./db'); - -const add_user_interface_schema = Joi.object().required().keys({ - email : Joi.string().email(), - lastname : Joi.string(), - name : Joi.string(), - company_id : Joi.number().integer().positive(), - department_id : Joi.number().integer().positive(), - - start_date : Joi.string().optional(), - end_date : Joi.string().default(null).allow(null), - admin : Joi.boolean().default(false), - auto_approve : Joi.boolean().default(false), - password : Joi.string().default(() => uuid.v4(), 'Populate default password'), - }); - +'use strict' + +const Joi = require('joi') +const uuid = require('node-uuid') +const Promise = require('bluebird') +const _ = require('underscore') +const Exception = require('../error') +const Models = require('./db') + +const add_user_interface_schema = Joi.object() + .required() + .keys({ + email: Joi.string().email(), + slack_username: Joi.string() + .optional() + .default(null) + .allow(null, ''), + lastname: Joi.string(), + name: Joi.string(), + company_id: Joi.number() + .integer() + .positive(), + department_id: Joi.number() + .integer() + .positive(), + + start_date: Joi.string().optional(), + end_date: Joi.string() + .default(null) + .allow(null), + admin: Joi.boolean().default(false), + auto_approve: Joi.boolean().default(false), + password: Joi.string().default(() => uuid.v4(), 'Populate default password') + }) function add_user(args) { - let validated_args = Joi.validate(args, add_user_interface_schema); + const validated_args = Joi.validate(args, add_user_interface_schema) if (validated_args.error) { - console.log('An error occured when validatin parameters for add_user: '); - console.dir(validated_args); + console.log('An error occured when validating parameters for add_user: ') + console.dir(validated_args) Exception.throw_user_error({ - system_error : 'Failed to add new due to validation errors', - user_error : 'Failed to add user', - }); + system_error: 'Failed to add new due to validation errors', + user_error: 'Failed to add user: ' + validated_args.error + }) } // Use validated (and expanded) arguments object - args = validated_args.value; + args = validated_args.value - let attributes = {}; + const attributes = {} + const slack_username = args.slack_username + ? '@' + args.slack_username.replace('@', '') + : null - attributes.email = args.email.toLowerCase(); - attributes.lastname = args.lastname; - attributes.name = args.name; - attributes.companyId = args.company_id; - attributes.DepartmentId = args.department_id; + attributes.email = args.email.toLowerCase() + attributes.slack_username = slack_username + attributes.lastname = args.lastname + attributes.name = args.name + attributes.company_id = args.company_id + attributes.department_id = args.department_id - attributes.password = Models.User.hashify_password(args.password); - attributes.admin = args.admin; - attributes.auto_approve = args.auto_approve; - attributes.end_date = args.end_date; + attributes.password = Models.User.hashify_password(args.password) + attributes.admin = args.admin + attributes.auto_approve = args.auto_approve + attributes.end_date = args.end_date // Pass start date inky if it is set, otherwise rely on database to use // default value if (args.start_date) { - attributes.start_date = args.start_date; + attributes.start_date = args.start_date } - return Promise.resolve() - - // Ensure given department ID is owned by given company ID - .then(() => Models.Department - .findOne({ - where : { id : args.department_id, companyId : args.company_id }, - }) - .then( department => { - if ( ! department ) { - Exception.throw_user_error({ - system_error : 'Mismatch in department/company IDs when creating new user ' - + args.department_id + '/' + args.company_id, - user_error : 'Used wrong department', - }); - } - return Promise.resolve(); - }) - ) - - // Ensure provided email is free to use - .then(() => validate_email_to_be_free({ email : args.email })) - - // Create new user record - .then(() => Models.User.create(attributes)); + return ( + Promise.resolve() + + // Ensure given department ID is owned by given company ID + .then(() => + Models.Department.findOne({ + where: { id: args.department_id, company_id: args.company_id } + }).then(department => { + if (!department) { + Exception.throw_user_error({ + system_error: + 'Mismatch in department/company IDs when creating new user ' + + args.department_id + + '/' + + args.company_id, + user_error: 'Used wrong department' + }) + } + return Promise.resolve() + }) + ) + + // Ensure provided email is free to use + .then(() => validate_email_to_be_free({ email: args.email })) + + // Create new user record + .then(() => Models.User.create(attributes)) + ) } function add_users_in_bulk(args) { - let bulk_header = args.bulk_header, - bulk_data = args.bulk_data, - company_id = args.to_company_id; - - let company, - email_vector_index = 0, - lastname_vector_index = 1, - name_vector_index = 2, - department_vector_index = 3; - - return Models.Company.scope('with_simple_departments').findOne({ - where : { id : company_id }, - }) + const bulk_header = args.bulk_header + const bulk_data = args.bulk_data + const company_id = args.to_company_id + + let company + const email_vector_index = 0 + const slack_username_vector_index = 1 + const lastname_vector_index = 2 + const name_vector_index = 3 + const department_vector_index = 4 + + return ( + Models.Company.scope('with_simple_departments') + .findOne({ + where: { id: company_id } + }) + // Validate department names and replace names with IDs + .then(cmp => { + company = cmp + const dep_name_to_id = _.object( + company.departments.map(dep => [dep.name, dep.id]) + ) - // Validate department names and replace names with IDs - .then(cmp => { - company = cmp; - let dep_name_to_id = _.object( - company.departments.map(dep => [dep.name, dep.id]) - ); - - let with_invalid_departments = _.filter( - bulk_data, vector => ! dep_name_to_id[ vector[ department_vector_index] ] - ); - - if (with_invalid_departments.length > 0) { - let unknown_departments = with_invalid_departments - .map(vector => '"'+vector[department_vector_index]+'"') - .join(', '); - - Exception.throw_user_error({ - user_error : 'Following departments could not be found in ' - + company.name + ' account: ' + unknown_departments, - system_error : 'While importing users to company ' - + company.id + ' there were unknown departments ' - + unknown_departments, - }); - } + const with_invalid_departments = _.filter( + bulk_data, + vector => !dep_name_to_id[vector[department_vector_index]] + ) - bulk_data.forEach( - vector => vector[ department_vector_index ] = dep_name_to_id[ vector[ department_vector_index ] ] - ); + if (with_invalid_departments.length > 0) { + const unknown_departments = with_invalid_departments + .map(vector => '"' + vector[department_vector_index] + '"') + .join(', ') - return Promise.resolve(); - }) + Exception.throw_user_error({ + user_error: + 'Following departments could not be found in ' + + company.name + + ' account: ' + + unknown_departments, + system_error: + 'While importing users to company ' + + company.id + + ' there were unknown departments ' + + unknown_departments + }) + } - // Add users - .then(() => { - return Promise.map(bulk_data, vector => { - let email = vector[ email_vector_index ]; - - return Promise.resolve() - .then(() => add_user({ - email : email, - lastname : vector[ lastname_vector_index ], - name : vector[ name_vector_index ], - department_id : vector[ department_vector_index ], - company_id : company_id, - })) - .catch(error => { - return Promise.resolve({ - error : error, - email : email, - }); - }); - }, { - concurrency : 2, - }) - }) + bulk_data.forEach( + vector => + (vector[department_vector_index] = + dep_name_to_id[vector[department_vector_index]]) + ) - // Sort out successfully creted users and errors - .then(users_or_errors => { - let result = { - users : [], - errors : [], - }; + return Promise.resolve() + }) - users_or_errors.forEach( item => { - item.hasOwnProperty('error') - ? result.errors.push( item ) - : result.users.push( item ) - }); + // Add users + .then(() => + Promise.map( + bulk_data, + vector => { + const email = vector[email_vector_index] + + return Promise.resolve() + .then(() => + add_user({ + email, + slack_username: vector[slack_username_vector_index], + lastname: vector[lastname_vector_index], + name: vector[name_vector_index], + department_id: vector[department_vector_index], + company_id + }) + ) + .catch(error => + Promise.resolve({ + error, + email + }) + ) + }, + { + concurrency: 2 + } + ) + ) + + // Sort out successfully created users and errors + .then(users_or_errors => { + const result = { + users: [], + errors: [] + } - return Promise.resolve(result); - }); + users_or_errors.forEach(item => { + item.hasOwnProperty('error') + ? result.errors.push(item) + : result.users.push(item) + }) + return Promise.resolve(result) + }) + ) } -const validate_email_to_be_free_schema = Joi.object().required().keys({ - email : Joi.string().email().required(), - }); +const validate_email_to_be_free_schema = Joi.object() + .required() + .keys({ + email: Joi.string() + .email() + .required() + }) function validate_email_to_be_free(args) { - let validate_args = Joi.validate(args, validate_email_to_be_free_schema); + const validate_args = Joi.validate(args, validate_email_to_be_free_schema) if (validate_args.error) { Exception.throw_user_error({ - system_error : 'validate_email_to_be_free failed arguments validation', - user_error : 'Failed to validate email', - }); + system_error: 'validate_email_to_be_free failed arguments validation', + user_error: 'Failed to validate email' + }) } - return Models - .User - .find_by_email(args.email) - .then(user => { - - if (user) { - Exception.throw_user_error( - 'Email is already in use' - ); - } + return Models.User.find_by_email(args.email).then(user => { + if (user) { + Exception.throw_user_error('Email is already in use') + } - return Promise.resolve(); - }); + return Promise.resolve() + }) } module.exports = { - add_user : add_user, - add_users_in_bulk : add_users_in_bulk, - validate_email_to_be_free : validate_email_to_be_free, -}; - + add_user, + add_users_in_bulk, + validate_email_to_be_free +} diff --git a/lib/passport/getCompanyAdminByToken.js b/lib/passport/getCompanyAdminByToken.js index f8382ad0e..81379b4f6 100644 --- a/lib/passport/getCompanyAdminByToken.js +++ b/lib/passport/getCompanyAdminByToken.js @@ -1,40 +1,37 @@ +'use strict' -'use strict'; +const { throwUserError } = require('../error') +const Promise = require('bluebird') -const - { throwUserError } = require('../error'), - Promise = require('bluebird'); - -module.exports = ({token, model}) => { - - if ( ! token ) { +module.exports = ({ token, model }) => { + if (!token) { throwUserError({ - system_error : "Provided token has FALSY value", - user_error : "Wrong access token", - }); + system_error: 'Provided token has FALSY value', + user_error: 'Wrong access token' + }) } - let action = model.Company.getCompanyByApiToken({ token }); + let action = model.Company.getCompanyByApiToken({ token }) action = action.then(company => { - if ( ! company ) { + if (!company) { throwUserError({ system_error: `Cannot find company record for provided token ${token}`, - user_error: 'Wrong access token', - }); + user_error: 'Wrong access token' + }) } - const [adminUser] = company.get('users').filter(u => u.is_admin()); + const [adminUser] = company.get('users').filter(u => u.is_admin()) - if ( ! adminUser) { + if (!adminUser) { throwUserError({ - system_error: `Failed to find admin users for company ${ company.id }`, - user_error: 'Wrong access token', - }); + system_error: `Failed to find admin users for company ${company.id}`, + user_error: 'Wrong access token' + }) } - return Promise.resolve(adminUser); - }); + return Promise.resolve(adminUser) + }) - return action; -}; + return action +} diff --git a/lib/passport/index.js b/lib/passport/index.js index 9509b99d9..d8a2ae7a5 100644 --- a/lib/passport/index.js +++ b/lib/passport/index.js @@ -1,4 +1,3 @@ - /* * Module to encapsulate logic for passport instantiation used for * authentication. @@ -7,29 +6,28 @@ * * */ -'use strict'; +'use strict' -const - model = require('../model/db'), - passport = require('passport'), - Promise = require('bluebird'), - LocalStrategy = require('passport-local').Strategy, - BearerStrategy= require('passport-http-bearer').Strategy, - getCompanyAdminByToken = require('./getCompanyAdminByToken'); +const model = require('../model/db') +const passport = require('passport') +const Promise = require('bluebird') +const LocalStrategy = require('passport-local').Strategy +const BearerStrategy = require('passport-http-bearer').Strategy +const getCompanyAdminByToken = require('./getCompanyAdminByToken') +const config = require('../config') // In case if user is successfully logged in, make sure it is // activated function prepare_user_for_session(args) { - var user = args.user, - done = args.done; + const user = args.user + const done = args.done - user.maybe_activate() - .then(function(user){ - return user.reload_with_session_details(); + user + .maybe_activate() + .then(user => user.reload_with_session_details()) + .then(() => { + done(null, user) }) - .then(function(){ - done(null, user); - }); } // Function that performs authentication of given user object @@ -37,143 +35,224 @@ function prepare_user_for_session(args) { // The method is callback based and the result is conveyed // via provided callback function "done" // -function authenticate_user(args){ +function authenticate_user({ user, password, done }) { + const email = user.email + + /* + * In case of LDAP authentification connect the LDAP server + */ + if (user.company.ldap_auth_enabled) { + // email = 'euler@ldap.forumsys.com'; password = 'password'; // TODO remove + Promise.resolve(user.company.get_ldap_server()) + .then(ldap_server => { + ldap_server.authenticate(email, password, (err, u) => { + ldap_server.close() + + if (err) { + console.log('LDAP auth error: %s', err) + return done(null, false) + } + + prepare_user_for_session({ + user, + done + }) + }) + + ldap_server.close() + }) + .catch(error => { + console.error( + 'Failed while trying to deal with LDAP server with error: %s', + error, + error.stack + ) - var user = args.user, - password = args.password, - done = args.done, - email = user.email; + done(null, false) + }) - // In case of LDAP authentification connect the LDAP server - if ( user.company.ldap_auth_enabled ) { + return + } -// email = 'euler@ldap.forumsys.com'; password = 'password'; // TODO remove - Promise.resolve( user.company.get_ldap_server() ) - .then(function(ldap_server){ + /** + * Local authentication + */ - ldap_server.authenticate(email, password, function (err, u) { - ldap_server.close(); + // Check if the provided password is correct + if (!user.is_my_password(password)) { + console.error( + 'When login user entered existing email ' + + email + + ' but incorrect password' + ) + done(null, false) + return + } + + // Authenticate the user + prepare_user_for_session({ + user, + done + }) +} - if (err) { - console.log("LDAP auth error: %s", err); - return done(null, false); +function strategy_handler(email, password, strategy, done) { + let authFunction + switch (strategy) { + case 'local': + authFunction = function({ user, password, done }) { + authenticate_user({ user, password, done }) + } + break + case 'google': + authFunction = function({ user, email, done }) { + let domain + domain = email.split('@') + if (domain && domain.length > 0) { + domain = domain[domain.length - 1] + } else { + domain = false } - prepare_user_for_session({ - user : user, - done : done, - }); - }); - ldap_server.close(); - }) - .catch(function(error){ - console.error('Failed while trying to deal with LDAP server with error: %s', error); + if (!domain) { + return done('no auth domain') + } - done(null, false); - }); + // check if valid domain + const validDomains = config.get('google:auth:domains') || false + if (!validDomains) { + console.error('no valid domains') - // Provided password is correct - } else if (user.is_my_password(password)) { + return done('no valid domains for google set') + } - prepare_user_for_session({ - user : user, - done : done, - }); + if (validDomains.indexOf(domain) == -1) { + console.error('valid domains: ', validDomains, 'not valid: ', domain) - // User exists but provided password does not match - } else { - console.error( - 'When login user entered existsing email ' +email+ - ' but incorrect password' - ); - done(null, false); - } -} + return done('invalid auth domain') + } -function strategy_handler(email, password, done) { + prepare_user_for_session({ + user, + done + }) + } + break + default: + return done('invalid strategy: ' + strategy) + } // Normalize email to be in lower case - email = email.toLowerCase(); - - model.User - .find_by_email( email ) - .then(function(user){ + email = email.toLowerCase() + model.User.find_by_email(email) + .then(user => { // Case when no user for provided email - if ( ! user ) { + if (!user) { console.error( - 'At login: failed to find user with provided email %s', email - ); + 'At login: failed to find user with provided email %s', + email + ) // We need to abort the execution of current callback function // hence the return before calling "done" callback - return done(null, false); + return done(null, false) } // Athenticate user by provided password - user.getCompany() - .then(function(company){ - - // We need to have company for user fetchef dow the line so query it now - user.company = company; - - authenticate_user({ - user : user, - password : password, - done : done, - }); - }); + user.getCompany().then(company => { + // We need to have company for user fetchef dow the line so query it now + user.company = company + + authFunction({ + user, + email, + password, + done + }) + }) }) // there was unknown error when trying to retrieve user object - .catch(function(error){ + .catch(error => { console.error( 'At login: unknown error when trying to login in as %s. Error: %s', - email, error - ); + email, + error, + error.stack + ) - done(null, false); - }); + done(null, false) + }) } -module.exports = function(){ - - passport.use(new LocalStrategy( strategy_handler )); +module.exports = function() { + if (config.get('login:google')) { + const GoogleStrategy = require('passport-google-oauth20').Strategy + + passport.use( + new GoogleStrategy( + { + clientID: config.get('google:auth:clientid'), + clientSecret: config.get('google:auth:clientsecret'), + callbackURL: config.get('branding:url') + '/auth/google/callback' + }, + (accessToken, refreshToken, profile, done) => { + if (profile.emails && profile.emails.length > 0) { + const email = profile.emails[0].value + strategy_handler(email, false, 'google', done) + } else { + console.error('missing email in google reponse - scope?', profile) + done('no email found') + } + } + ) + ) + } - passport.use(new BearerStrategy((token, done) => { - getCompanyAdminByToken({ token, model }) - .then(user => user.reload_with_session_details()) - .then(user => done(null, user)) - .catch(error => { - console.log(`Failed to authenticate TOKEN. Reason: '${error}'`); - done(null, false); - }); - })); + passport.use( + new LocalStrategy((email, password, done) => { + strategy_handler(email, password, 'local', done) + }) + ) + + passport.use( + new BearerStrategy((token, done) => { + getCompanyAdminByToken({ token, model }) + .then(user => user.reload_with_session_details()) + .then(user => done(null, user)) + .catch(error => { + console.log(`Failed to authenticate TOKEN. Reason: '${error}'`) + done(null, false) + }) + }) + ) // Define how user object is going to be flattered into session // after request is processed. // In session store we save only user ID - passport.serializeUser(function(user, done) { - done(null, user.id); - }); + passport.serializeUser((user, done) => { + done(null, user.id) + }) // Defines how the user object is restored based on data saved // in session storage. // Fetch user data from DB based on ID. - passport.deserializeUser(function(id, done) { - - model.User.find({where : {id : id}}).then(function(user){ - return user.reload_with_session_details(); - }) - .then(function(user){ - done(null, user); - }) - .catch(function(error){ - console.error('Failed to fetch session user '+id+' with error: '+error); + passport.deserializeUser((id, done) => { + model.User.findOne({ where: { id } }) + .then(user => user.reload_with_session_details()) + .then(user => { + done(null, user) + }) + .catch(error => { + console.error( + 'Failed to fetch session user ' + id + ' with error: ' + error, + error.stack + ) - done(null, false, { message : 'Failed to fetch session user' }); - }); - }); + done(null, false, { message: 'Failed to fetch session user' }) + }) + }) - return passport; -}; + return passport +} diff --git a/lib/route/api/index.js b/lib/route/api/index.js index 0926662a2..aa76ad6d8 100644 --- a/lib/route/api/index.js +++ b/lib/route/api/index.js @@ -1,47 +1,55 @@ +'use strict' -"use strict"; +const express = require('express') +const router = express.Router() -const - express = require('express'), - router = express.Router(); - - -const NOTIFICATION_TYPE_PENDING_REQUESTS = 'pending_request'; +const NOTIFICATION_TYPE_PENDING_REQUESTS = 'pending_request' /** * Factory method that created a notification of given type */ -const newNotification = ({type, value}) => { - +const newNotification = ({ type, value }) => { if (type === NOTIFICATION_TYPE_PENDING_REQUESTS) { return { type, numberOfRequests: value, - label: (value === 1 ? 'A leave request to process' : `${value} leave requests to process`), - link: '/requests/', + label: + value === 1 + ? 'A leave request to process' + : `${value} leave requests to process`, + link: '/requests/' } } - return null; -}; + return null +} router.get('/notifications/', async (req, res) => { - const actingUser = req.user; + const actingUser = req.user - const data = []; + const data = [] try { - const leaves = await actingUser.promise_leaves_to_be_processed(); + const leaves = await actingUser.promise_leaves_to_be_processed() if (leaves.length > 0) { - data.push(newNotification({type: NOTIFICATION_TYPE_PENDING_REQUESTS, value: leaves.length})); + data.push( + newNotification({ + type: NOTIFICATION_TYPE_PENDING_REQUESTS, + value: leaves.length + }) + ) } - res.json({data}); + res.json({ data }) } catch (error) { - console.log(`Failed to fetch notifications for user [${actingUser.id}]: ${error} at ${error.stack}`); - res.json({ error: 'Failed to fetch notifications.' }); + console.log( + `Failed to fetch notifications for user [${actingUser.id}]: ${error} at ${ + error.stack + }` + ) + res.json({ error: 'Failed to fetch notifications.' }) } -}); +}) -module.exports = router; \ No newline at end of file +module.exports = router diff --git a/lib/route/audit.js b/lib/route/audit.js index 512dfd24d..387d0f171 100644 --- a/lib/route/audit.js +++ b/lib/route/audit.js @@ -1,107 +1,114 @@ +'use strict' -"use strict"; - -var express = require('express'), -Bluebird = require('bluebird'), -validator = require('validator'), -_ = require('underscore'), -moment = require('moment'), -router = express.Router(), -Pager = require('./utils/pager')(); +const express = require('express') +const Bluebird = require('bluebird') +const validator = require('validator') +const _ = require('underscore') +const moment = require('moment') +const router = express.Router() +const Pager = require('./utils/pager')() // Make sure that current user is authorized to deal with settings -router.all(/.*/, require('../middleware/ensure_user_is_admin')); - -router.get(/email/, function(req, res){ - - var user_id = validator.toInt(req.query['user_id']), - start_date = validator.trim(req.query['start_date']), - end_date = validator.trim(req.query['end_date']), - page = validator.toInt(req.query['page']) || 1, - model = req.app.get('db_model'), - filter = { - company_id: req.user.companyId, - }; +router.all(/.*/, require('../middleware/ensure_user_is_admin')) + +router.get(/email/, (req, res) => { + const user_id = + typeof req.query.user_id !== 'undefined' && + validator.toInt(req.query.user_id) + let start_date = + typeof req.query.start_date !== 'undefined' && + validator.trim(req.query.start_date) + let end_date = + typeof req.query.end_date !== 'undefined' && + validator.trim(req.query.end_date) + const page = + (typeof req.query.page !== 'undefined' && + validator.toInt(req.query.page)) || + 1 + const model = req.app.get('db_model') + const filter = { + company_id: req.user.company_id + } - var items_per_page = Pager.items_per_page; + const items_per_page = Pager.items_per_page - if (start_date) start_date = req.user.company.normalise_date( start_date ); + if (start_date) start_date = req.user.company.normalise_date(start_date) // if there is a valid start date provided pass it to the filter - if ( validator.isDate(start_date) ) { - if (! filter.hasOwnProperty('created_at')) filter.created_at = {}; - filter.created_at['$gte'] = start_date; + if (start_date && validator.toDate(start_date)) { + if (!filter.hasOwnProperty('created_at')) filter.created_at = {} + filter.created_at.$gte = start_date } // ... same for end date - if (end_date) end_date = req.user.company.normalise_date( end_date ); + if (end_date) end_date = req.user.company.normalise_date(end_date) - if ( validator.isDate(end_date) ) { - if (! filter.hasOwnProperty('created_at')) filter.created_at = {}; - filter.created_at['$lte'] = end_date; + if (end_date && validator.toDate(end_date)) { + if (!filter.hasOwnProperty('created_at')) filter.created_at = {} + filter.created_at.$lte = end_date } - if ( validator.isInt(user_id) ) { - filter.user_id = user_id; + if (typeof user_id === 'number' || (user_id && validator.isInt(user_id))) { + filter.user_id = user_id } - var promise_emails = model.EmailAudit.findAndCountAll({ - where : filter, + const promise_emails = model.EmailAudit.findAndCountAll({ + where: filter, - limit : items_per_page, - offset : items_per_page * (page - 1), - order : [ - [ 'id', 'DESC'] - ], + limit: items_per_page, + offset: items_per_page * (page - 1), + order: [['id', 'DESC']], - include : [{ - model : model.User, - as : 'user', - }] - }); + include: [ + { + model: model.User, + as: 'user' + } + ] + }) - var promise_all_users = model.User.findAll({ - where : { - companyId : req.user.companyId, + const promise_all_users = model.User.findAll({ + where: { + company_id: req.user.company_id }, - order : [ - ['lastname'] - ], - }); + order: [['lastname']] + }) Bluebird.join( promise_emails, promise_all_users, - function(email_result, all_users){ - - var filter = { - user_id : user_id, - }; + (email_result, all_users) => { + const filter = { + user_id + } if (start_date) { - filter.start_date = moment.utc(start_date).format(req.user.company.get_default_date_format()); + filter.start_date = moment + .utc(start_date) + .format(req.user.company.get_default_date_format()) } if (end_date) { - filter.end_date = moment.utc(end_date).format(req.user.company.get_default_date_format()); + filter.end_date = moment + .utc(end_date) + .format(req.user.company.get_default_date_format()) } res.render('audit/emails', { - audit_emails : email_result.rows, - all_users : all_users, - filter : filter, - show_reset_button : _.some([ user_id, start_date, end_date ]), - pager : Pager.get_pager_object({ - filter : filter, - total_items_count : email_result.count, - current_page : page, + audit_emails: email_result.rows, + all_users, + filter, + show_reset_button: _.some([user_id, start_date, end_date]), + pager: Pager.get_pager_object({ + filter, + total_items_count: email_result.count, + current_page: page }), - }); - + title: 'Email Audit | TimeOff' + }) } - ); -}); - + ) +}) -module.exports = router; +module.exports = router diff --git a/lib/route/bankHolidays.js b/lib/route/bankHolidays.js index 103340641..d48c8d12b 100644 --- a/lib/route/bankHolidays.js +++ b/lib/route/bankHolidays.js @@ -1,251 +1,271 @@ +'use strict' -"use strict"; - -const express = require('express'), - moment = require('moment'), - router = express.Router(), - validator = require('validator'), - Promise = require('bluebird'), - config = require('../config'), - CalendarMonth = require('../model/calendar_month'); +const express = require('express') +const moment = require('moment') +const router = express.Router() +const validator = require('validator') +const Promise = require('bluebird') +const config = require('../config') +const CalendarMonth = require('../model/calendar_month') +const Exception = require('../error') // Make sure that current user is authorized to deal with settings -router.all(/.*/, require('../middleware/ensure_user_is_admin')); +router.all(/.*/, require('../middleware/ensure_user_is_admin')) -const getCurrentYear = ({req}) => { - const rawYear = req.query['year'] || req.body['year']; - return ( - validator.isNumeric(rawYear) +const getCurrentYear = ({ req }) => { + const rawYear = req.query.year || req.body.year || '' + return (validator.isNumeric(rawYear) ? moment.utc(rawYear, 'YYYY') : req.user.company.get_today() - ).year(); -}; + ).year() +} router.get('/bankholidays/', (req, res) => { - - res.locals.custom_java_script.push( - '/js/bank_holidays.js' - ); - - const currentYear = getCurrentYear({req}); - - req.user.getCompany({ - scope : ['with_bank_holidays', 'order_by_bank_holidays'], - }) - .then((company) => { - const today = moment.utc(); - const bankHolidays = company.bank_holidays.filter(bh => moment.utc(bh.date).year() === currentYear); - const calendar = [...Array(12).keys()] - .map(i => i+1) - .map(m => new CalendarMonth( - `${currentYear}-${m}`, - { - today, - schedule: {is_it_working_day: ({day}) => moment.utc(day).isoWeekday() < 6}, - bank_holidays: bankHolidays, - } - ) + res.locals.custom_java_script.push('/js/bank_holidays.js') + + const currentYear = getCurrentYear({ req }) + const model = req.app.get('db_model') + req.user + .getCompany({ + include: [{ model: model.BankHoliday, as: 'bank_holidays' }], + order: [[{ model: model.BankHoliday, as: 'bank_holidays' }, 'date']] + }) + .then(company => { + const today = moment.utc() + const bankHolidays = company.bank_holidays.filter( + bh => moment.utc(bh.date).year() === currentYear ) - .map(cm => cm.as_for_template()); - - res.render('bankHolidays', { - company, - calendar, - bankHolidays, - yearCurrent: currentYear, - yearPrev: currentYear - 1, - yearNext: currentYear + 1, - startDateOfYearCurrent: moment.utc(currentYear, 'YYYY'), - }); - }); -}); - -const promiseNewBankHoliday = ({model, req, companyId}) => { - - if (!validator.trim(req.body['name__new'])) { - return Promise.resolve(1); - } - const attributes = getAndValidateBankHoliday({ - req, - id: 'new', - itemName : 'New Bank Holiday', - }); + const calendar = [...Array(12).keys()] + .map(i => i + 1) + .map( + m => + new CalendarMonth(`${currentYear}-${m}`, { + today, + schedule: { + is_it_working_day: ({ day }) => moment.utc(day).isoWeekday() < 6 + }, + bank_holidays: bankHolidays + }) + ) + .map(cm => cm.as_for_template()) + + res.render('bankHolidays', { + company, + calendar, + bankHolidays, + yearCurrent: currentYear, + yearPrev: currentYear - 1, + yearNext: currentYear + 1, + startDateOfYearCurrent: moment.utc(currentYear, 'YYYY') + }) + }) +}) - if ( req.session.flash_has_errors() ) { - return Promise.resolve(1); - } +router.post('/bankholidays/', (req, res) => { + const model = req.app.get('db_model') + const currentYear = getCurrentYear({ req }) - return model.BankHoliday.create({...attributes, companyId}); -}; - -router.post('/bankholidays/', function(req,res){ - const model= req.app.get('db_model'); - const currentYear = getCurrentYear({req}); - - req.user.getCompany({ - scope : ['with_bank_holidays'], - }) - .then((company) => { - return Promise.all([ - promiseNewBankHoliday({model, req, companyId: company.id}), - ...company.bank_holidays.map(bankHoliday => { - const attributes = getAndValidateBankHoliday({ - req, - id: bankHoliday.id, - itemName: bankHoliday.name, - }); + req.user + .getCompany({ + scope: ['with_bank_holidays'] + }) + .then(company => { + /** + * Validate input first + */ + const allBankHolidays = company.bank_holidays + .filter( + bankHoliday => req.body[`date__${bankHoliday.id}`] !== undefined + ) + .map(bankHoliday => { + bankHoliday.name = + req.body[`name__${bankHoliday.id}`] || bankHoliday.name + bankHoliday.date = + req.body[`date__${bankHoliday.id}`] || bankHoliday.date + return bankHoliday + }) + + // Add the new bank holiday to the list if exists. + if (req.body.name__new && validator.trim(req.body.name__new)) { + allBankHolidays.push({ + name: req.body.name__new, + date: req.body.date__new, + company_id: company.id + }) + } + // Validation + const invalidBankHolidays = allBankHolidays.filter(bankHoliday => { + const date = company.normalise_date(bankHoliday.date) + return !validator.isDate(date) + }) + + // Handle errors + if (invalidBankHolidays.length > 0) { + invalidBankHolidays.forEach(bankHoliday => + req.session.flash_error( + `New day for ${bankHoliday.name} should be date` + ) + ) // If there were any validation errors: do not update bank holiday // (it affects all bank holidays, that is if one failed // validation - all bank holidays are not to be updated) - if ( req.session.flash_has_errors() ) { - return Promise.resolve(1); - } - - return bankHoliday.updateAttributes(attributes); - }), - ]); - }) - .then(() => { - if (!req.session.flash_has_errors()) { - req.session.flash_message('Changes to bank holidays were saved'); - } - }) - .catch((error) => { - console.error(`An error occurred when trying to edit Bank holidays by user [${req.user.id}]: ${error}`); - - req.session.flash_error('Failed to update bank holidays, please contact customer service'); - }) - .then(() => { - return res.redirect_with_session(`/settings/bankholidays/?year=${currentYear}`); - }); -}); + return Promise.reject(new Error('bad_request')) + } + + // All good, save all + return Promise.all([ + ...allBankHolidays.map(bankHoliday => { + // Create + if (!bankHoliday.id) { + return model.BankHoliday.create(bankHoliday) + } + + // Update + return bankHoliday.update({ + name: bankHoliday.name, + date: bankHoliday.date + }) + }) + ]) + }) + .then(() => { + req.session.flash_message('Changes to bank holidays were saved!') + res.redirect_with_session(`/settings/bankholidays/?year=${currentYear}`) + }) + .catch(error => { + console.error( + `An error occurred when trying to edit Bank holidays by user [${ + req.user.id + }]: ${error}` + ) + console.log(error) + + req.session.flash_error( + 'Failed to update bank holidays, please contact customer service' + ) + res.redirect_with_session(`/settings/bankholidays/?year=${currentYear}`) + }) +}) router.post('/bankholidays/import/', (req, res) => { - const model = req.app.get('db_model'), - config_countries = config.get('countries'), - currentYear = getCurrentYear({req}); - - Promise - .try(() => req.user.getCompany({ - scope : ['with_bank_holidays'], - })) - .then(company => { + const model = req.app.get('db_model') + const config_countries = config.get('countries') + const currentYear = getCurrentYear({ req }) + Promise.try(() => + req.user.getCompany({ + scope: ['with_bank_holidays'] + }) + ) + .then(company => { // re-organize existing bank holiday in look up map manner - let existing_bank_holidays_map = {}; + const existing_bank_holidays_map = {} company.bank_holidays.forEach(bh => { - existing_bank_holidays_map[ company.normalise_date(bh.date) ] = 1; - }); + existing_bank_holidays_map[company.normalise_date(bh.date)] = 1 + }) // Fetch all default bank holidays known for current country let bank_holidays_to_import = - config_countries[ (company.country || 'GB') ].bank_holidays; + config_countries[company.country || 'GB'].bank_holidays // prepare list of bank holidays that needs to be added bank_holidays_to_import = bank_holidays_to_import // Ignore those which dates already used - .filter(bh => ! existing_bank_holidays_map.hasOwnProperty( company.normalise_date( bh.date ) )) + .filter( + bh => + !existing_bank_holidays_map.hasOwnProperty( + company.normalise_date(bh.date) + ) + ) // Ignore those from another years .filter(bh => moment.utc(bh.date).year() === currentYear) // and transform bank holidays into import friendly structure - .map( - bh => ({ name : bh.name, date : bh.date, companyId : company.id }) - ); + .map(bh => ({ name: bh.name, date: bh.date, company_id: company.id })) - return model.BankHoliday.bulkCreate( bank_holidays_to_import ); + return model.BankHoliday.bulkCreate(bank_holidays_to_import) }) - .then( created_bank_holidays => { - - if ( created_bank_holidays.length && created_bank_holidays.length > 0) { - req.session.flash_message( - 'New bank holidays were added: ' - + created_bank_holidays.map(bh => bh.name).join(', ') - ); - } else { - - req.session.flash_message('No more new bank holidays exist'); + .then(created_bank_holidays => { + if (!created_bank_holidays.length || created_bank_holidays.length <= 0) { + req.session.flash_message('No more new bank holidays exist') + return } + + req.session.flash_message( + 'New bank holidays were added: ' + + created_bank_holidays.map(bh => bh.name).join(', ') + ) }) + .then(() => + res.redirect_with_session(`/settings/bankholidays/?year=${currentYear}`) + ) .catch(error => { - console.log( - 'An error occurred when trying to import default bank holidays by user '+req.user.id - ); - console.dir(error); + 'An error occurred when trying to import default bank holidays by user ' + + req.user.id + ) + console.dir(error) - if ( error && error.tom_error) { - req.session.flash_error( Exception.extract_user_error_message(error) ); + if (error && error.tom_error) { + req.session.flash_error(Exception.extract_user_error_message(error)) } - req.session.flash_error( - 'Failed to import bank holidays' - ); + req.session.flash_error('Failed to import bank holidays') }) - .then(() => { - return res.redirect_with_session(`/settings/bankholidays/?year=${currentYear}`); - }); -}); - -router.post('/bankholidays/delete/:bankHolidayId/', function(req, res){ - const currentYear = getCurrentYear({req}); - const bankHolidayId = req.params['bankHolidayId']; - - if (!validator.isInt(bankHolidayId)) { - console.error(`User ${req.user.id} submitted non-INT bank holiday ID ${bankHolidayId}`); - req.session.flash_error('Cannot remove bank holiday: wrong parameters'); - return res.redirect_with_session(`/settings/bankholidays/?year=${currentYear}`); +}) + +router.post('/bankholidays/delete/:bankHolidayId/', (req, res) => { + const currentYear = getCurrentYear({ req }) + const bankHolidayId = req.params.bankHolidayId + + if ( + typeof bankHolidayId !== 'number' && + (!bankHolidayId || !validator.isInt(bankHolidayId)) + ) { + console.error( + `User ${req.user.id} submitted non-INT bank holiday ID ${bankHolidayId}` + ) + req.session.flash_error('Cannot remove bank holiday: wrong parameters') + return res.redirect_with_session( + `/settings/bankholidays/?year=${currentYear}` + ) } - req.user.getCompany({ - scope : ['with_bank_holidays'], - }) - .then(company => { - const bankHolidayToRemove = company.bank_holidays.find(bh => String(bh.id) === String(bankHolidayId)); - - // Check if user specify valid department number - if (! bankHolidayToRemove) { - console.error( - `User ${req.user.id} tried to remove non-existing bank holiday number ${bankHolidayId}` - ); - req.session.flash_error('Cannot remove bank holiday: wrong parameters'); - - return res.redirect_with_session(`/settings/bankholidays/?year=${currentYear}`); - } - - return bankHolidayToRemove.destroy(); - }) - .then(() => { - req.session.flash_message('Bank holiday was successfully removed'); - return res.redirect_with_session(`/settings/bankholidays/?year=${currentYear}`); - }); -}); - -const getAndValidateBankHoliday = ({req, id, itemName}) => { - - // Get user parameters - let name = validator.trim(req.body[`name__${id}`]), - date = validator.trim(req.body[`date__${id}`]); - - // Nothing to validate, abort - if (!name && !date) { - return {}; - } - - // Validate provided parameters - // - // Note, we allow users to put whatever they want into the name. - // The XSS defence is in the templates + req.user + .getCompany({ + scope: ['with_bank_holidays'] + }) + .then(company => { + const bankHolidayToRemove = company.bank_holidays.find( + bh => String(bh.id) === String(bankHolidayId) + ) - date = req.user.company.normalise_date( date ); + // Check if user specify valid department number + if (!bankHolidayToRemove) { + return Promise.reject(new Error('Unable to remove the bank holiday.')) + } - if (!validator.isDate(date) ) { - req.session.flash_error(`New day for ${itemName} should be date`); - } + return bankHolidayToRemove.destroy() + }) + .then(() => { + req.session.flash_message('Bank holiday was successfully removed') + return res.redirect_with_session( + `/settings/bankholidays/?year=${currentYear}` + ) + }) + .catch(error => { + console.error( + `User ${ + req.user.id + } tried to remove non-existing bank holiday number ${bankHolidayId}` + ) + console.log('Error: ', error) + req.session.flash_error('Cannot remove bank holiday: wrong parameters') - return { name, date }; -} + res.redirect_with_session(`/settings/bankholidays/?year=${currentYear}`) + }) +}) -module.exports = router; +module.exports = router diff --git a/lib/route/calendar.js b/lib/route/calendar.js index 3b0845548..97e603718 100644 --- a/lib/route/calendar.js +++ b/lib/route/calendar.js @@ -1,164 +1,217 @@ +'use strict' + +const express = require('express') +const router = express.Router() +const Promise = require('bluebird') +const moment = require('moment') +const _ = require('underscore') +const validator = require('validator') +const get_and_validate_leave_params = require('./validator/leave_request') +const TeamView = require('../model/team_view') +const EmailTransport = require('../email') +const SlackTransport = require('../slack') + +const { + createNewLeave, + getLeaveForUserView, + doesUserHasExtendedViewOfLeave +} = require('../model/leave') +const { leaveIntoObject } = require('../model/Report') +const { getCommentsForLeave } = require('../model/comment') +const { sorter } = require('../util') + +router.post('/bookleave/', (req, res) => { + Promise.join( + req.user.promise_users_I_can_manage(), + req.user.get_company_with_all_leave_types(), + Promise.try(() => get_and_validate_leave_params({ req, params: req.body })), + (users, company, valid_attributes) => { + // Make sure that indexes submitted map to existing objects + const employee = users[valid_attributes.user] || req.user + const [leave_type] = company.leave_types.filter( + lt => `${lt.id}` === `${valid_attributes.leave_type}` + ) + + if (!employee) { + req.session.flash_error('Incorrect employee') + throw new Error('Got validation errors') + } -"use strict"; - -var express = require('express'), - router = express.Router(), - Promise = require('bluebird'), - moment = require('moment'), - _ = require('underscore'), - validator = require('validator'), - get_and_validate_leave_params = require('./validator/leave_request'), - TeamView = require('../model/team_view'), - EmailTransport = require('../email'); - -const {createNewLeave, getLeaveForUserView, doesUserHasExtendedViewOfLeave} = require('../model/leave'); -const { leaveIntoObject } = require('../model/Report'); -const { getCommentsForLeave } = require('../model/comment'); -const { sorter } = require('../util'); - -router.post('/bookleave/', function(req, res){ - - Promise.join ( - req.user.promise_users_I_can_manage(), - req.user.get_company_with_all_leave_types(), - Promise.try( () => get_and_validate_leave_params({req})), - (users, company, valid_attributes) => { - - // Make sure that indexes submitted map to existing objects - const employee = users[valid_attributes.user] || req.user; - const [leave_type] = company.leave_types - .filter(lt => `${lt.id}` === `${valid_attributes.leave_type}`); - - if (!employee) { - req.session.flash_error('Incorrect employee'); - throw new Error( 'Got validation errors' ); - } - - if (!leave_type) { - req.session.flash_error('Incorrect leave type'); - throw new Error( 'Got validation errors' ); - } - - if (company.is_mode_readonly_holidays() ){ - req.session.flash_error( - "Company account is locked and new Timeoff " - + "requests could not be added. Please contact administration." - ); - throw new Error('Company is in "Read-only holidays" mode'); - } - - return createNewLeave({ - for_employee : employee, - of_type : leave_type, - with_parameters : valid_attributes, - }); + if (!leave_type) { + req.session.flash_error('Incorrect leave type') + throw new Error('Got validation errors') } - ) + + if (company.is_mode_readonly_holidays()) { + req.session.flash_error( + 'Company account is locked and new Timeoff ' + + 'requests could not be added. Please contact administration.' + ) + throw new Error('Company is in "Read-only holidays" mode') + } + + return createNewLeave({ + for_employee: employee, + of_type: leave_type, + with_parameters: valid_attributes + }) + } + ) .then(leave => leave.reloadWithAssociates()) - .then(leave => (new EmailTransport()).promise_leave_request_emails({leave})) - .then(function(){ - - req.session.flash_message('New leave request was added'); - return res.redirect_with_session( - req.body['redirect_back_to'] - ? req.body['redirect_back_to'] - : '../' - ); + /* + .then(function(leave){ + return leave.reload({ + include : [ + {model : model.User, as : 'user'}, + {model : model.User, as : 'approver'}, + {model : model.LeaveType, as : 'leave_type'}, + ], + }); + }) + */ + .then(leave => { + const Slack = new SlackTransport() + + Slack.promise_leave_request_slacks({ + leave + }) + // Fail silently for the user and track the error for the administrator. + .catch(error => { + console.error( + 'Failed to send leave slack message to: ' + error, + error.stack + ) + }) + + const Email = new EmailTransport() + + Email.promise_leave_request_emails({ + leave + }) // Fail silently for the user and track the error for the administrator. + .catch(error => { + console.error( + 'Failed to send leave send_mail to: ' + error, + error, + error.stack + ) + }) + + return Promise.resolve(leave) + }) + .then(() => { + req.session.flash_message('New leave request was added') + return res.redirect_with_session( + req.body.redirect_back_to ? req.body.redirect_back_to : '../' + ) + }) + + .catch(error => { + console.error( + 'An error occured when user ' + + req.user.id + + ' try to create a leave request: ', + error, + error.stack + ) + req.session.flash_error('Failed to create a leave request') + if (error.user_message) { + req.session.flash_error(error.user_message) + } + return res.redirect_with_session( + req.body.redirect_back_to ? req.body.redirect_back_to : '../' + ) }) +}) + +router.get('/', (req, res) => { + const current_year = + req.query.year && validator.isNumeric(req.query.year) + ? moment.utc(req.query.year, 'YYYY') + : req.user.company.get_today() - .catch(function(error){ - console.error( - 'An error occured when user '+req.user.id+ - ' try to create a leave request: '+error+ - ' at: ' + error.stack - ); - req.session.flash_error('Failed to create a leave request'); - if (error.hasOwnProperty('user_message')) { - req.session.flash_error(error.user_message); - } - return res.redirect_with_session( - req.body['redirect_back_to'] - ? req.body['redirect_back_to'] - : '../' - ); - }); - -}); - -router.get('/', function(req, res) { - - var current_year = validator.isNumeric(req.query['year']) - ? moment.utc(req.query['year'], 'YYYY') - : req.user.company.get_today(); - - var show_full_year = validator.toBoolean(req.query['show_full_year']); + const show_full_year = + (req.query.show_full_year && + validator.toBoolean(req.query.show_full_year)) || + false Promise.join( req.user.promise_calendar({ - year : current_year.clone(), - show_full_year : show_full_year, + year: current_year.clone(), + show_full_year }), req.user.get_company_with_all_leave_types(), - req.user.reload_with_leave_details({ year : current_year }), + req.user.reload_with_leave_details({ year: current_year }), req.user.promise_supervisors(), - req.user.promise_allowance({ year : current_year }), - function(calendar, company, user, supervisors, user_allowance){ - let - full_leave_type_statistics = user.get_leave_statistics_by_types(); + req.user.promise_allowance({ year: current_year }), + (calendar, company, user, supervisors, user_allowance) => { + const full_leave_type_statistics = user.get_leave_statistics_by_types() res.render('calendar', { - calendar : _.map(calendar, function(c){return c.as_for_template()}), - company : company, - title : 'Calendar', - current_user : user, - supervisors : supervisors, - previous_year : moment.utc(current_year).add(-1,'year').format('YYYY'), - current_year : current_year.format('YYYY'), - next_year : moment.utc(current_year).add(1,'year').format('YYYY'), - show_full_year : show_full_year, - leave_type_statistics : _.filter(full_leave_type_statistics, st => st.days_taken > 0), + calendar: _.map(calendar, c => c.as_for_template()), + company, + title: 'Calendar | TimeOff', + current_user: user, + supervisors, + previous_year: moment + .utc(current_year) + .add(-1, 'year') + .format('YYYY'), + current_year: current_year.format('YYYY'), + next_year: moment + .utc(current_year) + .add(1, 'year') + .format('YYYY'), + show_full_year, + leave_type_statistics: _.filter( + full_leave_type_statistics, + st => st.days_taken > 0 + ), // User allowance object is simple object with attributes only - user_allowance : user_allowance, - }); + user_allowance + }) } - ); - -}); + ) +}) router.get('/teamview/', async (req, res) => { - const user = req.user; + const user = req.user if (user.company.is_team_view_hidden && !user.admin) { - return res.redirect_with_session('/'); + return res.redirect_with_session('/') } - const base_date = validator.isDate(req.query['date']) - ? moment.utc(req.query['date']) - : user.company.get_today(); + const base_date = + req.query.date && validator.toDate(req.query.date) + ? moment.utc(req.query.date) + : req.user.company.get_today() - const grouped_mode = getGroupedModeParameter(req); - const currentDepartmentId = getDepartmentIdForTeamView(req); - const team_view = new TeamView({ user, base_date }); + const grouped_mode = getGroupedModeParameter(req) + const current_deparment_id = getDepartmentIdForTeamView(req) + const team_view = new TeamView({ user, base_date }) try { const [team_view_details, company] = await Promise.all([ team_view.promise_team_view_details({ - department_id: currentDepartmentId, + department_id: current_deparment_id }), - user.get_company_with_all_leave_types(), - ]); + user.get_company_with_all_leave_types() + ]) // Enrich "team view details" with statistics as how many deducted days each employee spent current month const team_view_details_with_stat = await team_view.inject_statistics({ team_view_details, - leave_types: company.leave_types, - }); + leave_types: company.leave_types + }) - const {users_and_leaves, related_departments, current_department} = await team_view.restrainStatisticsForUser({ + const { + users_and_leaves, + related_departments, + current_department + } = await team_view.restrainStatisticsForUser({ user, - team_view_details: team_view_details_with_stat, - }); + team_view_details: team_view_details_with_stat + }) const renderingContext = { company, @@ -167,183 +220,202 @@ router.get('/teamview/', async (req, res) => { current_department, base_date, prev_date: moment.utc(base_date).add(-1, 'month'), - next_date: moment.utc(base_date).add(1, 'month'), - }; + next_date: moment.utc(base_date).add(1, 'month') + } if (grouped_mode) { - renderingContext.grouped_mode = true; - renderingContext.users_and_leaves_by_departments = groupUsersOnTeamViewByDepartments(users_and_leaves); + renderingContext.grouped_mode = true + renderingContext.users_and_leaves_by_departments = groupUsersOnTeamViewByDepartments( + users_and_leaves + ) } - res.render('team_view', renderingContext); - } - catch (error) { + res.render('team_view', renderingContext) + } catch (error) { console.error( - `An error occurred when user ${user.id} tried to access TeamView page: ${error}, at ${error.stack}` - ); - req.session.flash_error('Failed to access TeamView page. Please contact administrator.'); + `An error occurred when user ${ + user.id + } tried to access TeamView page: ${error}, at ${error.stack}` + ) + req.session.flash_error( + 'Failed to access TeamView page. Please contact administrator.' + ) - if (error.hasOwnProperty('user_message')) { - req.session.flash_error(error.user_message); + if (error.user_message) { + req.session.flash_error(error.user_message) } - return res.redirect_with_session('/'); - }; -}); + return res.redirect_with_session('/') + } +}) -const getGroupedModeParameter = (req) => { +const getGroupedModeParameter = req => { /** * grouped_mode parameter is saved in the current session so user's * transition between different pages does not reset the value */ - let groupedMode = !! req.query['grouped_mode']; + let groupedMode = !!req.query.grouped_mode - if (req.query['save_grouped_mode']) { + if (req.query.save_grouped_mode) { req.session.teamViewGroupedMode = groupedMode - } + } // for cases when no grouped_mode parameter was supplied: used onf from session - if (req.query['grouped_mode'] === undefined) { + if (req.query.grouped_mode === undefined) { groupedMode = req.session.teamViewGroupedMode } return groupedMode -}; +} -const getDepartmentIdForTeamView = (req) => { +const getDepartmentIdForTeamView = req => { /** * department parameter is saved in the current session so user's * transition between different pages does not reset the value */ - let departmentId = validator.isNumeric(req.query['department']) - ? req.query['department'] - : null; - if (req.query['save_current_department']) { + let departmentId = + req.query.department && validator.isNumeric(req.query.department) + ? req.query.department + : null + + if (req.query.save_current_department) { req.session.teamViewDepartmentId = departmentId - } + } // for cases when no grouped_mode parameter was supplied: used onf from session - if (req.query['department'] === undefined) { + if (req.query.department === undefined) { departmentId = req.session.teamViewDepartmentId } return departmentId } -const groupUsersOnTeamViewByDepartments = (usersAndLeaves) => { +const groupUsersOnTeamViewByDepartments = usersAndLeaves => { const departmentsDict = usersAndLeaves.reduce( - (acc, item) => ({ ...acc, [item.user.department.id]: { departmentName: item.user.department.name, users_and_leaves: [] } }), + (acc, item) => ({ + ...acc, + [item.user.department.id]: { + departmentName: item.user.department.name, + users_and_leaves: [] + } + }), {} - ); + ) usersAndLeaves.forEach(item => { - departmentsDict[item.user.department.id].users_and_leaves.push(item); - }); + departmentsDict[item.user.department.id].users_and_leaves.push(item) + }) - return Object.values(departmentsDict).sort((a, b) => sorter(a.departmentName, b.departmentName)); -}; - -router.get('/feeds/', function(req, res){ - req.user - .getFeeds() - .then(function(feeds){ - - return Promise.join( - promise_feed_of_type({user : req.user, feeds: feeds, type : 'calendar'}), - promise_feed_of_type({user : req.user, feeds: feeds, type : 'teamview'}), - function(calendar_feed, team_view_feed){ - res.render('feeds_list', { - title : 'My feeds', - calendar_feed : calendar_feed, - team_view_feed: team_view_feed, - current_host : req.get('host'), - }); - }); + return Object.values(departmentsDict).sort((a, b) => + sorter(a.departmentName, b.departmentName) + ) +} - }); -}); +router.get('/feeds/', (req, res) => { + req.user.getFeeds().then(feeds => + Promise.join( + promise_feed_of_type({ user: req.user, feeds, type: 'calendar' }), + promise_feed_of_type({ user: req.user, feeds, type: 'teamview' }), + (calendar_feed, team_view_feed) => { + res.render('feeds_list', { + title: 'My feeds | TimeOff', + calendar_feed, + team_view_feed, + current_host: req.get('host') + }) + } + ) + ) +}) -router.post('/feeds/regenerate/', function(req, res){ - var model = req.app.get('db_model'); +router.post('/feeds/regenerate/', (req, res) => { + const model = req.app.get('db_model') req.user .getFeeds() - .then(function(feeds){ - var the_feed = _.findWhere(feeds, { feed_token : req.body['token'] }); + .then(feeds => { + const the_feed = _.findWhere(feeds, { feed_token: req.body.token }) if (the_feed) { - return model.UserFeed.promise_new_feed({ - user : req.user, - type : the_feed.type, - }); + user: req.user, + type: the_feed.type + }) } - return Promise.resolve(); + return Promise.resolve() + }) + .then(() => { + req.session.flash_message('Feed was regenerated') + return res.redirect_with_session('/calendar/feeds/') }) - .then(function(){ - req.session.flash_message('Feed was regenerated'); - return res.redirect_with_session('/calendar/feeds/'); - }); -}); +}) // Fetch or create new feed feed provided types function promise_feed_of_type(args) { - var type = args.type, - user = args.user, - feeds= args.feeds, - feed = _.findWhere(feeds, { type : type }), - feed_promise; + const type = args.type + const user = args.user + const feeds = args.feeds + const feed = _.findWhere(feeds, { type }) + let feed_promise - if (! feed) { + if (!feed) { feed_promise = user.sequelize.models.UserFeed.promise_new_feed({ - user : user, - type : type, - }); + user, + type + }) } else { - feed_promise = Promise.resolve( feed ); + feed_promise = Promise.resolve(feed) } - return feed_promise; + return feed_promise } router.get('/leave-summary/:leaveId/', async (req, res) => { - const actingUser = req.user; - const leaveId = validator.trim(req.params['leaveId']); - const dbModel = req.app.get('db_model'); + const actingUser = req.user + const leaveId = validator.trim(req.params.leaveId) + const dbModel = req.app.get('db_model') try { - const leave = await getLeaveForUserView({actingUser, leaveId, dbModel}); - const extendedView = await doesUserHasExtendedViewOfLeave({user: actingUser, leave}); + const leave = await getLeaveForUserView({ actingUser, leaveId, dbModel }) + const extendedView = await doesUserHasExtendedViewOfLeave({ + user: actingUser, + leave + }) if (extendedView) { - const user = await leave.getUser(); - await user.promise_schedule_I_obey(); - const [extendedLeave] = await user.promise_my_leaves({ignore_year: true, filter: {id: leave.id}}); - const leaveDetails = leaveIntoObject(extendedLeave); - const comments = await getCommentsForLeave({leave}); - - leaveDetails.commentsString = comments.map(({comment}) => comment).join('
'); + const user = await leave.getUser() + await user.promise_schedule_I_obey() + const [extendedLeave] = await user.promise_my_leaves({ + ignore_year: true, + filter: { id: leave.id } + }) + const leaveDetails = leaveIntoObject(extendedLeave) + const comments = await getCommentsForLeave({ leave }) + + leaveDetails.commentsString = comments + .map(({ comment }) => comment) + .join('
') return res.render('leave/popup_leave_details', { leave: leaveDetails, - layout: false, - }); + layout: false + }) } else { // return res.send('Short'); - const leaveDetails = leaveIntoObject(leave); + const leaveDetails = leaveIntoObject(leave) return res.render('leave/popup_leave_details', { leave: leaveDetails, layout: false, - limitedView: true, - }); + limitedView: true + }) } } catch (error) { - console.log(`Failed to obtain Leave [${leaveId}] summary: ${error} at ${error.stack}`); - return res.send('Failed to get leave details...'); + console.log( + `Failed to obtain Leave [${leaveId}] summary: ${error} at ${error.stack}` + ) + return res.send('Failed to get leave details...') } +}) - return res.send('Failed to get leave details (should never happen)...'); -}); - -module.exports = router; +module.exports = router diff --git a/lib/route/dashboard.js b/lib/route/dashboard.js index f13ebda02..19eb62e7b 100644 --- a/lib/route/dashboard.js +++ b/lib/route/dashboard.js @@ -2,40 +2,36 @@ * * */ -"use strict"; +'use strict' -var express = require('express'); -var router = express.Router(); +const express = require('express') +const router = express.Router() -router.get('/', function(req, res) { +router.get('/', (req, res) => { + const user = req.user - var user = req.user; + req.session.keep_old() - req.session.keep_old(); + // if no user available in session show main public + if (!user) { + return res.redirect_with_session('./login/') + } - // if no user available in session show main public - if (!user) { - return res.redirect_with_session('./login/'); - } - - return res.redirect_with_session('./calendar/'); -}); + return res.redirect_with_session('./calendar/') +}) // Make sure that all fallowing handlers Dashboard // require authenticated users -router.all(/.*/, function (req, res, next) { - - if ( !req.user ) { - return res.redirect_with_session(303, '/'); - } - - next(); -}); - -router.get('/foo/', function(_req, res) { +router.all(/.*/, (req, res, next) => { + if (!req.user) { + return res.redirect_with_session(303, '/') + } - res.render('dashboard', { title: 'FOO' }); -}); + next() +}) +router.get('/foo/', (_req, res) => { + res.render('dashboard', { title: 'FOO' }) +}) -module.exports = router; +module.exports = router diff --git a/lib/route/departments.js b/lib/route/departments.js index 3edde01b6..9e61dd004 100644 --- a/lib/route/departments.js +++ b/lib/route/departments.js @@ -1,489 +1,534 @@ +'use strict' -"use strict"; +const { sorter } = require('../util') -const { sorter } = require('../util'); - -const express = require('express'), - router = express.Router(), - validator = require('validator'), - Promise = require('bluebird'), - _ = require('underscore'); +const express = require('express') +const router = express.Router() +const validator = require('validator') +const Promise = require('bluebird') +const _ = require('underscore') // Make sure that current user is authorized to deal with settings -router.all(/.*/, require('../middleware/ensure_user_is_admin')); +router.all(/.*/, require('../middleware/ensure_user_is_admin')) function generate_all_department_allowances() { - - var allowance_options = [{ value : 0, caption : 'None'}], - allowance = 0.5; + const allowance_options = [{ value: 0, caption: 'None' }] + let allowance = 0.5 while (allowance <= 50) { - allowance_options.push({ value : allowance, caption : allowance }); - allowance += 0.5; + allowance_options.push({ value: allowance, caption: allowance }) + allowance += 0.5 } - return allowance_options; + return allowance_options } function get_and_validate_department(args) { - var req = args.req, - index = args.suffix, - company = args.company, - // If no_suffix is set then parameter names are considered without "indexes" - no_suffix = args.no_suffix, - department_name = args.department_name; + const req = args.req + const session = req.session + const index = args.suffix + const company = args.company + // If no_suffix is set then parameter names are considered without "indexes" + const no_suffix = args.no_suffix + const department_name = args.department_name + + function getParam(name) { + return req.body[no_suffix ? name : name + '__' + index] + } // Get user parameters - let - name = validator.trim(req.body[no_suffix ? 'name' : 'name__'+index]), - allowance = validator.trim(req.body[no_suffix ? 'allowance' : 'allowance__'+index]), - boss_id = validator.trim(req.body[no_suffix ? 'boss_id' : 'boss_id__'+index]), - include_public_holidays = validator.toBoolean( - req.body[no_suffix ? 'include_public_holidays' : 'include_public_holidays__'+index] - ), - is_accrued_allowance = validator.toBoolean( - req.body[no_suffix ? 'is_accrued_allowance' : 'is_accrued_allowance__'+index] - ); + const name = getParam('name') && validator.trim(getParam('name')) + const allowance = + getParam('allowance') && validator.trim(getParam('allowance')) + const manager_id = + getParam('manager_id') && validator.trim(getParam('manager_id')) + + const include_public_holidays = validator.toBoolean( + getParam('include_public_holidays') === 'on' + ) + const is_accrued_allowance = validator.toBoolean( + getParam('is_accrued_allowance') === 'on' + ) // Validate provided parameters // // New allowance should be from range of (0;50] if (!validator.isFloat(allowance)) { - req.session.flash_error( - 'New allowance for '+department_name+' should be numeric' - ); - } else if (!((0 <= allowance) && (allowance <= 50))) { - req.session.flash_error( - 'New allowance for '+department_name+' should be between 0.5 and 50 days' - ); + session.flash_error( + 'New allowance for ' + department_name + ' should be numeric' + ) + } else if (!(allowance >= 0 && allowance <= 50)) { + session.flash_error( + 'New allowance for ' + + department_name + + ' should be between 0.5 and 50 days' + ) } // New manager ID should be numeric and from within // current company - if (!validator.isNumeric( boss_id ) ) { - req.session.flash_error( - 'New boss reference for '+department_name+' should be numeric' - ); - } else if ( ! _.contains( - _.map( company.users, function(user){ return String(user.id) }), - String(boss_id) - )) { + if ( + typeof manager_id !== 'number' && + (!manager_id || !validator.isNumeric(manager_id)) + ) { + session.flash_error( + 'New manager reference for ' + department_name + ' should be numeric' + ) + } else if ( + !_.contains( + _.map(company.users, user => String(user.id)), + String(manager_id) + ) + ) { req.session.flash_error( - 'New boss for '+department_name+' is unknown' - ); + 'New manager for ' + department_name + ' is unknown' + ) } return { - allowance : allowance, - bossId : boss_id, - include_public_holidays : include_public_holidays, - is_accrued_allowance : is_accrued_allowance, - name : name, - }; + allowance, + manager_id, + include_public_holidays, + is_accrued_allowance, + name + } } -router.get('/departments/', function(req, res){ - +router.get('/departments/', (req, res) => { // Add JS that is specific only to current page - res.locals.custom_java_script.push('/js/departments.js'); + res.locals.custom_java_script.push('/js/departments.js') - var company_for_template, - model = req.app.get('db_model'); + let company_for_template + const model = req.app.get('db_model') - req.user.getCompany({ - scope : ['with_active_users', 'order_by_active_users'], - }) - .then(function(company){ - company_for_template = company; - return company.getDepartments({ - scope : ['with_simple_users', 'with_boss'], - }); - }) - .then(function(departments){ - res.render('departments_overview', { - title : 'Departments settings', - departments : departments.sort((a, b) => sorter(a.name, b.name)), - allowance_options : generate_all_department_allowances(), - company : company_for_template, - }); - }); -}); - -router.post('/departments/', function(req, res){ - const - model = req.app.get('db_model'); - - req.user.getCompany({ - scope : ['with_active_users'], - }) - .then(company => { + req.user + .getCompany({ + scope: ['with_active_users', 'order_by_active_users'] + }) + .then(company => { + company_for_template = company + return company.getDepartments({ + scope: ['with_simple_users', 'with_manager'], + order: [[model.Department.default_order_field()]] + }) + }) + .then(departments => { + res.render('departments_overview', { + title: 'Settings - Departments | TimeOff', + departments: departments.sort((a, b) => sorter(a.name, b.name)), + allowance_options: generate_all_department_allowances(), + company: company_for_template + }) + }) +}) - let attributes = get_and_validate_department({ - req : req, - suffix : 'new', - company : company, - department_name : 'New department' - }); +router.post('/departments/', (req, res) => { + const model = req.app.get('db_model') - if ( req.session.flash_has_errors() ) { - return Promise.resolve(1); - } + req.user + .getCompany({ + scope: ['with_active_users'] + }) + .then(company => { + const attributes = get_and_validate_department({ + req, + params: req.body, + session: req.session, + suffix: 'new', + company, + department_name: 'New department' + }) - attributes.companyId = company.id; + if (req.session.flash_has_errors()) { + return Promise.resolve(1) + } - return model.Department.create(attributes); - }) + attributes.company_id = company.id - .then(() => { - if ( ! req.session.flash_has_errors() ) { - req.session.flash_message('Changes to departments were saved'); - } + return model.Department.create(attributes) + }) - return res.redirect_with_session('/settings/departments/'); - }) + .then(() => { + if (!req.session.flash_has_errors()) { + req.session.flash_message('Changes to departments were saved') + } - .catch(error => { - console.error( - 'An error occurred when trying to add department by user '+req.user.id - + ' : ' + error - ); + return res.redirect_with_session('/settings/departments/') + }) - req.session.flash_error( - 'Failed to add new department, please contact customer service' - ); + .catch(error => { + console.error( + 'An error occurred when trying to add department by user ' + + req.user.id + + ' : ', + error, + error.stack + ) - return res.redirect_with_session('/settings/departments/'); - }); -}); + req.session.flash_error( + 'Failed to add new department, please contact customer service' + ) -router.post('/departments/delete/:department_id/', function(req, res){ + return res.redirect_with_session('/settings/departments/') + }) +}) - var department_id = req.params['department_id'], - department_to_remove; +router.post('/departments/delete/:department_id/', (req, res) => { + const department_id = req.body.department_id + let department_to_remove - if (!validator.isInt(department_id)) { + if ( + typeof department_id !== 'number' && + (!department_id || !validator.isInt(department_id)) + ) { console.error( - 'User '+req.user.id+' submited non-int department ID '+department_id - ); + 'User ' + req.user.id + ' submited non-int department ID ' + department_id + ) - req.session.flash_error('Cannot remove department: wronge parameters'); + req.session.flash_error('Cannot remove department: wronge parameters') - return res.redirect_with_session('/settings/departments/'); + return res.redirect_with_session('/settings/departments/') } - req.user.getCompany() + req.user + .getCompany() - .then(function(company){ - return company.getDepartments({ - scope : ['with_simple_users'], - where : { - id : department_id, + .then(company => + company.getDepartments({ + scope: ['with_simple_users'], + where: { + id: department_id + } + }) + ) + .then(departments => { + department_to_remove = departments[0] + + // Check if user specify valid department number + if (!department_to_remove) { + req.session.flash_error('Cannot remove department: wronge parameters') + + throw new Error( + 'User ' + + req.user.id + + ' tried to remove non-existing department ID' + + department_id + ) } - }); - }) - .then(function(departments){ - department_to_remove = departments[ 0 ]; - - // Check if user specify valid department number - if (! department_to_remove) { - - req.session.flash_error('Cannot remove department: wronge parameters'); - throw new Error( - 'User '+req.user.id+' tried to remove non-existing department ID'+department_id - ); - } - - if (department_to_remove.users.length > 0){ - req.session.flash_error( - 'Cannot remove department '+department_to_remove.name - +' as it still has ' - +department_to_remove.users.length+' users.' - ); + if (department_to_remove.users.length > 0) { + req.session.flash_error( + 'Cannot remove department ' + + department_to_remove.name + + ' as it still has ' + + department_to_remove.users.length + + ' users.' + ) - throw new Error('Department still has users'); - } - - // TODO VPP remove corresponding records in supervisors linking table - return department_to_remove.destroy(); - }) - .then(function(){ - req.session.flash_message('Department was successfully removed'); - return res.redirect_with_session('/settings/departments/'); - }) - .catch(function(error){ - - console.error( - 'An error occurred when trying to edit departments by user '+req.user.id+' : '+error - ); + throw new Error('Department still has users') + } - return res.redirect_with_session( department_to_remove - ? '/settings/departments/edit/'+department_to_remove.get('id')+'/' - : '/settings/departments/' - ); - }); -}); + // TODO VPP remove corresponding records in supervisors linking table + return department_to_remove.destroy() + }) + .then(() => { + req.session.flash_message('Department was successfully removed') + return res.redirect_with_session('/settings/departments/') + }) + .catch(error => { + console.error( + 'An error occurred when trying to edit departments by user ' + + req.user.id + + ' : ' + + error, + error.stack + ) + + return res.redirect_with_session( + department_to_remove + ? '/settings/departments/edit/' + department_to_remove.get('id') + '/' + : '/settings/departments/' + ) + }) +}) function promise_to_extract_company_and_department(req, only_active = true) { - var department_id = req.params['department_id'], - company; - - return Promise.try(function(){ - - if ( ! validator.isInt(department_id)) { - throw new Error('User '+req.user.id+' tried to open department refered by non-int ID '+department_id); + const department_id = + req.body.department_id || + req.query.department_id || + req.params.department_id + let company + + return Promise.try(() => { + if ( + typeof department_id !== 'number' && + (!department_id || !validator.isInt(department_id)) + ) { + throw new Error( + 'User ' + + req.user.id + + ' tried to open department refered by non-int ID ' + + department_id + ) } if (only_active) { return req.user.getCompany({ - scope : ['with_active_users', 'order_by_active_users'], - }); + scope: ['with_active_users', 'order_by_active_users'] + }) } else { return req.user.getCompany({ - scope : ['with_all_users'], - }); + scope: ['with_all_users'] + }) } }) - .then(function(c){ - company = c; - - if ( ! company ) { - throw new Error('Cannot determin company!'); - } + .then(c => { + company = c - return company.getDepartments({ - scope : ['with_simple_users', 'with_boss', 'with_supervisors'], - where : { - id : department_id, + if (!company) { + throw new Error('Cannot determin company!') } - }); - }) - .then(function(departments){ - var department = departments[0]; - // Ensure we have database record for given department ID - if ( ! department ) { - throw new Error('Non existing department ID provided'); - } + return company.getDepartments({ + scope: ['with_simple_users', 'with_manager', 'with_supervisors'], + where: { + id: department_id + } + }) + }) + .then(departments => { + const department = departments[0] - return Promise.resolve({ - company : company, - department : department, - }); - }); -} + // Ensure we have database record for given department ID + if (!department) { + throw new Error('Non existing department ID provided') + } -router.get('/departments/edit/:department_id/', function(req, res){ - var department_id = req.params['department_id']; + return Promise.resolve({ + company, + department + }) + }) +} - Promise.try(function(){ - return promise_to_extract_company_and_department(req); - }) - .then(function(result){ - var department = result.department, - company = result.company; - - res.render('department_details', { - title : 'Department details', - department : department, - company : company, - allowance_options : generate_all_department_allowances(), - }); - }) - .catch(function(error){ - console.error( - 'An error occurred when trying to edit department '+department_id - +' for user '+req.user.id + ' : ' + error - ); +router.get('/departments/edit/:department_id/', (req, res) => { + const department_id = req.params.department_id - req.session.flash_error( - 'Failed to fetch details for given department' - ); + Promise.try(() => promise_to_extract_company_and_department(req)) + .then(result => { + const department = result.department + const company = result.company - return res.redirect_with_session('/settings/departments/'); - }); -}); + res.render('department_details', { + title: 'Settings - Department details | TimeOff', + department, + company, + allowance_options: generate_all_department_allowances() + }) + }) + .catch(error => { + console.error( + 'An error occurred when trying to edit department ' + + department_id + + ' for user ' + + req.user.id + + ' : ' + + error, + error.stack + ) + + req.session.flash_error('Failed to fetch details for given department') + + return res.redirect_with_session('/settings/departments/') + }) +}) -router.post('/departments/edit/:department_id/', function(req, res){ +router.post('/departments/edit/:department_id/', (req, res) => { + const department_id = req.body.department_id + let company + let department - var department_id = req.params['department_id'], - company, - department; + Promise.try(() => promise_to_extract_company_and_department(req)) + .then(result => { + company = result.company + department = result.department - // to remove supervisor we need to get all users, not only active ones - var only_active = !req.body.remove_supervisor_id - - Promise.try(function(){ - return promise_to_extract_company_and_department(req, only_active); - }) - .then(function(result){ - company = result.company; - department = result.department; + return Promise.resolve(1) + }) - return Promise.resolve(1); - }) + .then(() => { + if (req.body.remove_supervisor_id) { + return promise_to_remove_supervisor({ + supervisor_id: req.body.remove_supervisor_id, + company, + department + }).then(() => { + req.session.flash_message( + 'Supervisor was removed from ' + department.name + ) + return Promise.resolve(1) + }) + } else if (req.body.do_add_supervisors) { + return promise_to_update_supervisors({ + req, + company, + department + }).then(() => { + req.session.flash_message( + 'Supervisors were added to department ' + department.name + ) + return Promise.resolve(1) + }) + } - .then(function(){ - if (req.body.remove_supervisor_id) { - return promise_to_remove_supervisor({ - supervisor_id : req.body.remove_supervisor_id, - company : company, - department : department, - }) - .then(function(){ - req.session.flash_message('Supervisor was removed from ' + department.name); - return Promise.resolve(1); - }); - } else if ( req.body.do_add_supervisors ) { - return promise_to_update_supervisors({ - req : req, - company : company, - department : department, + return promise_to_update_department({ + req, + company, + department + }).then(() => { + req.session.flash_message( + 'Department ' + department.name + ' was updated' + ) + return Promise.resolve(1) }) - .then(function(){ - req.session.flash_message('Supervisors were added to department ' + department.name); - return Promise.resolve(1); - }); - } - - return promise_to_update_department({ - req : req, - company : company, - department : department, }) - .then(function(){ - req.session.flash_message('Department ' + department.name + ' was updated'); - return Promise.resolve(1); - }); - }) - .then(function(){ - return res.redirect_with_session('.'); - }) + .then(() => res.redirect_with_session('.')) - .catch(function(error){ - console.error( - 'An error occurred when trying to update secondary superwisors for depertment '+department_id - +' by user '+req.user.id + ' : ' + error - ); + .catch(error => { + console.error( + 'An error occurred when trying to update secondary superwisors for depertment ' + + department_id + + ' by user ' + + req.user.id + + ' : ' + + error, + error.stack + ) - req.session.flash_error( - "Failed to update department's details" - ); + req.session.flash_error("Failed to update department's details") - return res.redirect_with_session('../../'); - }); -}); + return res.redirect_with_session('../../') + }) +}) function promise_to_remove_supervisor(args) { - var - supervisor_id = args.supervisor_id, - company = args.company, - department = args.department; + const supervisor_id = args.supervisor_id + const company = args.company + const department = args.department // Make sure that provided supervisor ID belongs to user from current company - if (company.users.map(function(u){return String(u.id)}).indexOf( String(supervisor_id) ) === -1){ - return Promise.resolve(1); + if ( + company.users.map(u => String(u.id)).indexOf(String(supervisor_id)) === -1 + ) { + return Promise.resolve(1) } - return department.Model.sequelize.models.DepartmentSupervisor.destroy({ - where : { - department_id : department.id, - user_id : supervisor_id, - }, - }); + return department.Model.sequelize.models.DepartmentSupervisor.destroy({ + where: { + department_id: department.id, + user_id: supervisor_id + } + }) } function promise_to_update_supervisors(args) { + const req = args.req + const company = args.company + const department = args.department - var - req = args.req, - company = args.company, - department = args.department; - - var supervisor_ids = req.body.supervisor_id || []; + let supervisor_ids = req.supervisor_id || [] // Take list of all users as a base of intersaction, // so we use submitted data only as criteria and do not save it in database supervisor_ids = company.users - .map(function(user){ return user.id}) - .filter(function(id){ return supervisor_ids.indexOf(String(id)) !== -1}); + .map(user => user.id) + .filter(id => supervisor_ids.indexOf(String(id)) !== -1) - var link_model = department.Model.sequelize.models.DepartmentSupervisor; + const link_model = department.Model.sequelize.models.DepartmentSupervisor - return link_model.destroy({ - where : { - department_id : department.id, - } - }) - .then(function(){ - return link_model.bulkCreate( - supervisor_ids.map(function(id){ return { user_id : id, department_id : department.id } }) - ); - }); + return link_model + .destroy({ + where: { + department_id: department.id + } + }) + .then(() => + link_model.bulkCreate( + supervisor_ids.map(id => ({ + user_id: id, + department_id: department.id + })) + ) + ) } function promise_to_update_department(args) { - var - req = args.req, - company = args.company, - department = args.department; - - var attributes = get_and_validate_department({ - company : company, - department_name : department.name, - no_suffix : true, - req : req, - }); + const req = args.req + const company = args.company + const department = args.department + + const attributes = get_and_validate_department({ + company, + department_name: department.name, + no_suffix: true, + req + }) // If there were any validation errors: do not update department - if ( req.session.flash_has_errors() ) { - throw new Error("Invalid parameters submitted while while attempt to update department details"); + if (req.session.flash_has_errors()) { + throw new Error( + 'Invalid parameters submitted while while attempt to update department details' + ) } - return department.updateAttributes(attributes); + return department.update(attributes) } -router.get('/departments/available-supervisors/:department_id/', function(req, res){ +router.get('/departments/available-supervisors/:department_id/', (req, res) => { + const department_id = req.params.department_id + let department + let company - var department_id = req.params['department_id'], - department, - company; + Promise.try(() => promise_to_extract_company_and_department(req)) + .then(result => { + department = result.department + company = result.company - Promise.try(function(){ - return promise_to_extract_company_and_department(req); - }) - - .then(function(result){ - department = result.department; - company = result.company; - - return department.promise_me_with_supervisors(); - }) - - .then(function(department_with_supervisors){ - - var supervisor_map = {}; + return department.promise_me_with_supervisors() + }) - department_with_supervisors.supervisors.forEach(function(user){ - supervisor_map[user.id] = true; - }); + .then(department_with_supervisors => { + const supervisor_map = {} - res.render('department/available_supervisors', { - layout : false, - users : _.map( - _.filter(company.users, function(user){ return user.id !== department.bossId }), - function(user){ user._marked = supervisor_map[user.id]; return user } - ), - }); - }) - .catch(function(error){ - console.error( - 'An error occurred when trying to get all availabele superviers for department '+department_id - +' for user '+req.user.id + ' : ' + error - ); + department_with_supervisors.supervisors.forEach(user => { + supervisor_map[user.id] = true + }) - res.send('REQUEST FAILED'); - }); -}); + res.render('department/available_supervisors', { + layout: false, + users: _.map( + _.filter(company.users, user => user.id !== department.manager_id), + user => { + user._marked = supervisor_map[user.id] + return user + } + ), + title: 'Settings - Department Available Supervisors | TimeOff' + }) + }) + .catch(error => { + console.error( + 'An error occurred when trying to get all availabele superviers for department ' + + department_id + + ' for user ' + + req.user.id + + ' : ' + + error, + error.stack + ) + + res.send('REQUEST FAILED') + }) +}) -module.exports = router; +module.exports = router diff --git a/lib/route/feed.js b/lib/route/feed.js index 920ac04e3..fcff4aca0 100644 --- a/lib/route/feed.js +++ b/lib/route/feed.js @@ -1,157 +1,255 @@ - -"use strict"; - -const - express = require('express'), - router = express.Router(), - _ = require('underscore'), - moment = require('moment'), - Promise = require('bluebird'), - ical = require('ical-generator'), - config = require('../config'), - TeamView = require('../model/team_view'); - -const - numberOfFutureMonthsInTeamViewFeed = config.get('number_of_future_months_in_team_view_feed') || 6, - numberOfPastMonthsInTeamViewFeed = config.get('number_of_past_months_in_team_view_feed') || 2; - -const { getCommentsForLeave } = require('../model/comment'); - -router.get('/:token/ical.ics', function(req, res){ - - var cal = ical({ - domain : 'timeoff.management', - }), - token = req.params['token'], - model = req.app.get('db_model'), - user; - - Promise - .resolve() - .then(() => model.UserFeed.find({ - where : {feed_token : token}, - include : [{ - model : model.User, - as : 'user', - include : [{ - model : model.Company, - as : 'company', - where : { - mode : {$ne : model.Company.get_mode_readonly_holidays()}, - }, - }] - }] +'use strict' + +const express = require('express') +const router = express.Router() +const _ = require('underscore') +const moment = require('moment') +const Promise = require('bluebird') +const ical = require('ical-generator') +const config = require('../config') +const TeamView = require('../model/team_view') + +const numberOfFutureMonthsInTeamViewFeed = + config.get('number_of_future_months_in_team_view_feed') || 6 +const numberOfPastMonthsInTeamViewFeed = + config.get('number_of_past_months_in_team_view_feed') || 2 + +const { getCommentsForLeave } = require('../model/comment') + +router.get('/:token/anniversary.ics', (req, res) => { + const cal = ical({ + domain: 'timeoff.management' + }) + const token = req.params.token + const model = req.app.get('db_model') + + Promise.resolve() + .then(() => + model.UserFeed.find({ + where: { feed_token: token }, + include: [ + { + model: model.User, + as: 'user', + include: [ + { + model: model.Company, + as: 'company' + } + ] + } + ] }) ) - .then(function(feed){ - - if ( ! feed ) { - throw new Error("Unknown token provided"); + .then(feed => { + if (!feed) { + throw new Error('Unknown token provided') } - user = feed.user; + return model.User.findAll({ + where: { + company_id: feed.user.company.id, + $or: [{ end_date: { $lt: new Date() } }, { end_date: null }] + } + }) + .then(users => { + cal.name('anniversary') + + const days = users.map(u => { + // next one + const nextOne = new Date(u.start_date) + const year0 = nextOne.getFullYear() + const yearNow = new Date().getFullYear() + nextOne.setFullYear(yearNow) + const years = yearNow - year0 // moment().diff(u.start_date, 'years'); + return { + user: u, + moment: nextOne, + years + } + }) - if (feed.is_calendar()){ - cal.name(user.full_name() + ' calendar'); + return days + }) + .then(days => { + days.forEach(day => { + const start = moment.utc(day.moment) + const end = moment.utc(day.moment) + + cal.createEvent({ + start: start.toDate(), + end: end.toDate(), + summary: + day.user.full_name() + + ' is ' + + day.years + + ' years at the company.', + allDay: true, + description: new Buffer( + JSON.stringify({ years: day.years, name: day.user.full_name() }) + ).toString('base64') + }) + }) + res.send(cal.toString()) + }) + }) + .catch(err => { + console.error(err) + res.status(404).send('N/A') + }) +}) + +router.get('/:token/ical.ics', (req, res) => { + const cal = ical({ + domain: 'timeoff.management' + }) + const token = req.params.token + const model = req.app.get('db_model') + let user + + Promise.resolve() + .then(() => + model.UserFeed.findOne({ + where: { feed_token: token }, + include: [ + { + model: model.User, + as: 'user', + include: [ + { + model: model.Company, + as: 'company', + where: { + mode: { $ne: model.Company.get_mode_readonly_holidays() } + } + } + ] + } + ] + }) + ) + .then(feed => { + if (!feed) { + throw new Error('Unknown token provided') + } + + user = feed.user + + if (feed.is_calendar()) { + cal.name(user.full_name() + ' calendar') return user .promise_calendar({ - year : user.company.get_today(), - show_full_year : true, + year: user.calendar.company.get_today(), + show_full_year: true }) - .then(function(calendar){ - let days = _.flatten( calendar.map( cal => cal.as_for_team_view() )); + .then(calendar => { + cal.name(user.full_name() + ' calendar') - days.forEach(day => day.user = user); + const days = _.flatten( + _.map(calendar, cal => cal.as_for_team_view()) + ) - return Promise.resolve(days); - }); - } else { + days.forEach(day => { + day.user = user + }) - cal.name(`${ user.full_name() }'s team whereabout`); + return Promise.resolve(days) + }) + } else { + cal.name(`${user.full_name()}'s team whereabout`) // Get the list of month deltas in relation to current month, to we can calculate // moths for which to build the feed - let monthDeltas = Array.from(Array(numberOfFutureMonthsInTeamViewFeed + 1).keys()) - .concat( Array.from(Array(numberOfPastMonthsInTeamViewFeed).keys()).map(i => -1 * (i + 1)) ); - - return Promise - .resolve( - monthDeltas.map( - delta => user.company.get_today().clone().add(delta, 'months').startOf('month') - ) + const monthDeltas = Array.from( + Array(numberOfFutureMonthsInTeamViewFeed + 1).keys() + ).concat( + Array.from(Array(numberOfPastMonthsInTeamViewFeed).keys()).map( + i => -1 * (i + 1) ) - .map(month => { - - const team_view = new TeamView({ - user : user, - base_date : month, - }); + ) + + return Promise.resolve( + monthDeltas.map(delta => + user.company + .get_today() + .clone() + .add(delta, 'months') + .startOf('month') + ) + ) + .map( + month => { + const team_view = new TeamView({ + user, + base_date: month + }) - return team_view.promise_team_view_details() - .then(details => { - let days = []; + return team_view.promise_team_view_details().then(details => { + let days = [] details.users_and_leaves.forEach(rec => { - rec.days.forEach(day => day.user = rec.user); - days = days.concat( rec.days ); - }); - - return Promise.resolve(days); - }); - }, { concurrency : 2 }) - .then(arrayOfDays => Promise.resolve( _.flatten(arrayOfDays) )); + const user = rec.user + rec.days.forEach(day => { + day.user = user + }) + days = days.concat(rec.days) + }) + + return Promise.resolve(days) + }) + }, + { concurrency: 10 } + ) + .then(arrayOfDays => Promise.resolve(_.flatten(arrayOfDays))) } }) - .then(async (days) => { + .then(async days => { for (const day of days) { // We care only about days when employee is on leave if (!(day.is_leave_morning || day.is_leave_afternoon)) { - continue; + continue } - let start = moment.utc(day.moment), - end = moment.utc(day.moment), - allDay = false; + const start = moment.utc(day.moment) + const end = moment.utc(day.moment) + let allDay = false if (day.is_leave_morning && day.is_leave_afternoon) { - start.hour(9).minute(0); - end.hour(17).minute(0); - allDay = true; + start.hour(9).minute(0) + end.hour(17).minute(0) + allDay = true } else if (!day.is_leave_morning && day.is_leave_afternoon) { - start.hour(13).minute(0); - end.hour(17).minute(0); + start.hour(13).minute(0) + end.hour(17).minute(0) } else if (day.is_leave_morning && !day.is_leave_afternoon) { - start.hour(9).minute(0); - end.hour(13).minute(0); + start.hour(9).minute(0) + end.hour(13).minute(0) } - const comments = await getCommentsForLeave({leave: day.leave_obj}); + const comments = await getCommentsForLeave({ leave: day.leave_obj }) cal.createEvent({ - start : start.toDate(), - end : end.toDate(), - allDay : allDay, - summary : day.user.full_name() + ' is OOO (out of office)', - description: (comments.length > 0 - ? `With comments: ${comments.map(({comment}) => comment).join('. ')}` - : '' - ), - }); + start: start.toDate(), + end: end.toDate(), + allDay, + summary: day.user.full_name() + ' is OOO (out of office)', + description: + comments.length > 0 + ? `With comments: ${comments + .map(({ comment }) => comment) + .join('. ')}` + : '' + }) } - res.send( cal.toString() ); + res.send(cal.toString()) }) .catch(error => { + console.log(`Failed to fetch feed because of: ${error}`) + res.status(404).send('N/A') + }) +}) - console.log(`Failed to fetch feed because of: ${error}`); - - // TODO VPP set 404 status - res.send('N/A'); - }); - -}); - - -module.exports = router; +module.exports = router diff --git a/lib/route/integration_api.js b/lib/route/integration_api.js index f78660f67..eac9e8d86 100644 --- a/lib/route/integration_api.js +++ b/lib/route/integration_api.js @@ -1,130 +1,127 @@ +'use strict' -'use strict'; - -const - express = require('express'), - router = express.Router(), - validator = require('validator'), - Promise = require('bluebird'), - moment = require('moment'), - TeamView = require('../model/team_view'), - _ = require('underscore'), - {getAudit}= require('../model/audit'), - {getUsersWithLeaves} = require('../model/Report'); +const express = require('express') +const router = express.Router() +const validator = require('validator') +const Promise = require('bluebird') +const moment = require('moment') +const TeamView = require('../model/team_view') +const { getAudit } = require('../model/audit') +const { getUsersWithLeaves } = require('../model/Report') module.exports = passport => { - router.all( /.*/, passport.authenticate('bearer', { session: false }), (req, res, next) => { - if ( req.isAuthenticated() ) { - return next(); + if (req.isAuthenticated()) { + return next() } - return res.status(401).json({ ok : false}); - }); - - router.get( - '/', - (_req, res) => res.json({ok : true}) - ); - - router.get( - '/report/allowance', - (req, res) => { - - const startDate = validator.isDate(req.query['start_date']) - ? moment.utc(req.query['start_date']) - : req.user.company.get_today(); - - const endDate = validator.isDate(req.query['end_date']) - ? moment.utc(req.query['end_date']) - : req.user.company.get_today(); - - const teamView = new TeamView({ - user : req.user, - start_date : startDate, - end_date : endDate, - }); - - const currentDeparmentId = validator.isNumeric(req.query['department']) - ? req.query['department'] - : null; - - Promise.join( - teamView.promise_team_view_details({ - department_id : currentDeparmentId, - }), - req.user.get_company_with_all_leave_types(), - (teamViewDetails, company) => { - return teamView - .inject_statistics({ - team_view_details : teamViewDetails, - leave_types : company.leave_types, - }) - .then(teamViewDetails => ( - res.json({data : [ + return res.status(401).json({ ok: false }) + } + ) + + router.get('/', (_req, res) => res.json({ ok: true })) + + router.get('/report/allowance', (req, res) => { + const startDate = validator.isDate(req.params.start_date) + ? moment.utc(req.params.start_date) + : req.user.company.get_today() + + const endDate = validator.isDate(req.params.end_date) + ? moment.utc(req.params.end_date) + : req.user.company.get_today() + + const teamView = new TeamView({ + user: req.user, + start_date: startDate, + end_date: endDate + }) + + const currentDeparmentId = validator.isNumeric(req.params.department) + ? req.params.department + : null + + Promise.join( + teamView.promise_team_view_details({ + department_id: currentDeparmentId + }), + req.user.get_company_with_all_leave_types(), + (teamViewDetails, company) => + teamView + .inject_statistics({ + team_view_details: teamViewDetails, + leave_types: company.leave_types + }) + .then(teamViewDetails => + res.json({ + data: [ teamViewDetails.users_and_leaves.map(ul => ({ - userId: ul.user.id, + user_id: ul.user.id, userEmail: ul.user.email, userLastname: ul.user.lastname, userName: ul.user.name, - leaveTypeBreakDown: ul.statistics.leave_type_break_down.pretty_version, - deductedDays: ul.statistics.deducted_days, + leaveTypeBreakDown: + ul.statistics.leave_type_break_down.pretty_version, + deductedDays: ul.statistics.deducted_days })) - ]}) - )) - }) - .catch(error => { - console.log( - 'An error occured when user '+req.user.id+ - ' tried to access /reports/allowancebytime page: '+error - ); - - res.json({ error }) - }); - - } - ); - - router.get( - '/report/absence', - (req,res) => { - - const startDate = validator.isDate(req.query['start_date']) - ? moment.utc(req.query['start_date']) - : req.user.company.get_today(); - - const endDate = validator.isDate(req.query['end_date']) - ? moment.utc(req.query['end_date']) - : req.user.company.get_today(); - - const departmentId = validator.isNumeric(req.query['department']) - ? req.query['department'] - : null; - - let result = getUsersWithLeaves({company:req.user.company, startDate, endDate, departmentId}); - - result = result - .then(data => res.json(data)) - .catch(error => { - console.log(`An error occured when trying to access /report/absence: ${error} at ${error.stack}`); - res.json({ error: `${error}` }); - }); - }); - - router.get( - '/audit/', - (req,res) => { - getAudit({companyId: req.user.companyId}) - .then(data => res.json(data)) - .catch(error => { - console.log(`Failed to fetch Audit data: ${error} at ${error.stack}`); - res.json({ error: `${error}` }); - }); - } - ); - - return router; + ] + }) + ) + ).catch(error => { + console.log( + 'An error occured when user ' + + req.user.id + + ' tried to access /reports/allowancebytime page: ' + + error + ) + + res.json({ error }) + }) + }) + + router.get('/report/absence', (req, res) => { + const startDate = + req.params.start_date && validator.isDate(req.params.start_date) + ? moment.utc(req.params.start_date) + : req.user.company.get_today() + + const endDate = + req.params.end_date && validator.isDate(req.params.end_date) + ? moment.utc(req.params.end_date) + : req.user.company.get_today() + + const department_id = + req.params.department && validator.isNumeric(req.params.department) + ? req.params.department + : null + + getUsersWithLeaves({ + company: req.user.company, + startDate, + endDate, + department_id + }) + .then(data => res.json(data)) + .catch(error => { + console.log( + `An error occured when trying to access /report/absence: ${error} at ${ + error.stack + }` + ) + res.json({ error: `${error}` }) + }) + }) + + router.get('/audit/', (req, res) => { + getAudit({ company_id: req.user.company_id }) + .then(data => res.json(data)) + .catch(error => { + console.log(`Failed to fetch Audit data: ${error} at ${error.stack}`) + res.json({ error: `${error}` }) + }) + }) + + return router } diff --git a/lib/route/login.js b/lib/route/login.js index 1ccb615b1..16e277d1a 100644 --- a/lib/route/login.js +++ b/lib/route/login.js @@ -1,4 +1,3 @@ - /* * Contain handlers for dealing with user account: * - login @@ -10,309 +9,443 @@ * not the router itself! * Exported function gets passport object. * */ -'use strict'; +'use strict' + +const validator = require('validator') +const Promise = require('bluebird') +const fs = require('fs') +const config = require('../config') +const moment_tz = require('moment-timezone') +const EmailTransport = require('../email') +const SlackTransport = require('../slack') -var - validator = require('validator'), - Promise = require('bluebird'), - fs = require("fs"), - config = require('../config'), - moment_tz = require('moment-timezone'), - EmailTransport = require('../email'); +const multer = require('multer') +const upload = multer() -Promise.promisifyAll(fs); +Promise.promisifyAll(fs) -var get_url_to_site_root_for_anonymous_session = function(req) { +function get_url_to_site_root_for_anonymous_session(req) { return req.get('host').indexOf('app.timeoff') < 0 ? '/' - : config.get('promotion_website_domain'); + : config.get('branding:website') } module.exports = function(passport) { + const express = require('express') + const router = express.Router() + + router.get('/login', (req, res) => { + res.render('login', { + login: config.get('login') || { default: true }, + allow_create_new_accounts: JSON.parse(config.get('options:registration')), + title: 'Login | TimeOff', + url_to_the_site_root: get_url_to_site_root_for_anonymous_session(req) + }) + }) + + router.get( + '/auth/google', + passport.authenticate('google', { scope: ['email'] }) + ) + + router.get( + '/auth/google/callback', + passport.authenticate('google', { failureRedirect: '/login' }), + (req, res) => { + // Successful authentication, redirect home. + res.redirect('/') + } + ) - var express = require('express'); - var router = express.Router(); - - router.get('/login', function(req, res){ - res.render('login', { - allow_create_new_accounts: JSON.parse(config.get('allow_create_new_accounts')), - title : 'Time Off Management', - url_to_the_site_root : get_url_to_site_root_for_anonymous_session(req), - }); - }); - - router.post('/login', function(req, res, next) { - passport.authenticate('local', function(err, user) { - if (err) { return next(err); } + router.post('/login', (req, res, next) => { + passport.authenticate('local', (err, user) => { + if (err) { + return next(err) + } if (!user) { - req.session.flash_error('Incorrect credentials'); - return res.redirect_with_session('/login'); + req.session.flash_error('Incorrect credentials') + return res.redirect_with_session('/login') } - req.logIn(user, function(err) { - if (err) { return next(err); } - - req.session.flash_message('Welcome back '+user.name+'!'); - - return res.redirect_with_session('/'); - }); - })(req, res, next); - }); + req.logIn(user, err => { + if (err) { + return next(err) + } - router.get('/logout', function(req, res){ + req.session.flash_message('Welcome back ' + user.name + '!') - // Maybe this check is redundant but to be on safe side lets do it - if ( !req.user ) { - return res.redirect_with_session(303, '/'); - } + return res.redirect_with_session('/') + }) + })(req, res, next) + }) - req.logout(); + router.get('/logout', (req, res) => { + // Maybe this check is redundant but to be on safe side lets do it + if (!req.user) { + return res.redirect_with_session(303, '/') + } - return res.redirect_with_session(res.locals.url_to_the_site_root); - }); + req.logout() - router.get('/register', function(req, res){ + return res.redirect_with_session(res.locals.url_to_the_site_root) + }) - // Disable new accounts. - if ( !JSON.parse(config.get('allow_create_new_accounts')) ) { - return res.redirect_with_session(res.locals.url_to_the_site_root); - } + router.get('/register', (req, res) => { + // Disable new accounts. + if (!JSON.parse(config.get('allow:create:new:accounts'))) { + return res.redirect_with_session(res.locals.url_to_the_site_root) + } - // There is no need to register new accounts when user alreeady login - if ( req.user ) { - return res.redirect_with_session(303, '/'); - } + // There is no need to register new accounts when user alreeady login + if (req.user) { + return res.redirect_with_session(303, '/') + } - res.render('register',{ - url_to_the_site_root : get_url_to_site_root_for_anonymous_session(req), - countries : config.get('countries'), - timezones_available : moment_tz.tz.names(), - }); - }); + res.render('register', { + url_to_the_site_root: get_url_to_site_root_for_anonymous_session(req), + countries: config.get('countries'), + timezones_available: moment_tz.tz.names(), + title: 'Register new company | TimeOff' + }) + }) + + router.post('/register', (req, res) => { + // There is no need to register new accounts when user already login + // (just to prevent people to mess around) + if (req.user) { + return res.redirect_with_session(303, '/') + } - router.post('/register', function(req, res){ + // TODO at some point we need to unified form validation code + // and make it reusable - // There is no need to register new accounts when user alreeady login - // (just to prevent people to mess around) - if ( req.user ) { - return res.redirect_with_session(303, '/'); - } + const email = req.body.email + if (!email) { + req.session.flash_error('Email was not provided') + } else if (!validator.isEmail(email)) { + req.session.flash_error('Email address is invalid') + } - // TODO at some point we need to unified form validation code - // and make it reusable + const name = req.body.name - var email = req.body['email']; - if (!email){ - req.session.flash_error('Email was not provided'); - } else if ( ! validator.isEmail(email)) { - req.session.flash_error('Email address is invalid'); - } + const slack_username = req.body.slack_username || '' + /* Slack username is not mandatory. + if (!slack_username) { + req.session.flash_error('Slack username was not specified') + } + */ - var name = req.body['name']; - if (!name){ - req.session.flash_error('Name was not specified'); - } + if (!name) { + req.session.flash_error('Name was not specified') + } - var lastname = req.body['lastname']; - if (!lastname) { - req.session.flash_error('Last was not specified'); - } + const lastname = req.body.lastname + if (!lastname) { + req.session.flash_error('Last name was not specified') + } - var company_name = req.body['company_name']; + const company_name = req.body.company_name - var password = req.body['password']; - if (!password) { - req.session.flash_error('Password could not be blank'); - } else if ( password !== req.body['password_confirmed'] ) { - req.session.flash_error('Confirmed password does not match initial one'); - } + const password = req.body.password + if (!password) { + req.session.flash_error('Password could not be blank') + } else if (password !== req.body.password_confirmed) { + req.session.flash_error('Confirmed password does not match initial one') + } - var country_code = req.body['country']; - if (! validator.matches(country_code, /^[a-z]{2}/i) ){ - req.session.flash_error('Incorrect country code'); - } + const country_code = req.body.country + if (!validator.matches(country_code, /^[a-z]{2}/i)) { + req.session.flash_error('Incorrect country code') + } - let timezone = validator.trim(req.body['timezone']); - if ( ! moment_tz.tz.names().find(tz_str => tz_str === timezone) ) { - req.session.flash_error('Time zone is unknown'); - } + const timezone = validator.trim(req.body.timezone) + if (!moment_tz.tz.names().find(tz_str => tz_str === timezone)) { + req.session.flash_error('Time zone is unknown') + } - // In case of validation error redirect back to registration form - if ( req.session.flash_has_errors() ) { - return res.redirect_with_session('/register/'); - } + // In case of validation error redirect back to registration form + if (req.session.flash_has_errors()) { + return res.redirect_with_session('/register/') + } - // Try to create new record of user - req.app.get('db_model').User.register_new_admin_user({ - email : email.toLowerCase(), - password : password, - name : name, - lastname : lastname, - company_name : company_name, - country_code : country_code, - timezone : timezone, + // Try to create new record of user + req.app + .get('db_model') + .User.register_new_admin_user({ + email: email.toLowerCase(), + slack_username: slack_username.toLowerCase(), + password, + name, + lastname, + company_name, + country_code, + timezone }) // Send registration email - .then(function(user){ - var email = new EmailTransport(); - - return email.promise_registration_email({ - user : user, - }) - .then(function(){ - return Promise.resolve(user) - }); + .then(user => { + console.log('Sending registration email to ' + user.email) + + const email = new EmailTransport() + + return ( + email + .promise_registration_email({ + user + }) + .then(() => Promise.resolve(user)) + // Fail silently for the user and track the error for the administrator. + .catch(error => { + console.error( + 'Failed to send registration email to ' + + user.email + + ' : ' + + error, + error.stack + ) + return Promise.resolve(user) + }) + ) }) - .then(function(user){ + .then(user => { + console.log('Sending Slack notification to ' + user.email) + + const Slack = new SlackTransport() + + return ( + Slack.promise_registration_slack({ + user + }) + .then(() => Promise.resolve(user)) + // Fail silently for the user and track the error for the administrator. + .catch(error => { + console.error( + 'Failed to send slack notification to ' + + user.email + + ' : ' + + error, + error.stack + ) + return Promise.resolve(user) + }) + ) + }) + .then(user => { + console.log('Authenticated the newly created user ' + user.email) // Login newly created user - req.logIn(user, function(err) { - if (err) { return next(err); } - - req.session.flash_message( - 'Registration is complete.' - ); + req.logIn(user, err => { + if (err) { + console.error(err) + return + } - return res.redirect_with_session('/'); - }); + req.session.flash_message('Registration is complete.') + return res.redirect_with_session('/') + }) }) - .catch(function(error){ - console.error( - 'An error occurred when trying to register new user ' - + email + ' : ' + error - ); - - req.session.flash_error( - 'Failed to register user please contact customer service.'+ - (error.show_to_user ? ' '+ error : '') - ); - - return res.redirect_with_session('/register/'); - }); - - }); - - router.get('/forgot-password/', function(req, res){ - - res.render('forgot_password',{ - url_to_the_site_root : get_url_to_site_root_for_anonymous_session(req), - }); - }); - - router.post('/forgot-password/', function(req, res){ - var email = req.body['email']; - - if (!email){ - req.session.flash_error('Email was not provided'); - - } else if ( ! validator.isEmail(email)) { - req.session.flash_error('Email address is invalid'); + .catch(error => { + console.error( + 'An error occurred when trying to register new user ' + + email + + ' : ' + + error, + error.stack + ) + + req.session.flash_error( + 'Failed to register user please contact customer service.' + + (error.show_to_user ? ' ' + error : '') + ) + + return res.redirect_with_session('/register/') + }) + }) + + router.get('/forgot-password/', (req, res) => { + res.render('forgot_password', { + url_to_the_site_root: get_url_to_site_root_for_anonymous_session(req), + title: 'Forgotten password | TimeOff' + }) + }) + + router.post('/forgot-password/', (req, res) => { + let email = req.body.email + + if (!email) { + req.session.flash_error('Email was not provided') + } else if (!validator.isEmail(email)) { + req.session.flash_error('Email address is invalid') } // In case of validation error redirect back to forgot password form - if ( req.session.flash_has_errors() ) { - return res.redirect_with_session('./'); + if (req.session.flash_has_errors()) { + return res.redirect_with_session('./') } - var success_msg ='Please check your email box for further instructions'; + const success_msg = 'Please check your email box for further instructions' // Normalize email address: system operates only in low cased emails - email = email.toLowerCase(); - - req.app.get('db_model').User.find_by_email(email) - .then(function(user){ + email = email.toLowerCase() + req.app + .get('db_model') + .User.find_by_email(email) + .then(user => { if (!user) { - req.session.flash_message(success_msg); + req.session.flash_message(success_msg) - var error = new Error(''); - error.do_not_report = true; - throw error; + const error = new Error('') + error.do_not_report = true + throw error } - return Promise.resolve(user); + return Promise.resolve(user) }) - .then(function(user){ - var Email = new EmailTransport(); + .then(user => { + const Slack = new SlackTransport() + + Slack.promise_forgot_password_slack({ + user + }) + + const Email = new EmailTransport() return Email.promise_forgot_password_email({ - user : user, - }); + user + }) }) - .then(function(){ - req.session.flash_message(success_msg); - return res.redirect_with_session('./'); + .then(() => { + req.session.flash_message(success_msg) + return res.redirect_with_session('./') }) - .catch(function(error){ - - if (error.do_not_report ){ - return res.redirect_with_session('./'); + .catch(error => { + if (error.do_not_report) { + return res.redirect_with_session('./') } - console.error('An error occurred while submittin forgot password form: '+error); - req.session.flash_error('Failed to proceed with submitted data.'); - return res.redirect_with_session('./'); - }); - - }); - - router.get('/reset-password/', function(req, res){ + console.error( + 'An error occurred while submittin forgot password form: ' + error, + error.stack + ) + req.session.flash_error('Failed to proceed with submitted data.') + return res.redirect_with_session('./') + }) + }) - var token = req.query['t']; + router.get('/reset-password/', (req, res) => { + const token = req.query.t - req.app.get('db_model').User.get_user_by_reset_password_token(token) - .then(function(user){ - if (! user) { - req.session.flash_error('Unknown reset password link, please submit request again'); + req.app + .get('db_model') + .User.get_user_by_reset_password_token(token) + .then(user => { + if (!user) { + req.session.flash_error( + 'Unknown reset password link, please submit request again' + ) return res.redirect_with_session('/forgot-password/') } - res.render('reset_password',{ - url_to_the_site_root : get_url_to_site_root_for_anonymous_session(req), - token : token, - }); - }); - }); - - router.post('/reset-password/', function(req, res){ - - var token = req.body['t'], - password = req.body['password'], - confirm_password = req.body['confirm_password']; + res.render('reset_password', { + url_to_the_site_root: get_url_to_site_root_for_anonymous_session(req), + token, + title: 'Reset password | TimeOff' + }) + }) + }) + router.post('/reset-password/', (req, res) => { + const token = req.body.t + const password = req.body.password + const confirm_password = req.body.confirm_password if (password !== confirm_password) { - req.session.flash_error('Confirmed password does not match password'); - return res.redirect_with_session('/reset-password/?t='+token); + req.session.flash_error('Confirmed password does not match password') + return res.redirect_with_session('/reset-password/?t=' + token) } - req.app.get('db_model').User.get_user_by_reset_password_token(token) - .then(function(user){ - if (! user) { - req.session.flash_error('Unknown reset password link, please submit request again'); - return res.redirect_with_session('/forgot-password/'); + req.app + .get('db_model') + .User.get_user_by_reset_password_token(token) + .then(user => { + if (!user) { + req.session.flash_error( + 'Unknown reset password link, please submit request again' + ) + return res.redirect_with_session('/forgot-password/') } - return Promise.resolve(user); + return Promise.resolve(user) }) - .then(function(user){ - user.password = req.app.get('db_model').User.hashify_password(password); - return user.save(); + .then(user => { + user.password = req.app.get('db_model').User.hashify_password(password) + return user.save() }) - .then(function(user){ - var Email = new EmailTransport(); + .then(user => { + const Slack = new SlackTransport() + + Slack.promise_reset_password_slack({ + user + }) + + const Email = new EmailTransport() return Email.promise_reset_password_email({ - user : user, - }); + user + }) + }) + .then(() => { + req.session.flash_message( + 'Please use new password to login into system' + ) + return res.redirect_with_session('/login/') }) - .then(function(){ - req.session.flash_message('Please use new password to login into system'); - return res.redirect_with_session('/login/') - }); - }); - - return router; -}; + }) + + router.post('/import-company/', upload.single('company_dump'), (req, res) => + Promise.resolve() + .then(() => { + console.log('req.file', req.file) + + if (req.file.size === 0) { + throw new Error('No dump file to restore from was provided') + } + + if (req.file.path && !req.file.buffer) { + // disk storage + return fs.readFileAsync(req.file.path, 'utf8') + } + + // memory storage + return req.file.buffer.toString() + }) + .then(dump_json => Promise.resolve(JSON.parse(dump_json))) + .then(raw_company_obj => + req.app.get('db_model').Company.restore_from_dump({ + dump_json: raw_company_obj + }) + ) + .then(company => { + req.session.flash_message('Company ' + company.name + ' was restored') + res.redirect_with_session('/import-company/') + }) + .catch(error => { + req.session.flash_error( + 'Failed to import company, due to error: ' + error, + error.stack + ) + res.redirect_with_session('/import-company/') + }) + ) + + router.get('/import-company/', (req, res) => { + res.render('import_company', { + url_to_the_site_root: get_url_to_site_root_for_anonymous_session(req), + title: 'Import company | TimeOff' + }) + }) + + return router +} diff --git a/lib/route/reports.js b/lib/route/reports.js index 5aaa155c7..24ab8da01 100644 --- a/lib/route/reports.js +++ b/lib/route/reports.js @@ -1,265 +1,357 @@ - -"use strict"; - -const - express = require('express'), - router = express.Router(), - validator = require('validator'), - Promise = require('bluebird'), - moment = require('moment'), - TeamView = require('../model/team_view'), - Exception = require('../error'), - csv = Promise.promisifyAll(require('csv')), - _ = require('underscore'); - -const { fetchLeavesForLeavesReport } = require('../model/Report'); -const { sorter } = require('../util'); +'use strict' + +const express = require('express') +const router = express.Router() +const validator = require('validator') +const Promise = require('bluebird') +const moment = require('moment') +const config = require('../config') +const TeamView = require('../model/team_view') +const Exception = require('../error') +const csv = Promise.promisifyAll(require('csv')) +const _ = require('underscore') + +const { fetchLeavesForLeavesReport } = require('../model/Report') +const { sorter } = require('../util') // Make sure that current user is authorized to deal with settings -router.all(/.*/, require('../middleware/ensure_user_is_admin')); +router.all(/.*/, require('../middleware/ensure_user_is_admin')) router.get('/', (_req, res) => { - res.render('report/index'); -}); + res.render('report/index', { + title: 'Reports | TimeOff' + }) +}) router.get('/allowancebytime/', (req, res) => { - - let start_date = validator.isDate(req.query['start_date']) - ? moment.utc(req.query['start_date']) - : req.user.company.get_today(); - - let end_date = validator.isDate(req.query['end_date']) - ? moment.utc(req.query['end_date']) - : req.user.company.get_today(); - - var team_view = new TeamView({ - user : req.user, - start_date : start_date, - end_date : end_date, - }); - - var current_deparment_id = validator.isNumeric(req.query['department']) - ? req.query['department'] - : null; + const start_date = + req.query.start_date && validator.toDate(req.query.start_date) + ? moment.utc(req.query.start_date) + : req.user.company.get_today() + + const end_date = + req.query.end_date && validator.toDate(req.query.end_date) + ? moment.utc(req.query.end_date) + : req.user.company.get_today() + + const team_view = new TeamView({ + user: req.user, + start_date, + end_date + }) + + const current_deparment_id = + typeof req.query.department === 'number' || + (req.query.department && validator.isNumeric(req.query.department)) + ? req.query.department + : null Promise.join( team_view.promise_team_view_details({ - department_id : current_deparment_id, + department_id: current_deparment_id }), req.user.get_company_with_all_leave_types(), - (team_view_details, company) => { - return team_view + (team_view_details, company) => + team_view .inject_statistics({ - team_view_details : team_view_details, - leave_types : company.leave_types, + team_view_details, + leave_types: company.leave_types }) - .then(team_view_details => render_allowancebytime({ - req : req, - res : res, - team_view_details : team_view_details, - company : company, - start_date : start_date, - end_date : end_date, - })) - }) - .catch(error => { - console.error( - 'An error occured when user '+req.user.id+ - ' tried to access /reports/allowancebytime page: '+error - ); - - let - user_error_message = 'Failed to produce report. Please contact administrator.', + .then(team_view_details => + render_allowancebytime({ + params: req.query, + session: req.session, + res, + team_view_details, + company, + start_date, + end_date + }) + ) + ).catch(error => { + console.error( + 'An error occured when user ' + + req.user.id + + ' tried to access /reports/allowancebytime page: ', + error, + error.stack + ) - // By default go back to root report page - redirect_path = '../'; + let user_error_message = + 'Failed to produce report. Please contact administrator.' + // By default go back to root report page + let redirect_path = '../' - if ( error.tom_error ) { - user_error_message = Exception.extract_user_error_message(error); + if (error.tom_error) { + user_error_message = Exception.extract_user_error_message(error) - // If it is known error: stay on current page - redirect_path = './'; - } + // If it is known error: stay on current page + redirect_path = './' + } - req.session.flash_error(user_error_message); + req.session.flash_error(user_error_message) - return res.redirect_with_session(redirect_path); - }); -}); + return res.redirect_with_session(redirect_path) + }) +}) function render_allowancebytime(args) { - let - req = args.req, - res = args.res, - team_view_details = args.team_view_details, - company = args.company, - start_date = args.start_date, - end_date = args.end_date; - - return Promise - .try(() => req.query['as-csv'] - ? render_allowancebytime_as_csv(args) - : res.render('report/allowancebytime', { - users_and_leaves : team_view_details.users_and_leaves, - related_departments : team_view_details.related_departments, - current_department : team_view_details.current_department, - company : company, - start_date_str : start_date.format('YYYY-MM'), - end_date_str : end_date.format('YYYY-MM'), - start_date_obj : start_date, - end_date_obj : end_date, - same_month : (start_date.format('YYYYMM') === end_date.format('YYYYMM')), + const params = args.params + const session = args.session + const res = args.res + const team_view_details = args.team_view_details + const company = args.company + const start_date = args.start_date + const end_date = args.end_date + + return Promise.try(() => + params['as-csv'] + ? render_allowancebytime_as_csv(args) + : res.render('report/allowancebytime', { + users_and_leaves: team_view_details.users_and_leaves, + related_departments: team_view_details.related_departments, + current_department: team_view_details.current_department, + company, + start_date_str: start_date.format('YYYY-MM'), + end_date_str: end_date.format('YYYY-MM'), + start_date_obj: start_date, + end_date_obj: end_date, + same_month: start_date.format('YYYYMM') === end_date.format('YYYYMM'), + title: 'Reports - Allowance by time | TimeOff' }) - ); + ) } function render_allowancebytime_as_csv(args) { - let - res = args.res, - team_view_details = args.team_view_details, - company = args.company, - start_date = args.start_date, - end_date = args.end_date; + const params = args.params + const session = args.session + const res = args.res + const team_view_details = args.team_view_details + const company = args.company + const start_date = args.start_date + const end_date = args.end_date // Compose file name res.attachment( - company.name_for_machine() - + '_employee_allowances_between' - + start_date.format('YYYY_MM') - + '_and_' - + end_date.format('YYYY_MM') - + '.csv' - ); + company.name_for_machine() + + '_employee_allowances_between' + + start_date.format('YYYY_MM') + + '_and_' + + end_date.format('YYYY_MM') + + '.csv' + ) // Compose result CSV header - let content = [ + const content = [ ['email', 'last name', 'name'] - // Add dynamic list of Leave Types - .concat( - team_view_details.users_and_leaves.length > 0 - ? team_view_details.users_and_leaves[0].statistics.leave_type_break_down.pretty_version.map(it => it.name) - : [] - ) - .concat(['days deducted from allowance']) - ]; + // Add dynamic list of Leave Types + .concat( + team_view_details.users_and_leaves.length > 0 + ? team_view_details.users_and_leaves[0].statistics.leave_type_break_down.pretty_version.map( + it => it.name + ) + : [] + ) + .concat(['days deducted from allowance']) + ] // ... and body team_view_details.users_and_leaves.forEach(ul => { content.push( - [ - ul.user.email, - ul.user.lastname, - ul.user.name, - ] - // Dynamic part of the column list - .concat( ul.statistics.leave_type_break_down.pretty_version.map(it => it.stat)) - .concat([ul.statistics.deducted_days]) - ); - }); - - return csv.stringifyAsync( content ) - .then(csv_data_string => res.send(csv_data_string)); + [ul.user.email, ul.user.lastname, ul.user.name] + // Dynamic part of the column list + .concat( + ul.statistics.leave_type_break_down.pretty_version.map(it => it.stat) + ) + .concat([ul.statistics.deducted_days]) + ) + }) + + return csv + .stringifyAsync(content) + .then(csv_data_string => res.send(csv_data_string)) } -const extractParametersForLeavesReport = ({req, actingUser}) => { - const startDate = validator.isDate(req.query['start_date']) - ? moment.utc(req.query['start_date']) - : actingUser.company.get_today().startOf('month'); +const extractParametersForLeavesReport = ({ req, actingUser }) => { + const startDate = validator.isDate(req.query.start_date) + ? moment.utc(req.query.start_date) + : actingUser.company.get_today().startOf('month') - const endDate = validator.isDate(req.query['end_date']) - ? moment.utc(req.query['end_date']) - : actingUser.company.get_today().endOf('month'); + const endDate = validator.isDate(req.query.end_date) + ? moment.utc(req.query.end_date) + : actingUser.company.get_today().endOf('month') - const departmentId = validator.isNumeric(req.query['department']) - ? req.query['department'] - : null; + const departmentId = validator.isNumeric(req.query.department) + ? req.query.department + : null - const leaveTypeId = validator.isNumeric(req.query['leave_type']) - ? req.query['leave_type'] - : null; + const leaveTypeId = validator.isNumeric(req.query.leave_type) + ? req.query.leave_type + : null - return { startDate, endDate, departmentId, leaveTypeId }; -}; + return { startDate, endDate, departmentId, leaveTypeId } +} -const renderLeavesReportAsCsv = async ({res, company, startDate, endDate, leaves}) => { +const renderLeavesReportAsCsv = async ({ + res, + company, + startDate, + endDate, + leaves +}) => { // Compose file name res.attachment( - `${company.name_for_machine()}_leaves_report_between_${startDate.format('YYYY_MM_DD')}_and_${endDate.format('YYYY_MM_DD')}.csv` - ); + `${company.name_for_machine()}_leaves_report_between_${startDate.format( + 'YYYY_MM_DD' + )}_and_${endDate.format('YYYY_MM_DD')}.csv` + ) // Compose result CSV header const content = [ - ['Employee', 'Department', 'Leave Type', 'Deducted days', 'From', 'To', 'Status', 'Requested On', 'Approved By', 'Comment'] - ]; + [ + 'Employee', + 'Department', + 'Leave Type', + 'Deducted days', + 'From', + 'To', + 'Status', + 'Requested On', + 'Approved By', + 'Comment' + ] + ] // ... and body - content.push(...leaves.map( - ({employeeFullName, departmentName, type, deductedDays, startDate, endDate, status, createdAt, approver, comment}) => - ([employeeFullName, departmentName, type, deductedDays, startDate, endDate, status, createdAt, approver, comment]) - )); + content.push( + ...leaves.map( + ({ + employeeFullName, + departmentName, + type, + deductedDays, + startDate, + endDate, + status, + createdAt, + approver, + comment + }) => [ + employeeFullName, + departmentName, + type, + deductedDays, + startDate, + endDate, + status, + createdAt, + approver, + comment + ] + ) + ) - const csvString = await csv.stringifyAsync( content ); + const csvString = await csv.stringifyAsync(content) - return res.send(csvString); + return res.send(csvString) } -const defaultSortAttributeForLeaveReport = 'employeeFullName'; +const defaultSortAttributeForLeaveReport = 'employeeFullName' const sortersForLeavesReport = { - employeeFullName: (a,b) => sorter(a.employeeLastName, b.employeeLastName), - departmentName: (a,b) => sorter(a.departmentName, b.departmentName), - type: (a,b) => sorter(a.type, b.type), - startDate: (a,b) => moment.utc(a.startDate).toDate().valueOf() - moment.utc(b.startDate).toDate().valueOf(), - endDate: (a,b) => moment.utc(a.endDate).toDate().valueOf() - moment.utc(b.endDate).toDate().valueOf(), - status: (a,b) => sorter(a.status, b.status), - createdAt: (a,b) => moment.utc(a.createdAt).toDate().valueOf() - moment.utc(b.createdAt).toDate().valueOf(), - approver: (a,b) => sorter(a.approver, b.approver), -}; - -const getSorterForLeaves = (attribute = defaultSortAttributeForLeaveReport) => { - return sortersForLeavesReport[attribute] || sortersForLeavesReport[defaultSortAttributeForLeaveReport]; -}; + employeeFullName: (a, b) => sorter(a.employeeLastName, b.employeeLastName), + departmentName: (a, b) => sorter(a.departmentName, b.departmentName), + type: (a, b) => sorter(a.type, b.type), + startDate: (a, b) => + moment + .utc(a.startDate) + .toDate() + .valueOf() - + moment + .utc(b.startDate) + .toDate() + .valueOf(), + endDate: (a, b) => + moment + .utc(a.endDate) + .toDate() + .valueOf() - + moment + .utc(b.endDate) + .toDate() + .valueOf(), + status: (a, b) => sorter(a.status, b.status), + createdAt: (a, b) => + moment + .utc(a.createdAt) + .toDate() + .valueOf() - + moment + .utc(b.createdAt) + .toDate() + .valueOf(), + approver: (a, b) => sorter(a.approver, b.approver) +} -router.get('/leaves/', async (req, res) => { - const actingUser = req.user; - const dbModel = req.app.get('db_model'); - const renderAsCsv = !! req.query['as-csv']; - const sortBy = req.query['sort_by'] || defaultSortAttributeForLeaveReport; - let leaves = []; +const getSorterForLeaves = (attribute = defaultSortAttributeForLeaveReport) => + sortersForLeavesReport[attribute] || + sortersForLeavesReport[defaultSortAttributeForLeaveReport] - const { startDate, endDate, departmentId, leaveTypeId } = extractParametersForLeavesReport({req, actingUser}); +router.get('/leaves/', async (req, res) => { + const actingUser = req.user + const dbModel = req.app.get('db_model') + const renderAsCsv = !!req.query['as-csv'] + const sortBy = req.query.sort_by || defaultSortAttributeForLeaveReport + let leaves = [] + + const { + startDate, + endDate, + departmentId, + leaveTypeId + } = extractParametersForLeavesReport({ req, actingUser }) try { - ({ leaves } = await fetchLeavesForLeavesReport({actingUser, dbModel, startDate, endDate, departmentId, leaveTypeId})); + const res = await fetchLeavesForLeavesReport({ + actingUser, + dbModel, + startDate, + endDate, + departmentId, + leaveTypeId + }) - leaves = leaves.sort(getSorterForLeaves(sortBy)); + leaves = res.leaves.sort(getSorterForLeaves(sortBy)) } catch (error) { console.error( - `An error occurred when user ${actingUser.id} tried to access /reports/leaves/ page: ${error} at ${error.stack}` - ); + `An error occurred when user ${ + actingUser.id + } tried to access /reports/leaves/ page: ${error} at ${error.stack}` + ) - let userErrorMessage = 'Failed to produce Leaves report. Please contact administrator.'; + let userErrorMessage = + 'Failed to produce Leaves report. Please contact administrator.' // By default go back to root report page - let redirectPath = '../'; + let redirectPath = '../' - if ( error.tom_error ) { - userErrorMessage = Exception.extract_user_error_message(error); + if (error.tom_error) { + userErrorMessage = Exception.extract_user_error_message(error) // If it is known error: stay on current page - redirectPath = './'; + redirectPath = './' } - req.session.flash_error(userErrorMessage); + req.session.flash_error(userErrorMessage) - return res.redirect_with_session(redirectPath); + return res.redirect_with_session(redirectPath) } const company = await actingUser.getCompany({ - scope: ['with_leave_types', 'with_simple_departments'], - }); + scope: ['with_leave_types', 'with_simple_departments'] + }) if (renderAsCsv) { - await renderLeavesReportAsCsv({res, company, startDate, endDate, leaves}); + await renderLeavesReportAsCsv({ res, company, startDate, endDate, leaves }) } else { res.render('report/leaves', { leaves, @@ -271,24 +363,20 @@ router.get('/leaves/', async (req, res) => { startDateStr: startDate.format('YYYY-MM-DD'), endDateStr: endDate.format('YYYY-MM-DD'), company: actingUser.company, - leaveTypes: ( - company.leave_types + leaveTypes: company.leave_types ? company.leave_types - .map(lt => lt.toJSON()) - .map(lt => ({...lt, id: `${lt.id}`})) - .sort((a,b) => sorter(a.name, b.name)) - : [] - ), - departments: ( - company.departments + .map(lt => lt.toJSON()) + .map(lt => ({ ...lt, id: `${lt.id}` })) + .sort((a, b) => sorter(a.name, b.name)) + : [], + departments: company.departments ? company.departments - .map(d => d.toJSON()) - .map(d => ({...d, id: `${d.id}`})) - .sort((a,b) => sorter(a.name, b.name)) + .map(d => d.toJSON()) + .map(d => ({ ...d, id: `${d.id}` })) + .sort((a, b) => sorter(a.name, b.name)) : [] - ), - }); + }) } -}); +}) -module.exports = router; +module.exports = router diff --git a/lib/route/requests.js b/lib/route/requests.js index 543252d78..895f15933 100644 --- a/lib/route/requests.js +++ b/lib/route/requests.js @@ -1,287 +1,392 @@ +'use strict' -"use strict"; +const express = require('express') +const router = express.Router() +const Promise = require('bluebird') +const validator = require('validator') +const _ = require('underscore') +const LeaveCollectionUtil = require('../model/leave_collection')() +const EmailTransport = require('../email') +const SlackTransport = require('../slack') -var express = require('express'), - router = express.Router(), - Promise = require('bluebird'), - validator = require('validator'), - _ = require('underscore'), - LeaveCollectionUtil = require('../model/leave_collection')(), - EmailTransport = require('../email'); - -router.get('/', function(req, res){ - const dbModel = req.app.get('db_model'); +router.get('/', (req, res) => { + const dbModel = req.app.get('db_model') Promise.join( - req.user - .promise_my_active_leaves_ever() - .then(leaves => LeaveCollectionUtil.enrichLeavesWithComments({leaves, dbModel})) - .then(leaves => LeaveCollectionUtil.promise_to_group_leaves(leaves)), - req.user - .promise_leaves_to_be_processed() - .then(leaves => LeaveCollectionUtil.enrichLeavesWithComments({leaves, dbModel})), - function(my_leaves_grouped, to_be_approved_leaves){ - res.render('requests',{ - my_leaves_grouped : my_leaves_grouped, - to_be_approved_leaves : to_be_approved_leaves, - }); - } - ); -}); + req.user + .promise_my_active_leaves_ever() + .then(leaves => + LeaveCollectionUtil.enrichLeavesWithComments({ leaves, dbModel }) + ) + .then(leaves => LeaveCollectionUtil.promise_to_group_leaves(leaves)), + req.user + .promise_leaves_to_be_processed() + .then(leaves => + LeaveCollectionUtil.enrichLeavesWithComments({ leaves, dbModel }) + ), + (my_leaves_grouped, to_be_approved_leaves) => { + res.render('requests', { + my_leaves_grouped, + to_be_approved_leaves, + title: 'Requests | TimeOff' + }) + } + ) +}) function leave_request_action(args) { - var - current_action = args.action, - leave_action_method = args.leave_action_method, - was_pended_revoke = false; - - return function(req, res){ - - var request_id = validator.trim( req.body['request'] ); - - if (!validator.isNumeric(request_id)){ - req.session.flash_error('Failed to ' + current_action); + const current_action = args.action + const leave_action_method = args.leave_action_method + let was_pended_revoke = false + + return function(req, res) { + const request_id = validator.trim(req.body.request) + + if ( + typeof request_id !== 'number' && + (!request_id || !validator.isNumeric(request_id)) + ) { + req.session.flash_error('Failed to ' + current_action) } - if ( req.session.flash_has_errors() ) { - console.error('Got validation errors on '+current_action+' request handler'); + if (req.session.flash_has_errors()) { + console.error( + 'Got validation errors on ' + current_action + ' request handler' + ) - return res.redirect_with_session('../'); + return res.redirect_with_session('../') } - Promise.try(function(){ - return req.user.promise_leaves_to_be_processed(); - }) - .then(function(leaves){ - var leave_to_process = _.find(leaves, function(leave){ - return String(leave.id) === String(request_id) - && (leave.is_new_leave() || leave.is_pended_revoke_leave()); - }); - - if (! leave_to_process) { - throw new Error('Provided ID '+request_id - +'does not correspond to any leave requests to be '+current_action - +'ed for user ' + req.user.id - ); - } - - was_pended_revoke = leave_to_process.is_pended_revoke_leave(); - - return leave_to_process[leave_action_method]({ by_user : req.user }); - }) - .then(function(processed_leave){ - return processed_leave.reload({ - include : [ - {model : req.app.get('db_model').User, as : 'user'}, - {model : req.app.get('db_model').User, as : 'approver'}, - {model : req.app.get('db_model').LeaveType, as : 'leave_type' }, - ], - }); - }) - .then(function(processed_leave){ + Promise.try(() => req.user.promise_leaves_to_be_processed()) + .then(leaves => { + const leave_to_process = _.find( + leaves, + leave => + String(leave.id) === String(request_id) && + (leave.is_new_leave() || leave.is_pended_revoke_leave()) + ) + + if (!leave_to_process) { + throw new Error( + 'Provided ID ' + + request_id + + 'does not correspond to any leave requests to be ' + + current_action + + 'ed for user ' + + req.user.id + ) + } - var Email = new EmailTransport(); + was_pended_revoke = leave_to_process.is_pended_revoke_leave() - return Email.promise_leave_request_decision_emails({ - leave : processed_leave, - action : current_action, - was_pended_revoke : was_pended_revoke, + return leave_to_process[leave_action_method]({ by_user: req.user }) }) - .then(function(){ - return Promise.resolve( processed_leave); - }); - }) - .then(function(processed_leave){ - req.session.flash_message('Request from '+processed_leave.user.full_name() - +' was processed'); - - return res.redirect_with_session('../'); - }) - .catch(function(error){ - console.error('An error occurred when attempting to '+current_action - +' leave request '+request_id+' by user '+req.user.id+' Error: '+error - ); - req.session.flash_error('Failed to '+current_action); - return res.redirect_with_session('../'); - }); - }; + .then(processed_leave => + processed_leave.reload({ + include: [ + { model: req.app.get('db_model').User, as: 'user' }, + { model: req.app.get('db_model').User, as: 'approver' }, + { model: req.app.get('db_model').LeaveType, as: 'leave_type' } + ] + }) + ) + .then(processed_leave => { + const Email = new EmailTransport() + + return ( + Email.promise_leave_request_decision_emails({ + leave: processed_leave, + action: current_action, + was_pended_revoke + }) + .then(() => Promise.resolve(processed_leave)) + // Fail silently for the user and track the error for the administrator. + .catch(error => { + console.error( + 'Failed to send email for the leave request: ' + error, + error.stack + ) + return Promise.resolve(processed_leave) + }) + ) + }) + .then(processed_leave => { + const Slack = new SlackTransport() + + return ( + Slack.promise_leave_request_decision_slacks({ + leave: processed_leave, + action: current_action, + was_pended_revoke + }) + .then(() => Promise.resolve(processed_leave)) + // Fail silently for the user and track the error for the administrator. + .catch(error => { + console.error( + 'Failed to send slack notification for the leave request: ' + + error, + error.stack + ) + return Promise.resolve(processed_leave) + }) + ) + }) + .then(processed_leave => { + req.session.flash_message( + 'Request from ' + processed_leave.user.full_name() + ' was processed' + ) + return res.redirect_with_session('../') + }) + .catch(error => { + console.error( + 'An error occurred when attempting to ' + + current_action + + ' leave request ' + + request_id + + ' by user ' + + req.user.id + + ' Error: ' + + error, + error.stack + ) + req.session.flash_error('Failed to ' + current_action) + return res.redirect_with_session('../') + }) + } } router.post( '/reject/', leave_request_action({ - action : 'reject', - leave_action_method : 'promise_to_reject', + action: 'reject', + leave_action_method: 'promise_to_reject' }) -); +) router.post( '/approve/', leave_request_action({ - action : 'approve', - leave_action_method : 'promise_to_approve', - }) -); - -router.post('/cancel/', function(req, res){ - - var request_id = validator.trim( req.body['request'] ); - - Promise.try(function(){ - return req.user.promise_cancelable_leaves() - }) - .then(function(leaves){ - var leave_to_cancel = _.find(leaves, function(leave){ - return String(leave.id) === String(request_id); - }); - - if ( ! leave_to_cancel ) { - throw new Error('Given leave request is not amoung those current user can cancel'); - } - - return Promise.resolve(leave_to_cancel); - }) - .then(function(leave){ - return leave.promise_to_cancel() - .then(function(){ return Promise.resolve(leave)}); + action: 'approve', + leave_action_method: 'promise_to_approve' }) - .then(function(leave){ - return leave.reload({ - include : [ - {model : req.app.get('db_model').User, as : 'user'}, - {model : req.app.get('db_model').User, as : 'approver'}, - {model : req.app.get('db_model').LeaveType, as : 'leave_type' }, - ], - }); - }) - .then(function(leave){ +) + +router.post('/cancel/', (req, res) => { + const request_id = validator.trim(req.body.request) + + Promise.try(() => req.user.promise_cancelable_leaves()) + .then(leaves => { + const leave_to_cancel = _.find( + leaves, + leave => String(leave.id) === String(request_id) + ) + + if (!leave_to_cancel) { + throw new Error( + 'Given leave request is not amoung those current user can cancel' + ) + } - var Email = new EmailTransport(); + return Promise.resolve(leave_to_cancel) + }) + .then(leave => leave.promise_to_cancel().then(() => Promise.resolve(leave))) + .then(leave => + leave.reload({ + include: [ + { model: req.app.get('db_model').User, as: 'user' }, + { model: req.app.get('db_model').User, as: 'approver' }, + { model: req.app.get('db_model').LeaveType, as: 'leave_type' } + ] + }) + ) + .then(leave => { + const Email = new EmailTransport() - return Email.promise_leave_request_cancel_emails({ - leave : leave, + return ( + Email.promise_leave_request_cancel_emails({ + leave + }) + .then(() => Promise.resolve(leave)) + // Fail silently for the user and track the error for the administrator. + .catch(error => { + console.error( + 'Failed to send email for the leave request: ' + error, + error.stack + ) + return Promise.resolve(leave) + }) + ) }) - .then(function(){ - return Promise.resolve(leave); - }); - }) - .then(function(){ - req.session.flash_message('The leave request was canceled'); - }) - .catch(function(error){ - console.log('An error occurred: '+error); - req.session.flash_error('Failed to cancel leave request'); - }) - .finally(function(){ - return res.redirect_with_session('/requests/'); - }); -}); + .then(leave => { + const Slack = new SlackTransport() -router.post( - '/revoke/', - function(req, res){ - var request_id = validator.trim( req.body['request'] ); + return ( + Slack.promise_leave_request_cancel_slacks({ + leave + }) + .then(() => Promise.resolve(leave)) + // Fail silently for the user and track the error for the administrator. + .catch(error => { + console.error( + 'Failed to send slack notification for the leave request: ' + + error, + error.stack + ) + return Promise.resolve(leave) + }) + ) + }) + .then(leave => { + req.session.flash_message('The leave request was canceled') + }) + .catch(error => { + console.log('An error occurred: ' + error, error.stack) + req.session.flash_error('Failed to cancel leave request') + }) + .finally(() => res.redirect_with_session('/requests/')) +}) - // TODO NOTE revoke action now could be made from more then one place, - // so make sure that user is redirected to correct place +router.post('/revoke/', (req, res) => { + const request_id = validator.trim(req.body.request) - if (!validator.isNumeric(request_id)){ - req.session.flash_error('Failed to revoke leave request'); - } + // TODO NOTE revoke action now could be made from more then one place, + // so make sure that user is redirected to correct place - if ( req.session.flash_has_errors() ) { - console.log( - 'Got validation errors when revoking leave request for user ' + req.user.id - ); + if ( + typeof request_id !== 'number' && + (!request_id || !validator.isNumeric(request_id)) + ) { + req.session.flash_error('Failed to revoke leave request') + } - return res.redirect_with_session('../'); - } + if (req.session.flash_has_errors()) { + console.log( + 'Got validation errors when revoking leave request for user ' + + req.user.id + ) - Promise - // Get the Leave object for submitted ID - .try(() => req.app.get('db_model').Leave.findOne({ where : { id : request_id }})) + return res.redirect_with_session('../') + } - // Ensure that current user can act on this Leave object - .then(requested_leave => { + Promise + // Get the Leave object for submitted ID + .try(() => + req.app.get('db_model').Leave.findOne({ where: { id: request_id } }) + ) + + // Ensure that current user can act on this Leave object + .then(requested_leave => { + // Case when requested Leave is originated from current user + if (String(requested_leave.user_id) === String(req.user.id)) { + return Promise.resolve(requested_leave) + } - // Case when requested Leave is originated from current user - if ( String(requested_leave.userId) === String(req.user.id) ) { - return Promise.resolve( requested_leave ) + // Case when requested Leave is originated from one of employees + // current user can manage + return req.user.promise_users_I_can_manage().then(users => { + if (users.find(u => String(u.id) === String(requested_leave.user_id))) { + return Promise.resolve(requested_leave) } - // Case when requested Leave is originated from one of employees - // current user can manage - return req.user - .promise_users_I_can_manage() - .then(users => { - if ( users.find(u => String(u.id) === String(requested_leave.userId)) ) { - return Promise.resolve( requested_leave ); - } - - return Promise.resolve(); - }); + return Promise.resolve() }) + }) - .then(leave_to_process => { + .then(leave_to_process => { + // Ensure that Leave is in status from it could be revoked + if (!leave_to_process) { + throw new Error( + 'Provided ID ' + + request_id + + ' does not correspond to any leave requests to be revoked by user ' + + req.user.id + ) + } - // Ensure that Leave is in status from it could be revoked - if (! leave_to_process) { - throw new Error('Provided ID '+request_id - +' does not correspond to any leave requests to be revoked by user ' - + req.user.id - ); - } + // Do the action + return leave_to_process.promise_to_revoke() + }) - // Do the action - return leave_to_process.promise_to_revoke(); + // Ensure that Leave object has all content necessary for sending emails + .then(processed_leave => + processed_leave.reload({ + include: [ + { model: req.app.get('db_model').User, as: 'user' }, + { model: req.app.get('db_model').User, as: 'approver' }, + { model: req.app.get('db_model').LeaveType, as: 'leave_type' } + ] }) + ) - // Ensure that Leave object has all content necessary for sending emails - .then(processed_leave => processed_leave.reload({ - include : [ - {model : req.app.get('db_model').User, as : 'user'}, - {model : req.app.get('db_model').User, as : 'approver'}, - {model : req.app.get('db_model').LeaveType, as : 'leave_type' }, - ], - })) + // Send relevant emails + .then(processed_leave => { + const Email = new EmailTransport() - // Send relevant emails - .then(processed_leave => { + return ( + Email.promise_leave_request_revoke_emails({ + leave: processed_leave + }) + .then(() => Promise.resolve(processed_leave)) + // Fail silently for the user and track the error for the administrator. + .catch(error => { + console.error( + 'Failed to send email for the leave request: ' + error, + error.stack + ) + return Promise.resolve(processed_leave) + }) + ) + }) - var Email = new EmailTransport(); + // Send relevant slacks + .then(processed_leave => { + console.log('Processing SLACK') + const Slack = new SlackTransport() - return Email.promise_leave_request_revoke_emails({ - leave : processed_leave, + return ( + Slack.promise_leave_request_revoke_slacks({ + leave: processed_leave }) - .then(function(){ - return Promise.resolve(processed_leave); - }); - }) + .then(() => Promise.resolve(processed_leave)) + // Fail silently for the user and track the error for the administrator. + .catch(error => { + console.error( + 'Failed to send slack notification for the leave request: ' + + error, + error.stack + ) + return Promise.resolve(processed_leave) + }) + ) + }) - // Deal with next page: where to land and what to show - .then(processed_leave => { - req.session.flash_message( - 'You have requested leave to be revoked. ' - + ( - processed_leave.is_auto_approve() + // Deal with next page: where to land and what to show + .then(processed_leave => { + req.session.flash_message( + 'You have requested leave to be revoked. ' + + (processed_leave.is_auto_approve() ? '' - : 'Your supervisor needs to approve it' - ) - ); + : 'Your supervisor needs to approve it') + ) - return res.redirect_with_session('../'); - }) + return res.redirect_with_session('../') + }) - // Deal with issues if any occurs - .catch(error => { - console.error('An error occurred when attempting to revoke leave request ' - +request_id+' by user '+req.user.id+' Error: '+error - ); - req.session.flash_error('Failed to revoke leave request'); - return res.redirect_with_session('../'); - }); - } -); + // Deal with issues if any occurs + .catch(error => { + console.error( + 'An error occurred when attempting to revoke leave request ' + + request_id + + ' by user ' + + req.user.id + + ' Error: ', + error, + error.stack + ) + req.session.flash_error('Failed to revoke leave request') + return res.redirect_with_session('../') + }) +}) -module.exports = router; +module.exports = router diff --git a/lib/route/settings.js b/lib/route/settings.js index 77b1115ac..13c39bfbc 100644 --- a/lib/route/settings.js +++ b/lib/route/settings.js @@ -2,666 +2,747 @@ * * */ -"use strict"; - -const - express = require('express'), - router = express.Router(), - validator = require('validator'), - Promise = require('bluebird'), - moment = require('moment'), - moment_tz = require('moment-timezone'), - config = require('../config'), - Exception = require('../error'), - {extractUserErrorMessage, extractSystemErrorMessage} = Exception, - CompanyRemover = require('../model/company/remover'), - {calculateCarryOverAllowance} = require('../model/calculateCarryOverAllowance'), - uuidv4 = require('uuid/v4'), - _ = require('underscore'); - -const - CompanyExporter = require('../model/company/exporter'); -const { sorter } = require('../util'); +'use strict' + +const express = require('express') +const router = express.Router() +const validator = require('validator') +const Promise = require('bluebird') +const moment = require('moment') +const moment_tz = require('moment-timezone') +const config = require('../config') +const Exception = require('../error') +const { extractUserErrorMessage, extractSystemErrorMessage } = Exception +const CompanyRemover = require('../model/company/remover') +const { + calculateCarryOverAllowance +} = require('../model/calculateCarryOverAllowance') +const uuidv4 = require('uuid/v4') +const _ = require('underscore') + +const CompanyExporter = require('../model/company/exporter') +const { sorter } = require('../util') // Make sure that current user is authorized to deal with settings -router.all(/.*/, require('../middleware/ensure_user_is_admin')); - +router.all(/.*/, require('../middleware/ensure_user_is_admin')) router.get('/general/', async (req, res) => { - res.locals.custom_java_script.push( - '/js/settings_general.js' - ); - - res.locals.custom_css.push( - '/css/bootstrap-datepicker3.standalone.css' - ); - - const company = await req.user.getCompany({ - scope: ['with_leave_types'], - }); - - const schedule = await company.promise_schedule(); - - res.render('general_settings', { - company, - schedule, - countries: config.get('countries'), - timezones_available: moment_tz.tz.names(), - carryOverOptions: getAvailableCarriedOverOptions(), - yearCurrent: moment.utc().year(), - yearPrev: moment.utc().add(-1, 'y').year(), - leave_types: company.leave_types.sort((a, b) => sorter(a.name, b.name)), - }); -}); - -router.post('/company/', function(req, res){ - - const - name = validator.trim(req.body['name']), - country_code = validator.trim(req.body['country']), - date_format = validator.trim(req.body['date_format']), - timezone = validator.trim(req.body['timezone']), - carriedOverDays = validator.trim(req.body['carry_over']), - share_all_absences= validator.toBoolean( - req.body['share_all_absences'] - ), - isTeamViewHidden = validator.toBoolean( - req.body['is_team_view_hidden'] - ); - - if (!validator.isAlphanumeric(country_code)){ - req.session.flash_error('Country should contain only letters and numbers'); + res.locals.custom_java_script.push('/js/settings_general.js') + + res.locals.custom_css.push('/css/bootstrap-datepicker3.standalone.css') + + const model = req.app.get('db_model') + + req.user + .getCompany({ + scope: ['with_leave_types', 'with_bank_holidays'], + order: [ + [{ model: model.BankHoliday, as: 'bank_holidays' }, 'date'], + [{ model: model.LeaveType, as: 'leave_types' }, 'name'] + ] + }) + .then(company => ({ + company, + schedule: company.promise_schedule() + })) + .then(({ company, schedule }) => { + res.render('general_settings', { + company, + leave_types: company.leave_types, + schedule, + countries: config.get('countries'), + timezones_available: moment_tz.tz.names(), + title: 'Settings | TimeOff', + carryOverOptions: getAvailableCarriedOverOptions(), + yearCurrent: moment.utc().year(), + yearPrev: moment + .utc() + .add(-1, 'y') + .year() + }) + }) +}) + +router.post('/company/', (req, res) => { + const name = req.body.name && validator.trim(req.body.name) + const country_code = req.body.country && validator.trim(req.body.country) + const date_format = + req.body.date_format && validator.trim(req.body.date_format) + const timezone = req.body.timezone && validator.trim(req.body.timezone) + const carriedOverDays = + req.body.carry_over && validator.trim(req.body.carry_over) + const share_all_absences = + (req.body.share_all_absences && + validator.toBoolean(req.body.share_all_absences)) || + false + const isTeamViewHidden = + (req.body.is_team_view_hidden && + validator.toBoolean(req.body.is_team_view_hidden)) || + false + + if (!validator.isAlphanumeric(country_code)) { + req.session.flash_error('Country should contain only letters and numbers') } - if ( ! moment_tz.tz.names().find(tz_str => tz_str === timezone) ) { - req.session.flash_error('Time zone is unknown'); + if (!moment_tz.tz.names().find(tz_str => tz_str === timezone)) { + req.session.flash_error('Time zone is unknown') } - if ( ! validator.isNumeric(carriedOverDays)) { - req.session.flash_error('Carried over allowance has to be a number'); + if (!validator.isNumeric(carriedOverDays)) { + req.session.flash_error('Carried over allowance has to be a number') } // In case of validation error redirect back to edit form - if ( req.session.flash_has_errors() ) { - return res.redirect_with_session('/settings/general/'); + if (req.session.flash_has_errors()) { + return res.redirect_with_session('/settings/general/') } - req.user.getCompany() - - // Validate provided date format - .then(function(company){ + req.user + .getCompany() - if ( _.indexOf( company.get_available_date_formats(), date_format ) < 0 ) { - var error_msg = 'Unknown date format was provided'; - req.session.flash_error(error_msg); - throw new Error(error_msg); - } + // Validate provided date format + .then(company => { + if (_.indexOf(company.get_available_date_formats(), date_format) < 0) { + const error_msg = 'Unknown date format was provided' + req.session.flash_error(error_msg) + throw new Error(error_msg) + } - return Promise.resolve( company ); - }) + return Promise.resolve(company) + }) - .then(company => { - company.name = name; - company.country = country_code; - company.share_all_absences= share_all_absences; - company.date_format = date_format; - company.timezone = timezone; - company.carry_over = carriedOverDays; - company.is_team_view_hidden = isTeamViewHidden; + .then(company => { + company.name = name + company.country = country_code + company.share_all_absences = share_all_absences + company.date_format = date_format + company.timezone = timezone + company.carry_over = carriedOverDays + company.is_team_view_hidden = isTeamViewHidden - return company.save(); - }) - .then(function(){ - req.session.flash_message('Company was successfully updated'); - return res.redirect_with_session('/settings/general/'); - }) - .catch(function(error){ - console.log( - `An error occurred when trying to edit company for user ${req.user.id}: ${error} at ${error.stack}` - ); + return company.save() + }) + .then(() => { + req.session.flash_message('Company was successfully updated') + return res.redirect_with_session('/settings/general/') + }) + .catch(error => { + console.log( + `An error occurred when trying to edit company for user ${ + req.user.id + }: ${error}`, + error.stack + ) - req.session.flash_error( - 'Failed to update company details, please contact customer service' - ); + req.session.flash_error( + 'Failed to update company details, please contact customer service' + ) - return res.redirect_with_session('/settings/general/'); - }); -}); + return res.redirect_with_session('/settings/general/') + }) +}) router.post('/carryOverUnusedAllowance/', (req, res) => { req.user .getCompany() .then(company => company.getUsers()) - .then(users => calculateCarryOverAllowance({users})) - .then(() => req.session.flash_message( - 'Unused allowance was successfully carried over' - )) + .then(users => calculateCarryOverAllowance({ users })) + .then(() => + req.session.flash_message( + 'Unused allowance was successfully carried over' + ) + ) .catch(error => { - const logMarker = uuidv4(); + const logMarker = uuidv4() console.log( - `[${logMarker}] An error occurred while trying to carry over unused allowance by user ${req.user.id}: ${error} at ${error.stack}` - ); + `[${logMarker}] An error occurred while trying to carry over unused allowance by user ${ + req.user.id + }: ${error} at ${error.stack}` + ) req.session.flash_error( `Failed to carry over unused allowances, please contact customer service and provide incident ID: ${logMarker}` - ); + ) }) - .finally(() => res.redirect_with_session('/settings/general/')); -}); - -router.post('/schedule/', function(req, res){ + .finally(() => res.redirect_with_session('/settings/general/')) +}) - var company, schedule, user, - model = req.app.get('db_model'); +router.post('/schedule/', (req, res) => { + let company + let schedule + let user + const model = req.app.get('db_model') - req.user.getCompany() + req.user + .getCompany() // Obtain scheduler object - .then(function(c){ - company = c; + .then(c => { + company = c - if ( ! req.body.user_id) { + if (!req.body.user_id) { // We are dealing with company wide schedule: easy - return company.promise_schedule(); + return company.promise_schedule() } // Rest is attempt to fetch user specific schedule for given user - return company.getUsers({ - where : { - id : validator.trim( req.body.user_id ), - } - }) - .then(function(u){ - user = u.pop(); + return company + .getUsers({ + where: { + id: validator.trim(req.body.user_id) + } + }) + .then(u => { + user = u.pop() - if ( ! user) { - throw new Error( - "Failed to find user "+req.body.user_id+" for company "+company.id - ); - } + if (!user) { + throw new Error( + 'Failed to find user ' + + req.body.user_id + + ' for company ' + + company.id + ) + } - return user.promise_schedule_I_obey(); - }) - .then(function(sch){ - if (sch.is_user_specific()) { - // User specific schedule exists in database - return Promise.resolve(sch); - } + return user.promise_schedule_I_obey() + }) + .then(sch => { + if (sch.is_user_specific()) { + // User specific schedule exists in database + return Promise.resolve(sch) + } - // No user specific schedule in database: create in memory default instance - return model.Schedule - .promise_to_build_default_for({ user_id : user.id }); - }); + // No user specific schedule in database: create in memory default instance + return model.Schedule.promise_to_build_default_for({ + user_id: user.id + }) + }) }) // Update schedule object - .then(function(sch){ - schedule = sch; - - ['monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday', 'sunday'] - .forEach(function(day){ schedule.set(day, req.body[day]) }); + .then(sch => { + schedule = sch + ;[ + 'monday', + 'tuesday', + 'wednesday', + 'thursday', + 'friday', + 'saturday', + 'sunday' + ].forEach(day => { + schedule.set(day, req.body[day]) + }) - if (schedule.is_user_specific() && _.has(req.body, 'revoke_user_specific_schedule') ) { - return schedule.destroy(); + if ( + schedule.is_user_specific() && + _.has(req.body, 'revoke_user_specific_schedule') + ) { + return schedule.destroy() } else { - return schedule.save(); + return schedule.save() } }) // Action is successfully done - .then(function(){ - req.session.flash_message( schedule.is_user_specific() - ? 'Schedule for user was saved' - : 'Schedule for company was saved' - ); + .then(() => { + req.session.flash_message( + schedule.is_user_specific() + ? 'Schedule for user was saved' + : 'Schedule for company was saved' + ) }) // Action failed - .catch(function(error){ - console.error('An error occurred while saving schedule: ' + error); - req.session.flash_error( schedule.is_user_specific() - ? 'Failed to save user schedule' - : 'Failed to save company schedule' - ); - + .catch(error => { + console.error( + 'An error occurred while saving schedule: ' + error, + error.stack + ) + req.session.flash_error( + schedule.is_user_specific() + ? 'Failed to save user schedule' + : 'Failed to save company schedule' + ) }) // Depending on context redirect user to particular page - .finally(function(){ - res.redirect_with_session(schedule.is_user_specific() - ? (user ? '/users/edit/'+user.id+'/schedule/' : '/users/') - : '/settings/general/' - ); - }); -}); - -router.post('/leavetypes', function(req, res){ + .finally(() => { + res.redirect_with_session( + schedule.is_user_specific() + ? user + ? '/users/edit/' + user.id + '/schedule/' + : '/users/' + : '/settings/general/' + ) + }) +}) - var model = req.app.get('db_model'); +router.post('/leavetypes', (req, res) => { + const model = req.app.get('db_model') req.user - .get_company_with_all_leave_types() - .then(function(company){ - - var promise_new_leave_type = Promise.resolve(1); - - if (validator.trim(req.body['name__new'])) { - var attributes = get_and_validate_leave_type({ - req : req, - suffix : 'new', - item_name : 'New Leave Type' - }); - attributes.companyId = company.id; - promise_new_leave_type = model.LeaveType.create(attributes); + .then(company => { + let promise_new_leave_type = Promise.resolve(1) + + if (req.body.name__new && validator.trim(req.body.name__new)) { + const attributes = get_and_validate_leave_type({ + req, + suffix: 'new', + item_name: 'New Leave Type' + }) + attributes.company_id = company.id + promise_new_leave_type = model.LeaveType.create(attributes) } return Promise.all([ promise_new_leave_type, - _.map( - company.leave_types, - function(leave_type){ - - let attributes = get_and_validate_leave_type({ - req : req, - suffix : leave_type.id, - item_name : leave_type.name, - }); - - // Update leave type only if there are attributes submitted for it - return attributes - ? leave_type.updateAttributes(attributes) - : Promise.resolve(1); - } - - ) // End of map that create leave type update promises - ]); + _.map(company.leave_types, (leave_type, index) => { + const attributes = get_and_validate_leave_type({ + req, + suffix: leave_type.id, + item_name: leave_type.name + }) + + // Update leave type only if there are attributes submitted for it + return attributes ? leave_type.update(attributes) : Promise.resolve(1) + }) // End of map that create leave type update promises + ]) }) .then(() => { - req.session.flash_message('Changes to leave types were saved'); - return res.redirect_with_session('/settings/general/'); + req.session.flash_message('Changes to leave types were saved') + return res.redirect_with_session('/settings/general/') }) .catch(error => { console.error( - 'An error occurred when trying to edit Leave types by user '+req.user.id - + ' : ' + error - ); - - if (error.hasOwnProperty('user_message')) { - req.session.flash_error( error.user_message ); + 'An error occurred when trying to edit Leave types by user ' + + req.user.id + + ' : ', + error, + error.stack + ) + + if (error.user_message) { + req.session.flash_error(error.user_message) } req.session.flash_error( 'Failed to update leave types details, please contact customer service' - ); + ) - return res.redirect_with_session('/settings/general/'); - }); -}); - -router.post('/leavetypes/delete/:leave_type_id/', function(req, res){ + return res.redirect_with_session('/settings/general/') + }) +}) - var leave_type_id = req.params['leave_type_id']; +router.post('/leavetypes/delete/:leave_type_id/', (req, res) => { + const leave_type_id = req.params.leave_type_id - var model = req.app.get('db_model'); + const model = req.app.get('db_model') - if (!validator.isInt(leave_type_id)) { - console.log(`User ${req.user.id} submitted non-int leave_type id [${leave_type_id}]`); + if ( + typeof leave_type_id !== 'number' && + (!leave_type_id || !validator.isInt(leave_type_id)) + ) { + console.error( + 'User ' + + req.user.id + + ' submited non-int leave_type number ' + + leave_type_id + ) - req.session.flash_error('Cannot remove leave_type: wrong parameters'); + req.session.flash_error('Cannot remove leave_type: wrong parameters') - return res.redirect_with_session('/settings/general/'); - } + return res.redirect_with_session('/settings/general/') + } - req.user.getCompany({ - include : [{ - model : model.LeaveType, - as : 'leave_types', - include : [{model: model.Leave, as: 'leaves'}], - }], - order : [[{model: model.LeaveType, as : 'leave_types'}, 'name' ]], + req.user + .getCompany({ + include: [ + { + model: model.LeaveType, + as: 'leave_types', + include: [{ model: model.Leave, as: 'leaves' }] + } + ], + order: [[{ model: model.LeaveType, as: 'leave_types' }, 'name']] }) - .then(function(company){ - var leave_type_to_remove = company.leave_types.find( lt => String(lt.id) === String(leave_type_id) ); - - // Check if user specify valid department number - if (! leave_type_to_remove) { - - req.session.flash_error('Cannot remove leave type: wronge parameters'); - - throw new Error( - 'User '+req.user.id+' tried to remove non-existing leave type number' - +leave_type_id+' out of '+company.leave_types.length - ); - + .then(company => { + const leave_type_to_remove = company.leave_types.find( + lt => String(lt.id) === String(leave_type_id) + ) + + // Check if user specify valid department number + if (!leave_type_to_remove) { + req.session.flash_error('Cannot remove leave type: wronge parameters') + + throw new Error( + 'User ' + + req.user.id + + ' tried to remove non-existing leave type number' + + leave_type_id + + ' out of ' + + company.leave_types.length + ) // Check if there exist leaves for current type and if so, do not remove it - } else if (leave_type_to_remove.leaves.length > 0) { + } else if (leave_type_to_remove.leaves.length > 0) { + req.session.flash_error('Cannot remove leave type: type is in use') - req.session.flash_error('Cannot remove leave type: type is in use'); - - throw new Error('Failed to remove Leave type because it is in used.'); - } + throw new Error('Failed to remove Leave type because it is in used.') + } - return leave_type_to_remove.destroy(); + return leave_type_to_remove.destroy() }) - .then(function(){ - req.session.flash_message('Leave type was successfully removed'); - return res.redirect_with_session('/settings/general/'); + .then(() => { + req.session.flash_message('Leave type was successfully removed') + return res.redirect_with_session('/settings/general/') }) - .catch(function(error){ - console.error( - 'An error occurred when trying to remove leave type by user' + req.user.id - + ' : ' + error - ); + .catch(error => { + console.error( + 'An error occurred when trying to remove leave type by user' + + req.user.id + + ' : ' + + error, + error.stack + ) - req.session.flash_error( - 'Failed to remove Leave Type' - ); + req.session.flash_error('Failed to remove Leave Type') - return res.redirect_with_session('/settings/general/'); - }); -}); + return res.redirect_with_session('/settings/general/') + }) +}) router.get('/company/integration-api/', (req, res) => { - req.user - .getCompany() - .then(company => res.render('settings_company_integration_api', { - company, - })); -}); + req.user.getCompany().then(company => + res.render('settings_company_integration_api', { + company + }) + ) +}) router.post('/company/integration-api/', (req, res) => { - const featureIsEnabled = validator.toBoolean(req.body.integration_api_enabled); + const featureIsEnabled = validator.toBoolean(req.body.integration_api_enabled) - let action = req.user.getCompany(); + let action = req.user.getCompany() action = action.then(company => { - company.set('integration_api_enabled', featureIsEnabled); - return company.save(); - }); + company.set('integration_api_enabled', featureIsEnabled) + return company.save() + }) if (req.body.regenerate_token) { - action = action.then( company => company.regenerateIntegrationApiToken() ); + action = action.then(company => company.regenerateIntegrationApiToken()) } action = action.then(() => { - req.session.flash_message('Settings were saved'); + req.session.flash_message('Settings were saved') - return res.redirect_with_session('./'); - }); + return res.redirect_with_session('./') + }) - action = action.catch(error => { - console.log(`Failed to save Integration API configuration, reason: ${ extractSystemErrorMessage(error) }`); + action.catch(error => { + console.log( + `Failed to save Integration API configuration, reason: ${extractSystemErrorMessage( + error + )}` + ) req.session.flash_error( - `Failed to save settings. ${ extractUserErrorMessage(error) }` - ); + `Failed to save settings. ${extractUserErrorMessage(error)}` + ) - return res.redirect_with_session('./'); + return res.redirect_with_session('./') }) -}); +}) -router.get('/company/authentication/', function(req, res){ - - req.user - .getCompany() - .then(function(company){ - res.render('settings_company_authentication', { - company : company, - ldap_config : company.get('ldap_auth_config'), - }); - }); -}); - -router.post('/company/authentication/', function(req, res){ +router.get('/company/authentication/', (req, res) => { + req.user.getCompany().then(company => { + res.render('settings_company_authentication', { + company, + ldap_config: company.get('ldap_auth_config'), + title: 'Settings - Authentication | TimeOff' + }) + }) +}) +router.post('/company/authentication/', (req, res) => { req.user .getCompany() - .then(function(company){ - - var parameters = get_and_validate_ldap_auth_configuration({ - req : req, - }); + .then(company => { + const parameters = get_and_validate_ldap_auth_configuration({ + req + }) // Updaye in memory Company object but do not save changes until new LDAP // configuration checked against current user // (this is needed to prevent situation when admin by lock herself out) - company.set('ldap_auth_config', parameters.ldap_config); - company.setDataValue('ldap_auth_enabled', parameters.ldap_auth_enabled); + company.set('ldap_auth_config', parameters.ldap_config) + company.setDataValue('ldap_auth_enabled', parameters.ldap_auth_enabled) - var ldap_server = company.get_ldap_server(); + const ldap_server = company.get_ldap_server() // Handle event based errors from ldapauth-fork - var ldapError = ""; - ldap_server.on('error', function(err) { - ldapError = err; - }); + let ldapError = '' + ldap_server.on('error', err => { + ldapError = err + }) - var auth_func = function(email, password) { - return new Promise(function(resolve, reject) { + function auth_func(email, password) { + return new Promise((resolve, reject) => { // Wait one second before cheking for event based errors setTimeout(() => { if (ldapError) { - reject(ldapError); + reject(ldapError) } - }, 1000); + }, 1000) - ldap_server.authenticate(email, password, function(error, user) { + ldap_server.authenticate(email, password, (error, user) => { if (error) { - reject(error); + reject(error) } else { - resolve(user); + resolve(user) } - }); - }); - }; + }) + }) + } - return auth_func(req.user.email, parameters.password_to_check) - .then(function(){ - return company.save(); - }) - .catch(function(error){ - error = new Error( - "Failed to validate new LDAP settings with provided current user password. "+error - ); - error.show_to_user = true; - throw error; - }); + return auth_func(req.user.email, parameters.password_to_check) + .then(() => company.save()) + .catch(error => { + error = new Error( + 'Failed to validate new LDAP settings with provided current user password. ' + + error, + error.stack + ) + error.show_to_user = true + throw error + }) }) - .then(function(){ - if ( req.session.flash_has_errors() ) { - return res.redirect_with_session('/settings/company/authentication/'); + .then(() => { + if (req.session.flash_has_errors()) { + return res.redirect_with_session('/settings/company/authentication/') } else { - req.session.flash_message('LDAP configuration was updated'); - return res.redirect_with_session('/settings/company/authentication/'); + req.session.flash_message('LDAP configuration was updated') + return res.redirect_with_session('/settings/company/authentication/') } }) - .catch(function(error){ + .catch(error => { console.error( - "An error occured while trying to update LDAP configuration: %s", error - ); + 'An error occured while trying to update LDAP configuration: %s', + error, + error.stack + ) req.session.flash_error( 'Failed to update LDAP configuration. ' + - ( error.show_to_user ? error : 'Please contact customer service') - ); + (error.show_to_user ? error : 'Please contact customer service') + ) - return res.redirect_with_session('/settings/company/authentication/'); - }); -}); + return res.redirect_with_session('/settings/company/authentication/') + }) +}) function get_and_validate_leave_type(args) { - let - req = args.req, - suffix = args.suffix, - item_name = args.item_name; + const req = args.req + const suffix = args.suffix + const item_name = args.item_name // Get user parameters - let - name = validator.trim(req.body['name__'+suffix]), - color = validator.trim(req.body['color__'+suffix]) || 'leave_type_color_1', - limit = validator.trim(req.body['limit__'+suffix]) || 0, - first_record = validator.trim(req.body['first_record']) || 0, - use_allowance = validator.toBoolean( - req.body['use_allowance__'+suffix] - ), - auto_approve = validator.toBoolean( - req.body['auto_approve__'+suffix] - ); + const name = + req.body['name__' + suffix] && validator.trim(req.body['name__' + suffix]) + const color = + (req.body['color__' + suffix] && + validator.trim(req.body['color__' + suffix])) || + 'leave_type_color_1' + const limit = + (req.body['limit__' + suffix] && + validator.trim(req.body['limit__' + suffix])) || + 0 + const first_record = + (req.body.first_record && validator.trim(req.body.first_record)) || 0 + const use_allowance = + (req.body['use_allowance__' + suffix] && + validator.toBoolean(req.body['use_allowance__' + suffix])) || + false + const auto_approve = + (req.body['auto_approve__' + suffix] && + validator.toBoolean(req.body['auto_approve__' + suffix])) || + false // If no name for leave type was provided: do nothing - treat case // as no need to update the leave type - if ( ! name ) { - return false; + if (!name) { + return false } // VPP TODO move that into resusable component - let throw_user_error = function(message){ - let error = new Error(message); - error.user_message = message; - throw error; - }; + function throw_user_error(message) { + const error = new Error(message) + error.user_message = message + throw error + } // Validate provided parameters - if ( ! validator.matches(color, /^leave_type_color_\d+$/)) { - throw_user_error( 'New color for '+item_name+' should be valid css class' ); + if (!validator.matches(color, /^leave_type_color_\d+$/)) { + throw_user_error( + 'New color for ' + item_name + ' should be valid css class' + ) } - if ( ! validator.isNumeric(limit) ){ - throw_user_error( 'New limit for '+item_name+' should be a valide number' ); - - } else if ( limit < 0) { - throw_user_error( 'New limit for '+item_name+' should be positive number or 0' ); + if (typeof limit !== 'number' && (!limit || !validator.isNumeric(limit))) { + throw_user_error( + 'New limit for ' + item_name + ' should be a valide number' + ) + } else if (limit < 0) { + throw_user_error( + 'New limit for ' + item_name + ' should be positive number or 0' + ) } return { - name : name, - color : color, - use_allowance : use_allowance, - auto_approve : auto_approve, - limit : limit, - sort_order : ( (first_record && (String(first_record)===String(suffix))? 1 : 0) ), - }; + name, + color, + use_allowance, + auto_approve, + limit, + sort_order: first_record && String(first_record) === String(suffix) ? 1 : 0 + } } -function get_and_validate_ldap_auth_configuration(args) { - var req = args.req; - +function get_and_validate_ldap_auth_configuration({ req }) { // Get parameters // - var url = validator.trim(req.body['url']), - binddn = validator.trim(req.body['binddn']), - bindcredentials = validator.trim(req.body['bindcredentials']), - searchbase = validator.trim(req.body['searchbase']), - ldap_auth_enabled = validator.toBoolean(req.body['ldap_auth_enabled']), - allow_unauthorized_cert = validator.toBoolean(req.body['allow_unauthorized_cert']), - + const url = validator.trim(req.param('url') + '') + const binddn = validator.trim(req.param('binddn') + '') + const bindcredentials = validator.trim(req.param('bindcredentials') + '') + const searchbase = validator.trim(req.param('searchbase') + '') + const searchfilter = validator.trim(req.param('searchfilter') + '') + const ldap_auth_enabled = validator.toBoolean( + req.param('ldap_auth_enabled') + '' + ) + const allow_unauthorized_cert = validator.toBoolean( + req.param('allow_unauthorized_cert') + '' + ) // Fetch the password of current user that is valid in LDAP system - password_to_check = validator.trim(req.body['password_to_check']); + const password_to_check = validator.trim(req.body.password_to_check + '') // Validate provided parameters - if (!validator.matches(url, /^ldaps?:\/\/[a-z0-9\.\-]+:\d+$/i)){ + if (!validator.matches(url, /^ldaps?:\/\/[a-z0-9\.\-]+:\d+$/i)) { req.session.flash_error( "URL to LDAP server must be of following format: 'ldap://HOSTNAME:PORT'" - ); + ) } - if ( req.session.flash_has_errors() ) { - var error = new Error("Validation failed"); - error.show_to_user = true; - throw error; + if (!validator.matches(searchfilter, /\{\{username\}\}/)) { + req.session.flash_error( + "LDAP filter must contain the {{username}} placeholder. Use '(mail={{username}})' to match mail as the username." + ) + } + + if (req.session.flash_has_errors()) { + const error = new Error('Validation failed') + error.show_to_user = true + throw error } // Return the configuration object return { - ldap_config : { - url : url, - binddn : binddn, - bindcredentials : bindcredentials, - searchbase : searchbase, - allow_unauthorized_cert : allow_unauthorized_cert, + ldap_config: { + url, + binddn, + bindcredentials, + searchbase, + searchfilter, + allow_unauthorized_cert }, - ldap_auth_enabled : ldap_auth_enabled, - password_to_check : password_to_check, - }; + ldap_auth_enabled, + password_to_check + } } router.get('/company/backup/', (req, res) => { const companyExporter = new CompanyExporter({ - dbSchema : req.app.get('db_model'), - }); + dbSchema: req.app.get('db_model') + }) - let company; + let company req.user .getCompany() - .then(c => Promise.resolve(company = c)) + .then(c => Promise.resolve((company = c))) // Generate company summary - .then(company => companyExporter.promiseCompanySummary({ company : company })) + .then(company => companyExporter.promiseCompanySummary({ company })) // Get CSV presentation of company summary .then(companySummary => companySummary.promise_as_csv_string()) .then(csv_content => { + res.attachment(company.name_for_machine() + '_backup.csv') - res.attachment( - company.name_for_machine()+'_backup.csv' - ); - - res.send(csv_content); + res.send(csv_content) }) - .catch(function(error){ + .catch(error => { console.error( - "An error occured while downloading company summary: %s, at %s", error, error.stack - ); + 'An error occured while downloading company summary: %s, at %s', + error, + error.stack + ) req.session.flash_error( - "Failed to download company summary. " + - ( error.show_to_user ? error : 'Please contact customer service') - ); + 'Failed to download company summary. ' + + (error.show_to_user ? error : 'Please contact customer service') + ) - return res.redirect_with_session('/settings/general/'); - }); -}); + return res.redirect_with_session('/settings/general/') + }) +}) router.post('/company/delete/', (req, res) => { - - let company; + let company req.user .getCompany() - .then(c => Promise.resolve(company = c)) - .then(company => CompanyRemover.promiseToRemove({ - company : company, - byUser : req.user, - confirmName : req.body.confirm_name, - })) + .then(c => Promise.resolve((company = c))) + .then(company => + CompanyRemover.promiseToRemove({ + company, + byUser: req.user, + confirmName: req.body.confirm_name + }) + ) .then(() => { - req.session.flash_message(`Company ${company.name} and related data were successfully removed`); + req.session.flash_message( + `Company ${company.name} and related data were successfully removed` + ) - return res.redirect_with_session('/'); + return res.redirect_with_session('/') }) .catch(error => { - console.log( - `Failed to remove ${company.id} by user ${req.user.id}. Reason: ${ Exception.extract_system_error_message(error) }, at ${error.stack}` - ); + `Failed to remove ${company.id} by user ${ + req.user.id + }. Reason: ${Exception.extract_system_error_message(error)}, at ${ + error.stack + }` + ) req.session.flash_error( - `Failed to remove company. Reason: ${ Exception.extract_user_error_message(error) }` - ); + `Failed to remove company. Reason: ${Exception.extract_user_error_message( + error + )}` + ) - return res.redirect_with_session('/settings/general/'); - }); -}); + return res.redirect_with_session('/settings/general/') + }) +}) -const getAvailableCarriedOverOptions = () => ([ - {days : 0, label : 'None'}, - ...[...Array(21).keys()].filter(i=>i>0).map(i=>({days:i, label:i})), - {days: 1000, label: 'All'}, -]); +const getAvailableCarriedOverOptions = () => [ + { days: 0, label: 'None' }, + ...[...Array(21).keys()].filter(i => i > 0).map(i => ({ days: i, label: i })), + { days: 1000, label: 'All' } +] -module.exports = router; +module.exports = router diff --git a/lib/route/users/index.js b/lib/route/users/index.js index 6e6c05787..e85f570aa 100644 --- a/lib/route/users/index.js +++ b/lib/route/users/index.js @@ -1,446 +1,511 @@ - -"use strict"; - -const - express = require('express'), - router = express.Router(), - validator = require('validator'), - Promise = require('bluebird'), - moment = require('moment'), - _ = require('underscore'), - csv = Promise.promisifyAll(require('csv')), - fs = require("fs"), - formidable = require('formidable'), - LeaveCollectionUtil = require('../../model/leave_collection')(), - Exception = require('../../error'), - UserImporter = require('../../model/user_importer'), - EmailTransport = require('../../email'), - {getAuditCaptureForUser} = require('../../model/audit'); - -const { sorter } = require("../../util"); - +'use strict' + +const express = require('express') +const router = express.Router() +const validator = require('validator') +const Promise = require('bluebird') +const moment = require('moment') +const csv = Promise.promisifyAll(require('csv')) +const fs = require('fs') +const formidable = require('formidable') +const LeaveCollectionUtil = require('../../model/leave_collection')() +const Exception = require('../../error') +const UserImporter = require('../../model/user_importer') +const EmailTransport = require('../../email') +const { getAuditCaptureForUser } = require('../../model/audit') +const SlackTransport = require('../../slack') +const multer = require('multer') +const upload = multer() +const Sequelize = require('sequelize') +const Op = Sequelize.Op + +const { sorter } = require('../../util') // Make sure that current user is authorized to deal with settings -router.all(/.*/, require('../../middleware/ensure_user_is_admin')); - -router.get('/add/', function(req, res){ - req.user - .get_company_for_add_user() - .then(function(company){ - res.render('user_add', { - company : company, - departments: company.departments.sort((a, b) => sorter(a.name, b.name)), - }); - }); -}); - -router.post('/add/', function(req, res){ +router.all(/.*/, require('../../middleware/ensure_user_is_admin')) + +router.get('/add/', (req, res) => { + req.user.get_company_for_add_user().then(company => { + res.render('user_add', { + company, + departments: company.departments.sort((a, b) => sorter(a.name, b.name)), + title: 'Add new user | TimeOff' + }) + }) +}) - const - Email = new EmailTransport(); +router.post('/add/', (req, res) => { + const Email = new EmailTransport() + const Slack = new SlackTransport() - let current_company, - new_user_attributes; + let current_company, new_user_attributes req.user - .get_company_for_add_user() - .then(function(company){ - - current_company = company; + .get_company_for_add_user() + .then(company => { + current_company = company + + new_user_attributes = get_and_validate_user_parameters({ + req, + params: req.body, + item_name: 'user', + departments: company.departments, + // If current company has LDAP auth do not require password + require_password: !company.ldap_auth_enabled + }) - new_user_attributes = get_and_validate_user_parameters({ - req : req, - item_name : 'user', - departments : company.departments, - // If current company has LDAP auth do not require password - require_password : (company.ldap_auth_enabled ? false : true ), - }); + return Promise.resolve() + }) - return Promise.resolve(); - }) + // Make sure that we do not add user with existing emails + .then(() => + UserImporter.validate_email_to_be_free({ + email: new_user_attributes.email + }) + ) - // Make sure that we do not add user with existing emails - .then(() => UserImporter - .validate_email_to_be_free({ email : new_user_attributes.email }) - ) + // Add new user to database + .then(() => + UserImporter.add_user({ + name: new_user_attributes.name, + slack_username: new_user_attributes.slack_username, + lastname: new_user_attributes.lastname, + email: new_user_attributes.email, + department_id: new_user_attributes.department_id, + start_date: new_user_attributes.start_date, + end_date: new_user_attributes.end_date, + admin: new_user_attributes.admin, + auto_approve: new_user_attributes.auto_approve, + company_id: req.user.company_id, + password: new_user_attributes.password + }) + ) - // Add new user to database - .then(() => UserImporter.add_user({ - name : new_user_attributes.name, - lastname : new_user_attributes.lastname, - email : new_user_attributes.email, - department_id : new_user_attributes.DepartmentId, - start_date : new_user_attributes.start_date, - end_date : new_user_attributes.end_date, - admin : new_user_attributes.admin, - auto_approve : new_user_attributes.auto_approve, - company_id : req.user.companyId, - password : new_user_attributes.password, - })) + .then(new_user => + Email.promise_add_new_user_email({ + company: current_company, + admin_user: req.user, + new_user + }) + // Fail silently for the user and track the error for the administrator. + .catch(error => { + console.error( + 'Failed to send the email to ' + new_user.email + ' : ' + error, + error.stack + ) + return Promise.resolve(new_user) + }) + ) - .then(new_user => Email.promise_add_new_user_email({ - company : current_company, - admin_user : req.user, - new_user : new_user, - })) + .then(new_user => + Slack.promise_add_new_user_slack({ + company: current_company, + admin_user: req.user, + new_user + }) + // Fail silently for the user and track the error for the administrator. + .catch(error => { + console.error( + 'Failed to send the slack message to ' + + new_user.email + + ' : ' + + error, + error.stack + ) + return Promise.resolve(new_user) + }) + ) - .then(function(){ - if ( req.session.flash_has_errors() ) { - return res.redirect_with_session('../add/'); - } else { - req.session.flash_message('New user account successfully added'); - return res.redirect_with_session('../'); - } - }) + .then(() => { + if (req.session.flash_has_errors()) { + return res.redirect_with_session('../add/') + } + req.session.flash_message('New user account successfully added') + return res.redirect_with_session('../') + }) - .catch(function(error){ - console.log( - 'An error occurred when trying to add new user account by user '+req.user.id - ); - console.dir(error); + .catch(error => { + console.log( + 'An error occurred when trying to add new user account by user ' + + req.user.id, + error.stack + ) + console.dir(error) - if ( error && error.tom_error) { - req.session.flash_error( Exception.extract_user_error_message(error) ); - } + if (error && error.tom_error) { + req.session.flash_error(Exception.extract_user_error_message(error)) + } - req.session.flash_error( - 'Failed to add new user' - ); + req.session.flash_error('Failed to add new user') - return res.redirect_with_session('../add/'); - }); -}); + return res.redirect_with_session('../add/') + }) +}) -router.get('/import/', function(req, res){ - req.user - .getCompany() - .then(company => res.render( - 'users_import', { - company : company, - } - )); -}); +router.get('/import/', (req, res) => { + req.user.getCompany().then(company => + res.render('users_import', { + company, + title: 'Import users | TimeOff' + }) + ) +}) -router.post('/import/', function(req, res){ - let - form = new formidable.IncomingForm(), - parseAsync = Promise.promisify(form.parse); +router.post('/import/', upload.single('users_import'), (req, res) => { + const form = new formidable.IncomingForm() + const parseAsync = Promise.promisify(form.parse) parseAsync .call(form, req) .then(args => { - - let files = args[1]; - - if (files.users_import.size === 0) { + if (req.file.size === 0) { Exception.throw_user_error({ - user_error : 'No .CSV file to restore from was provided', - system_error : 'User ' + req.user.id + ' tried to import employees ' - + 'without submitting .CSV file', - }); - } else if ( files.users_import.size > 2097152 ) { + user_error: 'No .CSV file to restore from was provided', + system_error: + 'User ' + + req.user.id + + ' tried to import employees ' + + 'without submitting .CSV file' + }) + } else if (req.file.size > 2097152) { Exception.throw_user_error({ - user_error : '.CSV file could not be bigger then 2M', - system_error : 'User ' + req.user.id + ' tried to submit file bigger then ' - + '2M', - }); + user_error: '.CSV file could not be bigger then 2M', + system_error: + 'User ' + req.user.id + ' tried to submit file bigger then ' + '2M' + }) } - return fs.readFileAsync(files.users_import.path, "utf8"); + if (req.file.path && !req.file.buffer) { + // disk storage + return fs.readFileAsync(req.file.path, 'utf8') + } + + // memory storage + return req.file.buffer.toString() }) - .then(csv_data_string => csv.parseAsync(csv_data_string,{trim:true})) + .then(csv_data_string => csv.parseAsync(csv_data_string, { trim: true })) .then(parsed_data => { - // Limit number of employees to be imported at one go // if (parsed_data.length > 201) { Exception.throw_user_error({ - user_error : 'Cannot import more then 200 employees per one go. ' - + 'Please splite .CSV file into chunks of no more then 200 employees ' - + 'and process them each at the time', - system_error : 'User ' + req.user.id + ' tried to import more then 200 ' - + 'user at one time' - }); + user_error: + 'Cannot import more then 200 employees per one go. ' + + 'Please splite .CSV file into chunks of no more then 200 employees ' + + 'and process them each at the time', + system_error: + 'User ' + + req.user.id + + ' tried to import more then 200 ' + + 'user at one time' + }) } return UserImporter.add_users_in_bulk({ - to_company_id : req.user.companyId, - bulk_header : parsed_data.shift(), - bulk_data : parsed_data, - }); + to_company_id: req.user.company_id, + bulk_header: parsed_data.shift(), + bulk_data: parsed_data + }) }) .then(action_result => { - console.dir(action_result); - if ( action_result.users.length > 0 ) { + console.dir(action_result) + if (action_result.users.length > 0) { req.session.flash_message( - 'Successfully imported users with following emails: ' - + action_result.users.map(user => user.email).sort().join(', ') - ); + 'Successfully imported users with following emails: ' + + action_result.users + .map(user => user.email) + .sort() + .join(', ') + ) } if (action_result.errors.length > 0) { - action_result.errors.forEach(err => req.session.flash_error( - 'Failed to add user ' + err.email + '. Reason: ' + err.error - )); + action_result.errors.forEach(err => + req.session.flash_error( + 'Failed to add user ' + err.email + '. Reason: ' + err.error + ) + ) } - res.redirect_with_session('/users/import/'); + res.redirect_with_session('/users/import/') }) - .catch(function(error){ + .catch(error => { console.error( - 'An error occurred when trying to import users for company' - + req.user.companyId - + '. Reason: ' + Exception.extract_system_error_message(error) - ); + 'An error occurred when trying to import users for company' + + req.user.company_id + + '. Reason: ' + + Exception.extract_system_error_message(error), + error.stack + ) req.session.flash_error( - 'Failed to import users, reason: ' - + Exception.extract_user_error_message(error) - ); - res.redirect_with_session('/users/import/'); - }); -}); - -router.post('/import-sample/', function(req, res){ + 'Failed to import users, reason: ' + + Exception.extract_user_error_message(error) + ) + res.redirect_with_session('/users/import/') + }) +}) +router.post('/import-sample/', (req, res) => { req.user .getCompany({ - scope : ['with_active_users', 'with_simple_departments'], + scope: ['with_active_users', 'with_simple_departments'] }) .then(company => { + res.attachment(company.name_for_machine() + '.csv') - res.attachment( - company.name_for_machine()+'.csv' - ); - - let content = company.users.map( user => [ + const content = company.users.map(user => [ user.email, + user.slack_username, user.lastname, user.name, - company.departments.find( dep => dep.id === user.DepartmentId ).name - ]); - - content.unshift( ['email','lastname', 'name', 'department'] ); - - return csv.stringifyAsync( content ); + company.departments.find(dep => dep.id === user.department_id).name + ]) + + content.unshift([ + 'email', + 'slack_username', + 'lastname', + 'name', + 'department' + ]) + + return csv.stringifyAsync(content) }) - .then(csv_data_string => res.send(csv_data_string)); + .then(csv_data_string => res.send(csv_data_string)) +}) -}); +router.get('/edit/:user_id/', (req, res) => { + const user_id = validator.trim(req.params.user_id) -router.get('/edit/:user_id/', function(req, res){ - const user_id = validator.trim(req.params['user_id']); + Promise.try(() => ensure_user_id_is_integer({ req, user_id })) + .then(() => req.user.get_company_for_user_details({ user_id })) + .then(company => { + const employee = company.users[0] - Promise - .try(() => ensure_user_id_is_integer({req : req, user_id : user_id})) - .then(() => req.user.get_company_for_user_details({user_id})) - .then(function(company){ + return employee.promise_schedule_I_obey().then(() => { + res.render('user_details', { + company, + employee, + show_main_tab: true, + departments: company.departments.sort((a, b) => + sorter(a.name, b.name) + ), + title: 'Edit user | TimeOff' + }) + }) + }) + .catch(error => { + console.error( + 'An error occurred when trying to open employee details by user ' + + req.user.id + + ' : ' + + error, + error.stack + ) - const employee = company.users[0]; + return res.redirect_with_session('../../') + }) +}) - return employee.promise_schedule_I_obey() - .then(function(){ - res.render('user_details', { - company : company, - employee : employee, - show_main_tab : true, - departments: company.departments.sort((a, b) => sorter(a.name, b.name)), - }); - }); - }) - .catch(function(error){ - console.error( - 'An error occurred when trying to open employee details by user '+req.user.id - + ' : ' + error - ); +router.get('/edit/:user_id/absences/', (req, res) => { + const user_id = validator.trim(req.params.user_id) + let user_allowance - return res.redirect_with_session('../../'); - }); -}); + const dbModel = req.app.get('db_model') -router.get('/edit/:user_id/absences/', function(req, res){ - let - user_id = validator.trim(req.params['user_id']), - user_allowance; + Promise.try(() => ensure_user_id_is_integer({ req, user_id })) + .then(() => req.user.get_company_for_user_details({ user_id })) + .then(company => { + const employee = company.users[0] + return employee.reload_with_session_details() + }) + .then(employee => employee.reload_with_leave_details({})) + .then(employee => + Promise.join( + employee + .promise_allowance() + .then(allowance_obj => + Promise.resolve([(user_allowance = allowance_obj), employee]) + ), - const dbModel = req.app.get('db_model'); + employee.promise_adjustmet_for_year(moment.utc().format('YYYY')), - Promise + employee.promise_carried_over_allowance_for_year( + moment.utc().format('YYYY') + ), - .try( () => ensure_user_id_is_integer({req : req, user_id : user_id}) ) - .then(() => req.user.get_company_for_user_details({ user_id : user_id }) ) - .then(function(company){ - let employee = company.users[0]; - return employee.reload_with_session_details(); - }) - .then( employee => employee.reload_with_leave_details({})) - .then(employee => Promise.join( + (args, employee_adjustment, carried_over_allowance) => { + args.push(null) + args.push(employee_adjustment) + args.push(carried_over_allowance) + return Promise.resolve(args) + } + ) + ) + .then(args => { + const allowance_obj = args[0] + const remaining_allowance = + allowance_obj.total_number_of_days_in_allowance - + allowance_obj.number_of_days_taken_from_allowance + const employee = args[1] + const total_days_number = allowance_obj.total_number_of_days_in_allowance + const employee_adjustment = args[3] + const carried_over_allowance = args[4] + + const leave_statistics = { + total_for_current_year: total_days_number, + remaining: remaining_allowance + } - employee - .promise_allowance() - .then( allowance_obj => Promise.resolve([user_allowance = allowance_obj, employee]) ), + leave_statistics.used_so_far = + allowance_obj.number_of_days_taken_from_allowance - employee - .promise_adjustmet_for_year(moment.utc().format('YYYY')), + leave_statistics.used_so_far_percent = + leave_statistics.total_for_current_year > 0 + ? (100 * leave_statistics.used_so_far) / + leave_statistics.total_for_current_year + : 0 - employee - .promise_carried_over_allowance_for_year(moment.utc().format('YYYY')), + leave_statistics.remaining_percent = + leave_statistics.total_for_current_year > 0 + ? (100 * + (leave_statistics.total_for_current_year - + leave_statistics.used_so_far)) / + leave_statistics.total_for_current_year + : 0 - (args, employee_adjustment, carried_over_allowance) => { - args.push(null); - args.push(employee_adjustment); - args.push(carried_over_allowance); - return Promise.resolve(args); - }) - ) - .then(args => { - let - allowance_obj = args[0], - - remaining_allowance = allowance_obj.total_number_of_days_in_allowance - allowance_obj.number_of_days_taken_from_allowance, - employee = args[1], - total_days_number = allowance_obj.total_number_of_days_in_allowance, - employee_adjustment = args[3], - carried_over_allowance = args[4]; - - let leave_statistics = { - total_for_current_year : total_days_number, - remaining : remaining_allowance, - }; - - leave_statistics.used_so_far = allowance_obj.number_of_days_taken_from_allowance; - - leave_statistics.used_so_far_percent = leave_statistics.total_for_current_year > 0 - ? 100 * leave_statistics.used_so_far / leave_statistics.total_for_current_year - : 0; - - leave_statistics.remaining_percent = leave_statistics.total_for_current_year > 0 - ? 100 * (leave_statistics.total_for_current_year - leave_statistics.used_so_far) / leave_statistics.total_for_current_year - : 0; - - return employee - .promise_schedule_I_obey() - .then(function(){ + return employee.promise_schedule_I_obey().then(() => { employee .promise_my_active_leaves_ever({}) - .then(leaves => LeaveCollectionUtil.enrichLeavesWithComments({leaves, dbModel})) + .then(leaves => + LeaveCollectionUtil.enrichLeavesWithComments({ leaves, dbModel }) + ) .then(leaves => LeaveCollectionUtil.promise_to_group_leaves(leaves)) - .then(function(grouped_leaves){ - + .then(grouped_leaves => { res.render('user_details', { - employee : employee, - grouped_leaves : grouped_leaves, - show_absence_tab : true, - leave_type_statistics : employee.get_leave_statistics_by_types(), - leave_statistics : leave_statistics, - employee_adjustment : employee_adjustment, - carried_over_allowance: carried_over_allowance, - user_allowance : user_allowance, - }); - - }); - }); - }) - .catch(function(error){ - console.error( - 'An error occurred when trying to open employee absences by user '+req.user.id - + ' : ' + error - ); - - return res.redirect_with_session('../../../'); - }); -}); + employee, + grouped_leaves, + show_absence_tab: true, + leave_type_statistics: employee.get_leave_statistics_by_types(), + leave_statistics, + employee_adjustment, + carried_over_allowance, + user_allowance, + title: 'Edit user | TimeOff' + }) + }) + }) + }) + .catch(error => { + console.error( + 'An error occurred when trying to open employee absences by user ' + + req.user.id + + ' : ' + + error, + error.stack + ) + return res.redirect_with_session('../../../') + }) +}) -router.get('/edit/:user_id/schedule/', function(req, res){ - var user_id = validator.trim(req.params['user_id']); +router.get('/edit/:user_id/schedule/', (req, res) => { + const user_id = validator.trim(req.params.user_id) - Promise.try(function(){ - ensure_user_id_is_integer({req : req, user_id : user_id}); + Promise.try(() => { + ensure_user_id_is_integer({ req, user_id }) }) - .then(function(){ - return req.user.get_company_for_user_details({ - user_id : user_id, - }); - }) - .then(function(company){ - - var employee = company.users[0]; + .then(() => + req.user.get_company_for_user_details({ + user_id + }) + ) + .then(company => { + const employee = company.users[0] - return employee - .promise_schedule_I_obey() - .then(function(schedule){ + return employee.promise_schedule_I_obey().then(schedule => { res.render('user_details', { - employee : employee, - schedule : schedule, - show_schedule_tab : true, - }); - }); - }) - .catch(function(error){ - console.error( - 'An error occurred when trying to open employee absences by user '+req.user.id - + ' : ' + error - ); + employee, + schedule, + show_schedule_tab: true, + title: 'User - Schedule | TimeOff' + }) + }) + }) + .catch(error => { + console.error( + 'An error occurred when trying to open employee absences by user ' + + req.user.id + + ' : ' + + error, + error.stack + ) - return res.redirect_with_session('../../../'); - }); -}); + return res.redirect_with_session('../../../') + }) +}) router.get('/edit/:user_id/calendar/', async (req, res) => { - const userId = validator.trim(req.params['user_id']); + const user_id = validator.trim(req.params.user_id) - const year = validator.isNumeric(req.query['year']) - ? moment.utc(req.query['year'], 'YYYY') - : req.user.company.get_today(); + const year = validator.isNumeric(req.query.year || req.body.year || '') + ? moment.utc(req.query.year || req.body.year, 'YYYY') + : req.user.company.get_today() - let employee, calendar, companyEnriched, user, supervisors, userAllowance; + let employee, calendar, companyEnriched, supervisors, userAllowance try { - await ensure_user_id_is_integer({req, user_id: userId}); + await ensure_user_id_is_integer({ req, user_id }) const company = await req.user.get_company_for_user_details({ - user_id : userId, - }); + user_id + }) - employee = company.users[0]; + employee = company.users[0] - await employee.reload_with_session_details(); + await employee.reload_with_session_details() calendar = await employee.promise_calendar({ year: year.clone(), - show_full_year: true, - }); - companyEnriched = await employee.get_company_with_all_leave_types(); - employee = await employee.reload_with_leave_details({ year }); - supervisors = await employee.promise_supervisors(); - userAllowance = await employee.promise_allowance({ year }); - + show_full_year: true + }) + companyEnriched = await employee.get_company_with_all_leave_types() + employee = await employee.reload_with_leave_details({ year }) + supervisors = await employee.promise_supervisors() + userAllowance = await employee.promise_allowance({ year }) } catch (error) { - console.error( - `An error ocurred while trying to render Calendar for user [${userId}]: ${error} at ${error.stack}` - ); + `An error ocurred while trying to render Calendar for user [${user_id}]: ${error} at ${ + error.stack + }` + ) - return res.redirect_with_session('../../../'); + return res.redirect_with_session('../../../') } - const fullLeaveTypeStatistics = employee.get_leave_statistics_by_types(); + const fullLeaveTypeStatistics = employee.get_leave_statistics_by_types() res.render('user_details', { employee, - show_calendar_tab : true, - - calendar : calendar.map(c => c.as_for_template()), - company : companyEnriched, - current_user : employee, - supervisors : supervisors, - previous_year : moment.utc(year).add(-1,'year').format('YYYY'), - current_year : year.format('YYYY'), - next_year : moment.utc(year).add(1,'year').format('YYYY'), - show_full_year : true, - user_allowance : userAllowance, - leave_type_statistics: fullLeaveTypeStatistics.filter(st => st.days_taken > 0), - }); -}); - - + show_calendar_tab: true, + + calendar: calendar.map(c => c.as_for_template()), + company: companyEnriched, + current_user: employee, + supervisors, + previous_year: moment + .utc(year) + .add(-1, 'year') + .format('YYYY'), + current_year: year.format('YYYY'), + next_year: moment + .utc(year) + .add(1, 'year') + .format('YYYY'), + show_full_year: true, + user_allowance: userAllowance, + leave_type_statistics: fullLeaveTypeStatistics.filter( + st => st.days_taken > 0 + ) + }) +}) // Special step performed while saving existing employee account details // @@ -448,389 +513,429 @@ router.get('/edit/:user_id/calendar/', async (req, res) => { // to be updated to be in future - check if during the time user was inactive // new user was added (including other companies) // -var ensure_user_was_not_useed_elsewhere_while_being_inactive = function(args){ - var - employee = args.employee, - new_user_attributes = args.new_user_attributes, - req = args.req, - model = args.model; +function ensure_user_was_not_useed_elsewhere_while_being_inactive(args) { + const employee = args.employee + const new_user_attributes = args.new_user_attributes + const req = args.req + const model = args.model if ( // Employee has end_date defined employee.end_date && - ( - ! new_user_attributes.end_date - || - ( - // new "end_date" is provided - // new "end_date" is in future - new_user_attributes.end_date && - moment.utc( new_user_attributes.end_date ).startOf('day').toDate() >= req.user.company.get_today().startOf('day').toDate() - ) - ) + (!new_user_attributes.end_date || + // new "end_date" is provided + // new "end_date" is in future + (new_user_attributes.end_date && + moment + .utc(new_user_attributes.end_date) + .startOf('day') + .toDate() >= + req.user.company + .get_today() + .startOf('day') + .toDate())) ) { - return model.User.find_by_email(new_user_attributes.email) - .then(function(user){ - - if (user && user.companyId !== employee.companyId) { - var error_msg = 'There is an active account with similar email somewhere within system.'; - req.session.flash_error(error_msg); - throw new Error(error_msg); - } + return model.User.find_by_email(new_user_attributes.email).then(user => { + if (user && user.company_id !== employee.company_id) { + const error_msg = + 'There is an active account with similar email somewhere within system.' + req.session.flash_error(error_msg) + throw new Error(error_msg) + } - return Promise.resolve(); - }); + return Promise.resolve() + }) } - return Promise.resolve(); -}; + return Promise.resolve() +} // Extra step: in case when employee is going to have new email, // check that it is not duplicated // -var ensure_email_is_not_used_elsewhere = function(args){ - var - employee = args.employee, - new_user_attributes = args.new_user_attributes, - req = args.req, - model = args.model; +function ensure_email_is_not_used_elsewhere(args) { + const employee = args.employee + const new_user_attributes = args.new_user_attributes + const req = args.req + const model = args.model if (new_user_attributes.email === employee.email) { - return Promise.resolve(); + return Promise.resolve() } - return model.User - .find_by_email(new_user_attributes.email) - .then(function(user){ - - if (user) { - req.session.flash_error('Email is already in use'); - throw new Error('Email is already used'); - } + return model.User.find_by_email(new_user_attributes.email).then(user => { + if (user) { + req.session.flash_error('Email is already in use') + throw new Error('Email is already used') + } - return Promise.resolve(); - }); -}; + return Promise.resolve() + }) +} -var ensure_we_are_not_removing_last_admin = function(args){ - var - employee = args.employee, - new_user_attributes = args.new_user_attributes, - req = args.req, - model = args.model; +function ensure_we_are_not_removing_last_admin(args) { + const employee = args.employee + const new_user_attributes = args.new_user_attributes + const req = args.req + const model = args.model if ( // It is about to change admin rights - new_user_attributes.admin !== employee.admin + new_user_attributes.admin !== employee.admin && // and it is revoking admin rights - && ! new_user_attributes.admin + !new_user_attributes.admin ) { - return model.User - .count({ where : { - companyId : employee.companyId, - id : { $ne : employee.id}, - admin : true, - }}) - .then(function(number_of_admins_to_be_left){ - if (number_of_admins_to_be_left > 0) { - return Promise.resolve(); - } + return model.User.count({ + where: { + company_id: employee.company_id, + id: { $ne: employee.id }, + admin: true + } + }).then(number_of_admins_to_be_left => { + if (number_of_admins_to_be_left > 0) { + return Promise.resolve() + } - req.session.flash_error('This is last admin within company. Cannot revoke admin rights.'); - throw new Error('Attempt to revoke admin rights from last admin in comapny '+employee.companyId); - }); + req.session.flash_error( + 'This is last admin within company. Cannot revoke admin rights.' + ) + throw new Error( + 'Attempt to revoke admin rights from last admin in comapny ' + + employee.company_id + ) + }) } - return Promise.resolve(); -}; + return Promise.resolve() +} -router.post('/edit/:user_id/', function(req, res){ - var user_id = validator.trim(req.params['user_id']); +router.post('/edit/:user_id/', (req, res) => { + const user_id = validator.trim(req.params.user_id) - var new_user_attributes, - employee, - model = req.app.get('db_model'); + let new_user_attributes + let employee + const model = req.app.get('db_model') - Promise.try(function(){ - ensure_user_id_is_integer({req : req, user_id : user_id}); + Promise.try(() => { + ensure_user_id_is_integer({ req, user_id }) }) - .then(function(){ - return req.user.get_company_for_user_details({ - user_id : user_id, - }); - }) - .then(function(company){ - - new_user_attributes = get_and_validate_user_parameters({ - req : req, - item_name : 'user', - departments : company.departments, - }); - - if (new_user_attributes.password) { - new_user_attributes.password = model.User.hashify_password( - new_user_attributes.password - ); - } + .then(() => + req.user.get_company_for_user_details({ + user_id + }) + ) + .then(company => { + new_user_attributes = get_and_validate_user_parameters({ + req, + params: req.body, + item_name: 'user', + departments: company.departments + }) - employee = company.users[0]; + if (new_user_attributes.password) { + new_user_attributes.password = model.User.hashify_password( + new_user_attributes.password + ) + } - return Promise.resolve(); - }) + employee = company.users[0] - // Ensure that new email if it was changed is not used anywhere else - // withing system - .then(function(){ return ensure_email_is_not_used_elsewhere({ - employee : employee, - new_user_attributes : new_user_attributes, - req : req, - model : model, - })}) - - // Double check user in case it is re-activated - .then(function(){ return ensure_user_was_not_useed_elsewhere_while_being_inactive({ - employee : employee, - new_user_attributes : new_user_attributes, - req : req, - model : model, - })}) - - .then(function(){ return ensure_we_are_not_removing_last_admin({ - employee : employee, - new_user_attributes : new_user_attributes, - req : req, - model : model, - })}) - - // All validations are passed: update database - .then(function(){ - - let adjustment = new_user_attributes.adjustment; - delete new_user_attributes.adjustment; - - const captureAuditTrail = getAuditCaptureForUser({ - byUser: req.user, - forUser: employee.get({plain: true}), - newAttributes: new_user_attributes, - }); - - employee - - // Update user record - .updateAttributes(new_user_attributes) - - .then(() => captureAuditTrail()) - - // Update adjustment if necessary - .then(() => { - if ( adjustment !== undefined ) { - return employee.promise_to_update_adjustment({ - year : moment.utc().format('YYYY'), - adjustment : adjustment, - }); - } + return Promise.resolve() + }) - return Promise.resolve(); + // Ensure that new email if it was changed is not used anywhere else + // withing system + .then(() => + ensure_email_is_not_used_elsewhere({ + employee, + new_user_attributes, + req, + model }) + ) - .then(function(){ - req.session.flash_message( - 'Details for '+employee.full_name()+' were updated' - ); - return res.redirect_with_session(req.body.back_to_absences ? './absences/' : '.'); - }); - }) + // Double check user in case it is re-activated + .then(() => + ensure_user_was_not_useed_elsewhere_while_being_inactive({ + employee, + new_user_attributes, + req, + model + }) + ) - .catch(function(error){ - console.error( - 'An error occurred when trying to save chnages to user account by user '+req.user.id - + ' : ' + error - ); + .then(() => + ensure_we_are_not_removing_last_admin({ + employee, + new_user_attributes, + req, + model + }) + ) - req.session.flash_error( - 'Failed to save changes.' - ); + // All validations are passed: update database + .then(() => { + const adjustment = new_user_attributes.adjustment + delete new_user_attributes.adjustment + + const captureAuditTrail = getAuditCaptureForUser({ + byUser: req.user, + forUser: employee.get({ plain: true }), + newAttributes: new_user_attributes + }) + + employee + + // Update user record + .update(new_user_attributes) + + .then(() => captureAuditTrail()) + + // Update adjustment if necessary + .then(() => { + if (adjustment !== undefined) { + return employee.promise_to_update_adjustment({ + year: moment.utc().format('YYYY'), + adjustment + }) + } + + return Promise.resolve() + }) + + .then(() => { + req.session.flash_message( + 'Details for ' + employee.full_name() + ' were updated' + ) + return res.redirect_with_session( + req.body.back_to_absences ? './absences/' : '.' + ) + }) + }) - return res.redirect_with_session(req.body.back_to_absences ? './absences/' : '.'); - }); -}); + .catch(error => { + console.error( + 'An error occurred when trying to save changes to user account by user ' + + req.user.id + + ' : ' + + error, + error.stack + ) + req.session.flash_error('Failed to save changes.') -router.post('/delete/:user_id/', function(req, res){ - const user_id = validator.trim(req.params['user_id']); - let auditCapture; + return res.redirect_with_session( + req.body.back_to_absences ? './absences/' : '.' + ) + }) +}) - Promise.try(() => ensure_user_id_is_integer({req, user_id})) - .then(() => req.user.get_company_for_user_details({user_id})) +router.post('/delete/:user_id/', (req, res) => { + const user_id = validator.trim(req.params.user_id) + let auditCapture + Promise.try(() => ensure_user_id_is_integer({ req, user_id })) + .then(() => req.user.get_company_for_user_details({ user_id })) .then(company => { - const employee = company.users[0]; - const employeePlain = employee.get({plain: true}); + const employee = company.users[0] + const employeePlain = employee.get({ plain: true }) auditCapture = getAuditCaptureForUser({ - byUser: req.user, - forUser: employeePlain, + byUser: req.user, + forUser: employeePlain, newAttributes: Object.assign( {}, - ...Object.keys(employeePlain).map(k => ({[k]:null})) - ), - }); - return employee.remove(); + ...Object.keys(employeePlain).map(k => ({ [k]: null })) + ) + }) + return employee.remove() }) .then(() => auditCapture()) - .then(() => { - req.session.flash_message( - 'Employee records were removed from the system' - ); - return res.redirect_with_session('../..'); + .then(result => { + req.session.flash_message('Employee records were removed from the system') + return res.redirect_with_session('../..') }) .catch(error => { console.error( - `An error occurred when trying to remove user ${user_id} by user ` - + `${req.user.id}. Error: ${error}` - ); - - req.session.flash_error(`Failed to remove user. ${error}`); - - return res.redirect_with_session(`../../edit/${user_id}/`); - }); -}); + 'An error occurred when trying to remove user ' + + user_id + + ' by user ' + + req.user.id + + '. Error: ' + + error, + error.stack + ) + req.session.flash_error('Failed to remove user. ' + error) -router.all('/search/', function(req, res){ + return res.redirect_with_session('../../edit/' + user_id + '/') + }) +}) +router.all('/search/', (req, res) => { // Currently we support search only by email and only JSON type requests - if ( ! req.accepts('json')) { + if (!req.accepts('json')) { // redirect client to the users index page - return res.redirect_with_session('../'); + return res.redirect_with_session('../') } - var email = validator.trim( req.body['email'] ).toLowerCase(); + const email = validator.trim(req.body.email || req.query.email).toLowerCase() - if ( ! validator.isEmail( email )) { - req.session.flash_error('Provided email does not look like valid one: "'+email+'"'); - return res.json([]); + if (!validator.isEmail(email)) { + req.session.flash_error( + 'Provided email does not look like valid one: "' + email + '"' + ) + return res.json([]) } // search for users only related to currently login admin // - var promise_result = req.user.getCompany({ - include : [{ - model : req.app.get('db_model').User, - as : 'users', - where : { - email : email + const promise_result = req.user.getCompany({ + include: [ + { + model: req.app.get('db_model').User, + as: 'users', + where: { + email + } } - }] - }); + ] + }) - promise_result.then(function(company){ + promise_result.then(company => { if (company.users.length > 0) { res.json(company.users) } else { - res.json([]); + res.json([]) } - }); -}); - + }) +}) /* Handle the root for users section, it shows the list of all users * */ -router.get('/', function(req, res) { - - var department_id = req.query['department'], - users_filter = {}, - model = req.app.get('db_model'); +router.get('/', (req, res) => { + let department_id = req.query.department + let users_filter = {} + const model = req.app.get('db_model') - if (validator.isNumeric( department_id )) { - users_filter = { DepartmentId : department_id }; - } else { - department_id = undefined; - } + if ( + typeof department_id === 'number' || + (department_id && validator.isNumeric(department_id)) + ) { + users_filter = { department_id } + } else { + department_id = undefined + } - req.user.getCompany({ - include : [ + req.user + .getCompany({ + include: [ { - model : model.User, - as : 'users', - where : users_filter, - required : false, - include : [ - { model : model.Department, as : 'department' }, + model: model.User, + as: 'users', + where: users_filter, + required: false, + include: [ + { model: model.Department, as: 'department' }, // Following is needed to be able to calculate how many days were // taken from allowance { - model : model.Leave, - as : 'my_leaves', - required : false, - where : { + model: model.Leave, + as: 'my_leaves', + required: false, + where: { // status : model.Leave.status_approved(), - status : [ + status: [ model.Leave.status_approved(), model.Leave.status_new(), - model.Leave.status_pended_revoke(), + model.Leave.status_pended_revoke() ], - $or : { - date_start : { - $between : [ - moment.utc().startOf('year').format('YYYY-MM-DD'), - moment.utc().endOf('year').format('YYYY-MM-DD HH:mm'), + [Op.or]: { + date_start: { + [Op.between]: [ + moment + .utc() + .startOf('year') + .format('YYYY-MM-DD'), + moment + .utc() + .endOf('year') + .format('YYYY-MM-DD HH:mm') ] }, - date_end : { - $between : [ - moment.utc().startOf('year').format('YYYY-MM-DD'), - moment.utc().endOf('year').format('YYYY-MM-DD HH:mm'), + date_end: { + [Op.between]: [ + moment + .utc() + .startOf('year') + .format('YYYY-MM-DD'), + moment + .utc() + .endOf('year') + .format('YYYY-MM-DD HH:mm') ] } } }, - include : [{ - model : model.LeaveType, - as : 'leave_type', - }, + include: [ + { + model: model.LeaveType, + as: 'leave_type' + } ] // End of my_leaves include } - ], - }, + ] + } ], + order: [ + [{ model: model.User, as: 'users' }, 'lastname'], + [ + { model: model.User, as: 'users' }, + { model: model.Department, as: 'department' }, + model.Department.default_order_field() + ] + ] }) // Make sure that objects have all necessary attributes to render page // (template system is sync only) - .then(function(company){ - return company.getBank_holidays() + .then(company => + company + .getBank_holidays() // stick bank holidays to company - .then(function(bank_holidays){ - company.bank_holidays = bank_holidays; + .then(bank_holidays => { + company.bank_holidays = bank_holidays return company.getDepartments({ - order : [ model.Department.default_order_field() ], - }); + order: [model.Department.default_order_field()] + }) }) // stick departments to company as well - .then(function(departments){ - company.departments = departments.sort((a,b) => sorter(a.name, b.name)); - return Promise.resolve(company); + .then(departments => { + company.departments = departments.sort((a, b) => + sorter(a.name, b.name) + ) + return Promise.resolve(company) }) - }) + ) // Make sure that user's leaves have reference back to user in question - .then(function(company){ - company.users.forEach(function(user){ - user.company = company; - user.my_leaves.forEach(function(leave){ leave.user = user }); - }); + .then(company => { + company.users.forEach(user => { + user.company = company + user.my_leaves.forEach(leave => { + leave.user = user + }) + }) - return Promise.resolve(company); + return Promise.resolve(company) }) // Update users to have neccessary data for leave calculations - .then(function(company){ - return Promise.resolve(company.users).map(function(user){ - return user.promise_schedule_I_obey(); - },{ - concurrency : 10, - }) - .then(function(){ return Promise.resolve(company) }); - }) + .then(company => + Promise.resolve(company.users) + .map(user => user.promise_schedule_I_obey(), { + concurrency: 10 + }) + .then(() => Promise.resolve(company)) + ) /* * Following block builds array of object for each user in company. @@ -842,19 +947,22 @@ router.get('/', function(req, res) { * so we need to get all data before passing it into template as template * * */ - .then(company => Promise - .resolve(company.users) - .map(user => user - .promise_allowance() - .then(allowance_obj => Promise.resolve({ - user_row : user, - number_of_days_available_in_allowance : allowance_obj.number_of_days_available_in_allowance, - })), - { - concurrency : 10 - } - ) - .then(users_info => Promise.resolve([company, users_info])) + .then(company => + Promise.resolve(company.users) + .map( + user => + user.promise_allowance().then(allowance_obj => + Promise.resolve({ + user_row: user, + number_of_days_available_in_allowance: + allowance_obj.number_of_days_available_in_allowance + }) + ), + { + concurrency: 10 + } + ) + .then(users_info => Promise.resolve([company, users_info])) ) // We are moving away from passing complex objects into templates @@ -865,205 +973,231 @@ router.get('/', function(req, res) { // So prepare special rendering data structure here .then(args => promise_user_list_data_for_rendering(args)) - .then(function(args){ - let - company = args[0], - users_info = args[1]; + .then(args => { + const company = args[0] + const users_info = args[1] - if ( req.query['as-csv'] ) { + if (req.query['as-csv']) { return users_list_as_csv({ - users_info : users_info, - company : company, - req : res, - res : res, - }); + users_info, + company, + req: res, + res + }) } res.render('users', { - company : company, - department_id : Number(department_id), - title : company.name + "'s people", - users_info : users_info, - }); - }); -}); + company, + department_id: Number(department_id), + title: company.name + "'s people", + users_info + }) + }) +}) function promise_user_list_data_for_rendering(args) { - let - company = args[0], - users_info = args[1]; + const company = args[0] + const users_info = args[1] const usersInfoForRendering = users_info.map(ui => ({ - user_id : ui.user_row.id, - user_email : ui.user_row.email, - user_name : ui.user_row.name, - user_lastname : ui.user_row.lastname, - user_full_name : ui.user_row.full_name(), - department_id : ui.user_row.department.id, - department_name : ui.user_row.department.name, - is_admin : ui.user_row.admin, - number_of_days_available_in_allowance : ui.number_of_days_available_in_allowance, - number_of_days_taken_from_allowance : ui.user_row.calculate_number_of_days_taken_from_allowance(), - is_active : ui.user_row.is_active(), - })); - - const sortedUsersInfoForRendering = usersInfoForRendering - .sort((a, b) => sorter(a.user_lastname, b.user_lastname)); - - return Promise.resolve([company, sortedUsersInfoForRendering]); + user_id: ui.user_row.id, + user_email: ui.user_row.email, + user_slack_username: ui.user_row.slack_username, + user_name: ui.user_row.name, + user_lastname: ui.user_row.lastname, + user_full_name: ui.user_row.full_name(), + department_id: ui.user_row.department.id, + department_name: ui.user_row.department.name, + is_admin: ui.user_row.admin, + number_of_days_available_in_allowance: + ui.number_of_days_available_in_allowance, + number_of_days_taken_from_allowance: ui.user_row.calculate_number_of_days_taken_from_allowance(), + is_active: ui.user_row.is_active() + })) + + const sortedUsersInfoForRendering = usersInfoForRendering.sort((a, b) => + sorter(a.user_lastname, b.user_lastname) + ) + + return Promise.resolve([company, sortedUsersInfoForRendering]) } function users_list_as_csv(args) { - let users_info = args.users_info, - company = args.company, - res = args.res; + const users_info = args.users_info + const company = args.company + const res = args.res // Compose file name res.attachment( - company.name_for_machine() - + '_employees_on_' - + company.get_today().format('YYYY_MMM_DD') - + '.csv' - ); + company.name_for_machine() + + '_employees_on_' + + company.get_today().format('YYYY_MMM_DD') + + '.csv' + ) // Compose result CSV header - let content = [['email', 'lastname', 'name', 'department', 'remaining allowance', 'days used']]; + const content = [ + [ + 'email', + 'slack_username', + 'lastname', + 'name', + 'department', + 'remaining allowance', + 'days used' + ] + ] // ... and body users_info.forEach(ui => { content.push([ ui.user_email, + ui.user_slack_username, ui.user_lastname, ui.user_name, ui.department_name, ui.number_of_days_available_in_allowance, ui.number_of_days_taken_from_allowance - ]); - }); + ]) + }) - return csv.stringifyAsync( content ) - .then(csv_data_string => res.send(csv_data_string)); + return csv + .stringifyAsync(content) + .then(csv_data_string => res.send(csv_data_string)) } function get_and_validate_user_parameters(args) { - var req = args.req, - item_name = args.item_name, - require_password = args.require_password || false; - - // Get user parameters - var name = validator.trim(req.body['name']), - lastname = validator.trim(req.body['lastname']), - email = validator.trim(req.body['email_address']), - department_id = validator.trim(req.body['department']), - start_date = validator.trim(req.body['start_date']), - end_date = validator.trim(req.body['end_date']), - adjustment = validator.trim(req.body['adjustment']), - password = validator.trim(req.body['password_one']), - password_confirm = validator.trim(req.body['password_confirm']), - admin = validator.toBoolean(req.body['admin']), - auto_approve = validator.toBoolean(req.body['auto_approve']); - - // Validate provided parameters - - if (!validator.isEmail(email)) { - req.session.flash_error( - 'New email of '+item_name+' should be valid email address' - ); - } - - if (!validator.isNumeric(department_id)) { - req.session.flash_error( - 'New department number of '+item_name+' should be a valid number' - ); - } + const req = args.req + const params = args.params + const item_name = args.item_name + const require_password = args.require_password || false + + // Get user parameters + const name = params.name && validator.trim(params.name) + const lastname = params.lastname && validator.trim(params.lastname) + const slack_username = + params.slack_username && validator.trim(params.slack_username) + let email = params.email_address && validator.trim(params.email_address) + const department_id = params.department && validator.trim(params.department) + let start_date = params.start_date && validator.trim(params.start_date) + let end_date = params.end_date && validator.trim(params.end_date) + const adjustment = params.adjustment && validator.trim(params.adjustment) + const password = params.password_one && validator.trim(params.password_one) + const password_confirm = + params.password_confirm && validator.trim(params.password_confirm) + const admin = (params.admin && validator.toBoolean(params.admin)) || false + const auto_approve = + (params.auto_approve && validator.toBoolean(params.auto_approve)) || false + + // Validate provided parameters + if (!email || !validator.isEmail(email)) { + req.session.flash_error( + 'New email of ' + item_name + ' should be valid email address' + ) + } - if (adjustment && ! validator.isFloat(adjustment) ) { - req.session.flash_error( - 'New allowance adjustment of '+item_name+' should be a valid number' - ); - } else if (adjustment && ! ( adjustment % 1 === 0 || Math.abs( adjustment % 1 ) === 0.5 )) { - req.session.flash_error( - 'New allowance adjustment of '+item_name+' should be either whole integer number or with half' - ); - } + if ( + typeof department_id !== 'number' && + (!department_id || !validator.isNumeric(department_id)) + ) { + req.session.flash_error( + 'New department number of ' + item_name + ' should be a valid number' + ) + } - start_date = req.user.company.normalise_date( start_date ); + if (adjustment && !validator.isFloat(adjustment)) { + req.session.flash_error( + 'New allowance adjustment of ' + item_name + ' should be a valid number' + ) + } else if ( + adjustment && + !(adjustment % 1 === 0 || Math.abs(adjustment % 1) === 0.5) + ) { + req.session.flash_error( + 'New allowance adjustment of ' + + item_name + + ' should be either whole integer number or with half' + ) + } - if (!validator.isDate(start_date)) { - req.session.flash_error( - 'New start date for '+item_name+' should be valid date' - ); - } + start_date = req.user.company.normalise_date(start_date) - if (end_date ){ + if (!start_date || !validator.toDate(start_date)) { + req.session.flash_error( + 'New start date for ' + item_name + ' should be valid date' + ) + } - end_date = req.user.company.normalise_date( end_date ); + if (end_date) { + end_date = req.user.company.normalise_date(end_date) - if ( ! validator.isDate(end_date)) { - req.session.flash_error( - 'New end date for '+item_name+' should be valid date' - ); - } + if (!end_date || !validator.toDate(end_date)) { + req.session.flash_error( + 'New end date for ' + item_name + ' should be valid date' + ) } + } - if ( - start_date && - end_date && - moment.utc(start_date).toDate() > moment.utc(end_date).toDate() - ){ - req.session.flash_error( - 'End date for '+item_name+' is before start date' - ); - } + if ( + start_date && + end_date && + moment.utc(start_date).toDate() > moment.utc(end_date).toDate() + ) { + req.session.flash_error( + 'End date for ' + item_name + ' is before start date' + ) + } - if (password && password !== password_confirm) { - req.session.flash_error('Confirmed password does not match initial one'); - } + if (password && password !== password_confirm) { + req.session.flash_error('Confirmed password does not match initial one') + } - if (require_password && ! password) { - req.session.flash_error('Password is required'); - } + if (require_password && !password) { + req.session.flash_error('Password is required') + } - if ( req.session.flash_has_errors() ) { - throw new Error( 'Got validation errors' ); - } + if (req.session.flash_has_errors()) { + throw new Error('Got validation errors') + } - // Normalize email as we operate only with lower case letters in emails - email = email.toLowerCase(); - - var attributes = { - name : name, - lastname : lastname, - email : email, - DepartmentId : department_id, - start_date : start_date, - end_date : (end_date || null), - admin : admin, - auto_approve : auto_approve, - }; - - if (adjustment || String(adjustment) === '0') { - attributes.adjustment = adjustment; - } + // Normalize email as we operate only with lower case letters in emails + email = email.toLowerCase() + + const attributes = { + name, + lastname, + slack_username, + email, + department_id, + start_date, + end_date: end_date || null, + admin, + auto_approve + } - if ( password ) { - attributes.password = password; - } + if (adjustment || String(adjustment) === '0') { + attributes.adjustment = adjustment + } - return attributes; -} + if (password) { + attributes.password = password + } -function ensure_user_id_is_integer(args){ - var req = args.req, - user_id = args.user_id; + return attributes +} - if (! validator.isInt(user_id)){ - throw new Error( - 'User '+req.user.id+' tried to edit user with non-integer ID: '+user_id - ); - } +function ensure_user_id_is_integer(args) { + const req = args.req + const user_id = args.user_id - return; + if (typeof user_id !== 'number' && (!user_id || !validator.isInt(user_id))) { + throw new Error( + 'User ' + + req.user.id + + ' tried to edit user with non-integer ID: ' + + user_id + ) + } } -module.exports = router; +module.exports = router diff --git a/lib/route/users/summary.js b/lib/route/users/summary.js index c98ecfdac..d6a28f844 100644 --- a/lib/route/users/summary.js +++ b/lib/route/users/summary.js @@ -1,84 +1,84 @@ +'use strict' -"use strict"; - -const - express = require('express'), - router = express.Router(), - Exception = require('../../error'), - Promise = require('bluebird'); +const express = require('express') +const router = express.Router() +const Exception = require('../../error') +const Promise = require('bluebird') router.get('/summary/:userId/', (req, res) => { - - const requestor = req.user; - const userId = req.params.userId; + const requestor = req.user + const user_id = req.params.userId // Get user object by provided ID - let flow = req.app.get('db_model').User.scope('withDepartments').find({where:{id:userId}}); + let flow = req.app + .get('db_model') + .User.scope('withDepartments') + .find({ where: { id: user_id } }) // Ensure that requestor and user belong to the same company flow = flow.then(user => { - if (!user || user.companyId !== requestor.companyId) { + if (!user || user.company_id !== requestor.company_id) { throw Exception.throwUserError({ user_error: 'No access to given user', - system_error: `User ${requestor.id} tried to access details of user ${userId}: either ID does not belong to existing user of requestor and Id does not share company`, - }); + system_error: `User ${ + requestor.id + } tried to access details of user ${user_id}: either ID does not belong to existing user of requestor and Id does not share company` + }) } - return Promise.resolve(user); - }); + return Promise.resolve(user) + }) // If requestor is admin OR is manager for given user show detailed INFO flow = flow.then(user => { // In case admin is asking user's details: show detailed version if (requestor.is_admin()) { - return Promise.resolve({user, isDetailed: true}); + return Promise.resolve({ user, isDetailed: true }) } // Check if given user is among supervised ones - return requestor.promise_supervised_users() - .then(users => { - let isDetailed = false; - - if (users.filter(u => u.id === user.id).length === 1) { - isDetailed = true; - } + return requestor.promise_supervised_users().then(users => { + let isDetailed = false - return Promise.resolve({user, isDetailed}); - }); - }); + if (users.filter(u => u.id === user.id).length === 1) { + isDetailed = true + } - flow = flow.then(({user, isDetailed}) => { + return Promise.resolve({ user, isDetailed }) + }) + }) + flow = flow.then(({ user, isDetailed }) => { if (!isDetailed) { - return Promise.resolve({user}); + return Promise.resolve({ user }) } - return Promise.all([user.promise_allowance(), user.promise_supervisors()]) - .then(([userAllowance, supervisors]) => ({ - user, - userAllowance, - supervisors, - })); - }); + return Promise.all([ + user.promise_allowance(), + user.promise_supervisors() + ]).then(([userAllowance, supervisors]) => ({ + user, + userAllowance, + supervisors + })) + }) - flow = flow.then(({user, userAllowance, supervisors}) => { - const supervisorNames = (supervisors||[]).map(u => u.full_name()); + flow = flow.then(({ user, userAllowance, supervisors }) => { + const supervisorNames = (supervisors || []).map(u => u.full_name()) res.render('user/popup_user_details', { layout: false, userFullName: user.full_name(), departmentName: user.get('department').name, userAllowance, - supervisorNames, - }); - }); - + supervisorNames + }) + }) flow.catch(error => { - console.log(error); - res.send('Failed to get user details...'); - }); - -}); + console.log(error) + res.send('Failed to get user details...') + }) +}) -module.exports = router; +module.exports = router diff --git a/lib/route/utils/pager.js b/lib/route/utils/pager.js index c5cae9edd..d7b477c5d 100644 --- a/lib/route/utils/pager.js +++ b/lib/route/utils/pager.js @@ -9,48 +9,44 @@ * * an attribute "items_per_page" wich * globaly defines how many items per page are shown * * a method "get_pager_object" that return the pager object to be passed into the pager.hbs -* -* Pager object has following entries: -* -* * page_prev : number to address previous page, if 0 then previous page is disabled -* * page_next : page number to next opage, if 0 no more pages after current one -* * page : number of current page, page counting starts with 1 -* * filter : an object that contains other GET parameters to be placed into the -* pager's links; keys are the names of parameters and values are values -* * page_qnty : total number of pages available for current pager -* * count : total number of pages items -* * pages : simple array with item for each page, each item is corresponding page number -* + * + * Pager object has following entries: + * + * * page_prev : number to address previous page, if 0 then previous page is disabled + * * page_next : page number to next opage, if 0 no more pages after current one + * * page : number of current page, page counting starts with 1 + * * filter : an object that contains other GET parameters to be placed into the + * pager's links; keys are the names of parameters and values are values + * * page_qnty : total number of pages available for current pager + * * count : total number of pages items + * * pages : simple array with item for each page, each item is corresponding page number + * * */ -"use strict"; +'use strict' -module.exports = function(){ +module.exports = function() { return { - - items_per_page : 10, - - get_pager_object : function(args){ - - var - total_items_count = args.total_items_count, - filter = args.filter, - page = args.current_page; - - var page_qnty = Math.ceil( total_items_count / this.items_per_page ); - - var pager = { - filter : filter, - page : page, - page_qnty : page_qnty, - page_prev : (page > 1 ? page - 1 : 0), - page_next : (page >= page_qnty ? 0 : page + 1), - count : total_items_count, - pages : Array.apply(null, Array( page_qnty )) - .map(function (x, i) { return i+1; }), - }; - - return pager; - }, - }; -}; + items_per_page: 10, + + get_pager_object: function(args) { + const total_items_count = args.total_items_count + const filter = args.filter + const page = args.current_page + + const page_qnty = Math.ceil(total_items_count / this.items_per_page) + + const pager = { + filter, + page, + page_qnty, + page_prev: page > 1 ? page - 1 : 0, + page_next: page >= page_qnty ? 0 : page + 1, + count: total_items_count, + pages: Array.apply(null, Array(page_qnty)).map((x, i) => i + 1) + } + + return pager + } + } +} diff --git a/lib/route/validator/leave_request.js b/lib/route/validator/leave_request.js index aa27180bd..b9638f17d 100644 --- a/lib/route/validator/leave_request.js +++ b/lib/route/validator/leave_request.js @@ -1,85 +1,112 @@ - -'use strict'; - -var validator = require('validator'), - LeaveRequestParameters = require('../../model/leave_request_parameters'); - -module.exports = function(args){ - var req = args.req; - - var user = validator.trim( req.body['user'] ), - leave_type = validator.trim( req.body['leave_type'] ), - from_date = validator.trim( req.body['from_date'] ), - from_date_part = validator.trim( req.body['from_date_part'] ), - to_date = validator.trim( req.body['to_date'] ), - to_date_part = validator.trim( req.body['to_date_part'] ), - reason = validator.trim( req.body['reason'] ); - - if (user && !validator.isNumeric(user)){ - req.session.flash_error('Incorrect employee'); - } - - if (!validator.isNumeric(leave_type)){ - req.session.flash_error('Incorrect leave type'); - } - - var date_validator = function(date_str, label) { - try { - - // Basic check - if (! date_str ) throw new Error("date needs to be defined"); - - date_str = req.user.company.normalise_date(date_str); - - // Ensure that normalisation went OK - if (! validator.isDate(date_str)) throw new Error("Invalid date format"); - - } catch (e) { - console.log('Got an error ' + e); - req.session.flash_error(label + ' should be a date'); +'use strict' + +const validator = require('validator') +const moment = require('moment') +const LeaveRequestParameters = require('../../model/leave_request_parameters') + +module.exports = function(args) { + const req = args.req + const params = args.params + + const user = typeof params.user !== 'undefined' && validator.trim(params.user) + const leave_type = + typeof params.leave_type !== 'undefined' && + validator.trim(params.leave_type) + let from_date = + typeof params.from_date !== 'undefined' && validator.trim(params.from_date) + const from_date_part = + typeof params.from_date_part !== 'undefined' && + validator.trim(params.from_date_part) + let to_date = + typeof params.to_date !== 'undefined' && validator.trim(params.to_date) + const to_date_part = + typeof params.to_date_part !== 'undefined' && + validator.trim(params.to_date_part) + const reason = + typeof params.reason !== 'undefined' && validator.trim(params.reason) + + if ( + typeof user !== 'undefined' && + user && + typeof user !== 'number' && + (!user || !validator.isNumeric(user)) + ) { + req.session.flash_error('Incorrect employee') + } + + if ( + typeof leave_type !== 'number' && + (!leave_type || !validator.isNumeric(leave_type)) + ) { + req.session.flash_error('Incorrect leave type') + } + + const date_validator = function(date_str, label) { + try { + // Basic check + if (!date_str) throw new Error('date needs to be defined') + + date_str = req.user.company.normalise_date(date_str) + + // Ensure that normalisation went OK + if (!date_str || !validator.toDate(date_str)) { + throw new Error('Invalid date format') } + } catch (e) { + console.log('Got an error ' + e) + req.session.flash_error(label + ' should be a date') } - - date_validator(from_date, 'From date'); - - if ( !validator.matches(from_date_part, /^[123]$/) - || !validator.matches(to_date_part, /^[123]$/) - ){ - req.session.flash_error('Incorrect day part'); - } - - date_validator(to_date, 'To date'); - - // Check if it makes sence to continue validation (as following code relies on - // to and from dates to be valid ones) - if ( req.session.flash_has_errors() ) { - throw new Error( 'Got validation errors' ); - } - - // Convert dates inot format used internally - from_date = req.user.company.normalise_date(from_date); - to_date = req.user.company.normalise_date(to_date); - - if (from_date.substr(0,4) !== to_date.substr(0,4)) { - req.session.flash_error('Current implementation does not allow inter year leaves. Please split your request into two parts'); - } - - if ( req.session.flash_has_errors() ) { - throw new Error( 'Got validation errors' ); - } - - var valid_attributes = { - leave_type : leave_type, - from_date : from_date, - from_date_part : from_date_part, - to_date : to_date, - to_date_part : to_date_part, - reason : reason, - }; - - if ( user ) { - valid_attributes.user = user; - } - - return new LeaveRequestParameters( valid_attributes ); -}; + } + + date_validator(from_date, 'From date') + + if ( + typeof from_date_part === 'undefined' || + !validator.matches(from_date_part, /^[123]$/) || + typeof to_date_part === 'undefined' || + !validator.matches(to_date_part, /^[123]$/) + ) { + req.session.flash_error('Incorrect day part') + } + + date_validator(to_date, 'To date') + + // Check if it makes sence to continue validation (as following code relies on + // to and from dates to be valid ones) + if (req.session.flash_has_errors()) { + const error = new Error('Got validation errors') + error.flash = req.session.flash + throw error + } + + // Convert dates inot format used internally + from_date = req.user.company.normalise_date(from_date) + to_date = req.user.company.normalise_date(to_date) + + if (from_date.substr(0, 4) !== to_date.substr(0, 4)) { + req.session.flash_error( + 'Current implementation does not allow inter year leaves. Please split your request into two parts' + ) + } + + if (req.session.flash_has_errors()) { + const error = new Error('Got validation errors') + error.flash = req.session.flash + throw error + } + + const valid_attributes = { + leave_type, + from_date, + from_date_part, + to_date, + to_date_part, + reason + } + + if (user) { + valid_attributes.user = user + } + + return new LeaveRequestParameters(valid_attributes) +} diff --git a/lib/slack.js b/lib/slack.js new file mode 100644 index 000000000..54e4e3c04 --- /dev/null +++ b/lib/slack.js @@ -0,0 +1,429 @@ +'use strict' + +const bluebird = require('bluebird') +const handlebars = require('express-handlebars').create({ + partialsDir: __dirname + '/../views/partials/', + extname: '.hbs', + helpers: require('./view/helpers')() +}) +const config = require('./config') +const { WebClient } = require('@slack/client') + +function Slack() {} + +// This is a little helper that ensure that data in context are in a shape +// suitable for usage in templates +// +function _promise_to_unfold_context(context) { + if (context.user) { + return context.user.reload_with_session_details() + } else { + return bluebird.resolve(1) + } +} + +Slack.prototype.promise_rendered_slack_template = function(args) { + const filename = args.template_name + const context = args.context || {} + + return ( + bluebird + .resolve() + + // Prepare context to be passed into first rendering stage + .then(() => _promise_to_unfold_context(context)) + + // Render slack text + .then(() => + handlebars.render( + __dirname + '/../views/slack/' + filename + '.hbs', + context + ) + ) + + .then(text => + bluebird.resolve({ + slack_username: context.slack_username, + text + }) + ) + ) +} + +// If current configuration does not allow sending slacks, it return empty function +// +Slack.prototype.get_send_slack = function() { + const slack_token = config.get('slack:token') + + // Check if current installation is set to send slack notifications + if (!slack_token) { + return function() { + console.debug('Pretend to send slack: ' + JSON.stringify(arguments)) + return bluebird.resolve() + } + } + + const slack_bot_name = config.get('slack:bot_name') || '' + const slack_icon_url = config.get('slack:icon_url') || '' + + const web = new WebClient(slack_token) + + function push_slack(args) { + if (!args.channel) { + console.debug('No username set, skip sending to Slack.') + return Promise.resolve() + } + + console.debug('Sending slack message on channel "' + args.channel + '"') + return web.chat + .postMessage({ + username: slack_bot_name, + channel: args.channel, + icon_url: slack_icon_url, + attachments: [ + { + text: args.text + } + ] + }) + .then(res => { + // `res` contains information about the posted message + console.log('Message sent: ', res.ts) + }) + .catch(console.error) + } + + return push_slack +} + +// Send registration complete slack for provided user + +Slack.prototype.promise_registration_slack = function(args) { + const self = this + const user = args.user + const send_slack = self.get_send_slack() + + return self + .promise_rendered_slack_template({ + template_name: 'registration_complete_slack', + context: { + user, + slack_username: user.slack_username + } + }) + .then(slack_obj => + send_slack({ + channel: slack_obj.slack_username, + text: slack_obj.text + }).then(send_result => bluebird.resolve(send_result)) + ) +} + +Slack.prototype.promise_add_new_user_slack = function(args) { + const self = this + const company = args.company + const admin_user = args.admin_user + const new_user = args.new_user + const slack_username = args.new_user?.slack_username + const send_slack = self.get_send_slack() + + return self + .promise_rendered_slack_template({ + template_name: 'add_new_user_slack', + context: { + new_user, + admin_user, + company, + user: new_user, + slack_username + } + }) + .then(slack_obj => + send_slack({ + channel: slack_obj.slack_username, + text: slack_obj.text + }).then(send_result => bluebird.resolve(send_result)) + ) +} + +Slack.prototype.promise_leave_request_revoke_slacks = function(args) { + const self = this + const leave = args.leave + const send_slack = self.get_send_slack() + + let template_name_to_supervisor = 'leave_request_revoke_to_supervisor_slack' + let template_name_to_requestor = 'leave_request_revoke_to_requestor_slack' + + if (leave.get('user').is_auto_approve()) { + template_name_to_supervisor = + 'leave_request_revoke_to_supervisor_autoapprove_slack' + template_name_to_requestor = + 'leave_request_revoke_to_requestor_autoapprove_slack' + } + + const promise_slack_to_supervisor = self + .promise_rendered_slack_template({ + template_name: template_name_to_supervisor, + context: { + leave, + approver: leave.get('approver'), + requester: leave.get('user'), + user: leave.get('approver'), + slack_username: leave.get('approver').slack_username + } + }) + .then(slack_obj => { + console.log('Approver') + console.log(slack_obj) + return send_slack({ + channel: slack_obj.slack_username, + text: slack_obj.text + }).then(send_result => bluebird.resolve(send_result)) + }) + + const promise_slack_to_requestor = self + .promise_rendered_slack_template({ + template_name: template_name_to_requestor, + context: { + leave, + approver: leave.get('approver'), + requester: leave.get('user'), + user: leave.get('user'), + slack_username: leave.get('user').slack_username + } + }) + .then(slack_obj => { + console.log('Requester') + console.log(slack_obj) + + return send_slack({ + channel: slack_obj.slack_username, + text: slack_obj.text + }).then(send_result => bluebird.resolve(send_result)) + }) + + return bluebird.join( + promise_slack_to_supervisor, + promise_slack_to_requestor, + () => bluebird.resolve() + ) +} + +Slack.prototype.promise_leave_request_slacks = function(args) { + const self = this + const leave = args.leave + const send_slack = self.get_send_slack() + + let template_name_to_supervisor = 'leave_request_to_supervisor_slack' + let template_name_to_requestor = 'leave_request_to_requestor_slack' + + if (leave.get('user').is_auto_approve()) { + template_name_to_supervisor = + 'leave_request_to_supervisor_autoapprove_slack' + template_name_to_requestor = 'leave_request_to_requestor_autoapprove_slack' + } + + const promise_slack_to_supervisor = supervisor => + self + .promise_rendered_slack_template({ + template_name: template_name_to_supervisor, + context: { + leave, + approver: supervisor, + requester: leave.get('user'), + user: supervisor, + slack_username: supervisor.slack_username + } + }) + .then(slack_obj => + send_slack({ + channel: slack_obj.slack_username, + text: slack_obj.text + }).then(send_result => bluebird.resolve(send_result)) + ) + + const promise_slack_to_requestor = self + .promise_rendered_slack_template({ + template_name: template_name_to_requestor, + context: { + leave, + approver: leave.get('approver'), + requester: leave.get('user'), + user: leave.get('approver'), + slack_username: leave.get('user').slack_username + } + }) + .then(slack_obj => + send_slack({ + channel: slack_obj.slack_username, + text: slack_obj.text + }).then(send_result => bluebird.resolve(send_result)) + ) + + return bluebird.join( + promise_slack_to_requestor, + leave + .get('user') + .promise_supervisors() + .map(supervisor => promise_slack_to_supervisor(supervisor)), + () => bluebird.resolve() + ) +} + +Slack.prototype.promise_leave_request_decision_slacks = function(args) { + const self = this + const leave = args.leave + const action = args.action + const was_pended_revoke = args.was_pended_revoke + const send_slack = self.get_send_slack() + + const promise_slack_to_supervisor = self + .promise_rendered_slack_template({ + template_name: 'leave_request_decision_to_supervisor_slack', + context: { + leave, + approver: leave.get('approver'), + requester: leave.get('user'), + action, + was_pended_revoke, + user: leave.get('approver'), + slack_username: leave.get('approver').slack_username + } + }) + .then(slack_obj => + send_slack({ + channel: slack_obj.slack_username, + text: slack_obj.text + }).then(send_result => bluebird.resolve(send_result)) + ) + + const promise_slack_to_requestor = self + .promise_rendered_slack_template({ + template_name: 'leave_request_decision_to_requestor_slack', + context: { + leave, + approver: leave.get('approver'), + requester: leave.get('user'), + action, + was_pended_revoke, + user: leave.get('user'), + slack_username: leave.get('user').slack_username + } + }) + .then(slack_obj => + send_slack({ + channel: slack_obj.slack_username, + text: slack_obj.text + }).then(send_result => bluebird.resolve(send_result)) + ) + + return bluebird.join( + promise_slack_to_supervisor, + promise_slack_to_requestor, + () => bluebird.resolve() + ) +} + +Slack.prototype.promise_forgot_password_slack = function(args) { + const self = this + const user = args.user + const send_slack = self.get_send_slack() + + console.log('promise_forgot_password_slack') + console.log(args) + + return user + .getCompany() + .then(company => + self.promise_rendered_slack_template({ + template_name: 'forgot_password_slack', + context: { + user, + company, + slack_username: user.slack_username + } + }) + ) + .then(slack_obj => + send_slack({ + channel: slack_obj.slack_username, + text: slack_obj.text + }).then(send_result => bluebird.resolve(send_result)) + ) +} + +Slack.prototype.promise_reset_password_slack = function(args) { + const self = this + const user = args.user + const send_slack = self.get_send_slack() + + return self + .promise_rendered_slack_template({ + template_name: 'reset_password_slack', + context: { + user, + slack_username: user.slack_username + } + }) + .then(slack_obj => + send_slack({ + channel: slack_obj.slack_username, + text: slack_obj.text + }).then(send_result => bluebird.resolve(send_result)) + ) +} + +Slack.prototype.promise_leave_request_cancel_slacks = function(args) { + const self = this + const leave = args.leave + const send_slack = self.get_send_slack() + + const promise_slack_to_supervisor = self + .promise_rendered_slack_template({ + template_name: 'leave_request_cancel_to_supervisor_slack', + context: { + leave, + approver: leave.get('approver'), + requester: leave.get('user'), + user: leave.get('approver'), + slack_username: leave.get('approver').slack_username + } + }) + .then(slack_obj => { + console.log('APPROVER') + console.log(slack_obj) + return send_slack({ + channel: slack_obj.slack_username, + text: slack_obj.text + }).then(send_result => bluebird.resolve(send_result)) + }) + + const promise_slack_to_requestor = self + .promise_rendered_slack_template({ + template_name: 'leave_request_cancel_to_requestor_slack', + context: { + leave, + approver: leave.get('approver'), + requester: leave.get('user'), + user: leave.get('user'), + slack_username: leave.get('user').slack_username + } + }) + + .then(slack_obj => { + console.log('APPROVER') + console.log(slack_obj) + return send_slack({ + channel: slack_obj.slack_username, + text: slack_obj.text + }).then(send_result => bluebird.resolve(send_result)) + }) + + return bluebird.join( + promise_slack_to_supervisor, + promise_slack_to_requestor, + () => bluebird.resolve() + ) +} + +module.exports = Slack diff --git a/lib/util/index.js b/lib/util/index.js index 70785f217..52fe8d01f 100644 --- a/lib/util/index.js +++ b/lib/util/index.js @@ -1,14 +1,12 @@ +const config = require('../config') - -const config = require('../config'); - -const defaultLocale = config.get("locale_code_for_sorting") || "en"; +const defaultLocale = config.get('locale_code_for_sorting') || 'en' /** * Local aware comparator to be used as compare function for Array's `sort` function */ -const sorter = (a, b) => String(a).localeCompare(String(b), defaultLocale); +const sorter = (a, b) => String(a).localeCompare(String(b), defaultLocale) module.exports = { - sorter, -}; \ No newline at end of file + sorter +} diff --git a/lib/view/helpers.js b/lib/view/helpers.js index 5677edec3..4afa1591d 100644 --- a/lib/view/helpers.js +++ b/lib/view/helpers.js @@ -1,164 +1,166 @@ +'use strict' -"use strict"; +const moment = require('moment') +const moment_tz = require('moment-timezone') +const config = require('../config') -var - moment = require('moment'), - moment_tz = require('moment-timezone'), - config = require('../config'); +function as_date_formatted(date_str, format, options) { + if (!date_str) return '' -var as_date_formatted = function(date_str, format, options) { - - if (! date_str) return ''; - - if ( ! format ) { - format = get_current_format( options ); + if (!format) { + format = get_current_format(options) } // Special case when we have to take time zone into consideration // when printing date (usually it is needed for those dates recorded // automatically as UTC time stampts) - if ( options.tom_take_timezone_into_consideration ) { - return moment_tz.utc(date_str).tz( get_timezone( options ) ).format( format ); + if (options.tom_take_timezone_into_consideration) { + return moment_tz + .utc(date_str) + .tz(get_timezone(options)) + .format(format) } - return moment.utc(date_str).format(format); + return moment.utc(date_str).format(format) } // Note: that currently it returns only truely value of given property, that is if there property // exists and its value is falsy, that undef is returned back -var get_property_from_options = function(options, property_name){ - var value; - - if ( options.hasOwnProperty('data') - && options.data.hasOwnProperty('root') - && options.data.root.hasOwnProperty(property_name) - && options.data.root[property_name] +function get_property_from_options(options, property_name) { + let value + + if ( + options.hasOwnProperty('data') && + options.data.hasOwnProperty('root') && + options.data.root.hasOwnProperty(property_name) && + options.data.root[property_name] ) { - value = options.data.root[property_name]; + value = options.data.root[property_name] } - return value; -}; - -var get_current_format = function(options){ + return value +} - var format = 'YYYY-MM-DD'; +function get_current_format(options) { + let format = 'YYYY-MM-DD' - var user = get_property_from_options(options, 'logged_user') - || get_property_from_options(options, 'user'); + const user = + get_property_from_options(options, 'logged_user') || + get_property_from_options(options, 'user') - if ( user && user.hasOwnProperty('company') ) { - format = user.company.get_default_date_format(); + if (user && user.hasOwnProperty('company')) { + format = user.company.get_default_date_format() } - return format; -}; - -var get_timezone = function(options) { + return format +} - let timezone = 'Europe/London'; +function get_timezone(options) { + let timezone = 'Europe/London' - var user = get_property_from_options(options, 'logged_user') - || get_property_from_options(options, 'user'); + const user = + get_property_from_options(options, 'logged_user') || + get_property_from_options(options, 'user') - if ( user && user.hasOwnProperty('company') ) { - timezone = user.company.timezone; + if (user && user.hasOwnProperty('company')) { + timezone = user.company.timezone } - return timezone; -}; + return timezone +} -module.exports = function(){ +module.exports = function() { return { // Handlebars does not allow to have conditions in IF, here is // workaround picked from here: http://stackoverflow.com/questions/8853396/logical-operator-in-a-handlebars-js-if-conditional - if_equal : function(v1, v2, options){ - if(v1 === v2) { - return options.fn(this); + if_equal: function(v1, v2, options) { + if (v1 === v2) { + return options.fn(this) } - return options.inverse(this); + return options.inverse(this) }, // Given string with UTC date return string with date formated in customer specific manner - as_date : function(date_string, options) { - - return as_date_formatted(date_string, undefined, options); + as_date: function(date_string, options) { + return as_date_formatted(date_string, undefined, options) }, // Return string with given date formated as a timestamp - as_datetime : function (date_str, options) { + as_datetime: function(date_str, options) { return as_date_formatted( date_str, get_current_format(options) + ' HH:mm:ss', options - ); + ) }, // Do the same as "as_date" method but takes into consideration of company // timezone. It is needed for rendering dates that were recorded in database // automatically in UTC, dates that were recorded based on explicit input // from users should not be used with this method (but with "as_date" instead) - as_date_from_timestamp : function(date_string, options){ - + as_date_from_timestamp: function(date_string, options) { // Add custom flag to options so further down the call stack // we would know that date needs to be corrected with // current timezone - options.tom_take_timezone_into_consideration = true; + options.tom_take_timezone_into_consideration = true - return as_date_formatted(date_string, undefined, options); + return as_date_formatted(date_string, undefined, options) }, // Similar to "as_datetime" but with the same twist as "as_date_from_timestamp" - as_datetime_from_timestamp : function(date_str, options){ - + as_datetime_from_timestamp: function(date_str, options) { // Add custom flag to options so further down the call stack // we would know that date needs to be corrected with // current timezone - options.tom_take_timezone_into_consideration = true; + options.tom_take_timezone_into_consideration = true return as_date_formatted( date_str, get_current_format(options) + ' HH:mm:ss', options - ); + ) }, // Given string with UTC date and string with moment.js format return corresponding string - as_date_formatted : as_date_formatted, + as_date_formatted, // Get access to config value holding application domain - get_application_domain : function() { - return config.get('application_domain'); + get_application_domain: function() { + return config.get('branding:url') }, // Return URL to the web site with promotion materials for TimeOff.Management - get_promotion_website_domain : function() { - return config.get('promotion_website_domain'); + get_promotion_website_domain: function() { + return config.get('branding:website') }, - concatenate : function() { - var arg = Array.prototype.slice.call(arguments,0); - arg.pop(); - return arg.join(''); + concatenate: function() { + const arg = Array.prototype.slice.call(arguments, 0) + arg.pop() + return arg.join('') }, + ga_tracker: config.get('google:analytics:tracker'), // Should we include Google Analitics snipet? // (based on application config) - is_ga_analitics_on : function(options) { - if ( !!config.get('ga_analytics_on') ) { - return options.fn(this); + is_ga_analitics_on: function(options) { + if (config.get('google:analytics:tracker')) { + return options.fn(this) } - return options.inverse(this); + return options.inverse(this) }, - is_force_to_explicitly_select_type_when_requesting_new_leave: function (options) { - if (!!config.get('force_to_explicitly_select_type_when_requesting_new_leave')) { - return options.fn(this); + is_force_to_explicitly_select_type_when_requesting_new_leave: function( + options + ) { + if ( + config.get('force_to_explicitly_select_type_when_requesting_new_leave') + ) { + return options.fn(this) } - return options.inverse(this); - }, - - }; -}; + return options.inverse(this) + } + } +} diff --git a/migrations/20170103144054-add_default_date_format.js b/migrations/20170103144054-add_default_date_format.js index f48da0c09..6cf054d2d 100644 --- a/migrations/20170103144054-add_default_date_format.js +++ b/migrations/20170103144054-add_default_date_format.js @@ -1,27 +1,21 @@ -'use strict'; +'use strict' module.exports = { - up: function (queryInterface, Sequelize) { - - queryInterface.describeTable('Companies').then(function(attributes){ - + up: function(queryInterface, Sequelize) { + return queryInterface.describeTable('Companies').then(function(attributes) { if (attributes.hasOwnProperty('date_format')) { - return 1; + return 1 } - return queryInterface.addColumn( - 'Companies', - 'date_format', - { - type : Sequelize.STRING, - allowNull : false, - defaultValue : 'YYYY-MM-DD', - } - ); - }); + return queryInterface.addColumn('Companies', 'date_format', { + type: Sequelize.STRING, + allowNull: false, + defaultValue: 'YYYY-MM-DD' + }) + }) }, - down: function (queryInterface, Sequelize) { - return queryInterface.removeColumn('Companies', 'date_format'); + down: function(queryInterface, Sequelize) { + return queryInterface.removeColumn('Companies', 'date_format') } -}; +} diff --git a/migrations/20170329060832-rename_allowence_to_allowance.js b/migrations/20170329060832-rename_allowence_to_allowance.js index ed040078e..25091f77d 100644 --- a/migrations/20170329060832-rename_allowence_to_allowance.js +++ b/migrations/20170329060832-rename_allowence_to_allowance.js @@ -1,65 +1,77 @@ -'use strict'; +'use strict' -var models = require('../lib/model/db'); +const models = require('../lib/model/db') module.exports = { - up: function (queryInterface, Sequelize) { - - queryInterface.describeTable('Departments').then(function(attributes){ - - if (attributes.hasOwnProperty('allowance')) { - return 1; - } - - if ('sqlite' === queryInterface.sequelize.getDialect()) { - - console.log('Going into SQLIite case'); - - return queryInterface - // Create Temp Departments based on current model definitiom - .createTable('Departments_backup', models.Department.attributes) - - .then(function(){ - return queryInterface.sequelize.query('PRAGMA foreign_keys=off;'); - }) - - // Copy data form original Departments into new Temp one - .then(function(){ - return queryInterface.sequelize.query( - 'INSERT INTO `Departments_backup` (id, name, include_public_holidays, createdAt, updatedAt, companyId, bossId, allowance) SELECT id, name, include_public_holidays, createdAt, updatedAt, companyId, bossId, allowence FROM `'+ models.Department.tableName +'`'); - }) - - .then(function(){ - return queryInterface.dropTable( models.Department.tableName ); - }) - - .then(function(){ - return queryInterface.renameTable('Departments_backup', models.Department.tableName); - }) - - .then(function(){ - return queryInterface.sequelize.query('PRAGMA foreign_keys=on;'); - }) - - .then(function(){ - queryInterface.addIndex(models.Department.tableName, ['companyId']); - }) - - .then(function(){ - queryInterface.addIndex(models.Department.tableName, ['id']); - }); - - } else { - - console.log('Generic option'); - - return queryInterface.renameColumn('Departments', 'allowence', 'allowance') - .then(function(d){ console.dir(d) }); - } - }); + up: function(queryInterface, Sequelize) { + return queryInterface + .describeTable('Departments') + .then(function(attributes) { + if (attributes.hasOwnProperty('allowance')) { + return 1 + } + + if (queryInterface.sequelize.getDialect() === 'sqlite') { + console.log('Going into SQLIite case') + + return ( + queryInterface + // Create Temp Departments based on current model definitiom + .createTable('Departments_backup', models.Department.attributes) + + .then(function() { + return queryInterface.sequelize.query( + 'PRAGMA foreign_keys=off;' + ) + }) + + // Copy data form original Departments into new Temp one + .then(function() { + return queryInterface.sequelize.query( + 'INSERT INTO `Departments_backup` (id, name, include_public_holidays, createdAt, updatedAt, company_id, bossId, allowance) SELECT id, name, include_public_holidays, createdAt, updatedAt, company_id, bossId, allowence FROM `' + + models.Department.tableName + + '`' + ) + }) + + .then(function() { + return queryInterface.dropTable(models.Department.tableName) + }) + + .then(function() { + return queryInterface.renameTable( + 'Departments_backup', + models.Department.tableName + ) + }) + + .then(function() { + return queryInterface.sequelize.query('PRAGMA foreign_keys=on;') + }) + + .then(function() { + queryInterface.addIndex(models.Department.tableName, [ + 'company_id' + ]) + }) + + .then(function() { + queryInterface.addIndex(models.Department.tableName, ['id']) + }) + ) + } else { + console.log('Generic option') + + return queryInterface + .renameColumn('Departments', 'allowence', 'allowance') + .then(function(d) { + console.dir(d) + }) + } + }) }, - down: function (queryInterface, Sequelize) { - return queryInterface.renameColumn('Departments', 'allowance', 'allowence'); + down: function(queryInterface, Sequelize) { + return queryInterface.renameColumn('Departments', 'allowance', 'allowence') } -}; +} diff --git a/migrations/20170530-add_auto_approve_flag_to_user.js b/migrations/20170530-add_auto_approve_flag_to_user.js index f3d63691d..66d7973b3 100644 --- a/migrations/20170530-add_auto_approve_flag_to_user.js +++ b/migrations/20170530-add_auto_approve_flag_to_user.js @@ -1,27 +1,23 @@ +'use strict' -'use strict'; - -var models = require('../lib/model/db'); +const models = require('../lib/model/db') module.exports = { - up: function (queryInterface, Sequelize) { - - queryInterface.describeTable('Users').then(function(attributes){ - + up: function(queryInterface, Sequelize) { + return queryInterface.describeTable('Users').then(function(attributes) { if (attributes.hasOwnProperty('auto_approve')) { - return 1; + return 1 } return queryInterface.addColumn( 'Users', 'auto_approve', models.User.attributes.auto_approve - ); - }); - + ) + }) }, - down: function (queryInterface, Sequelize) { - return queryInterface.removeColumn('Users', 'auto_approve'); + down: function(queryInterface, Sequelize) { + return queryInterface.removeColumn('Users', 'auto_approve') } -}; +} diff --git a/migrations/20171218-company-wide-message.js b/migrations/20171218-company-wide-message.js index 99751b343..b2358901f 100644 --- a/migrations/20171218-company-wide-message.js +++ b/migrations/20171218-company-wide-message.js @@ -1,27 +1,23 @@ +'use strict' -'use strict'; - -var models = require('../lib/model/db'); +const models = require('../lib/model/db') module.exports = { - up: function (queryInterface, Sequelize) { - - queryInterface.describeTable('Companies').then(function(attributes){ - + up: function(queryInterface, Sequelize) { + return queryInterface.describeTable('Companies').then(function(attributes) { if (attributes.hasOwnProperty('company_wide_message')) { - return 1; + return 1 } return queryInterface.addColumn( 'Companies', 'company_wide_message', models.Company.attributes.company_wide_message - ); - }); - + ) + }) }, - down: function (queryInterface, Sequelize) { - return queryInterface.removeColumn('Companies', 'company_wide_message'); + down: function(queryInterface, Sequelize) { + return queryInterface.removeColumn('Companies', 'company_wide_message') } -}; +} diff --git a/migrations/20171219-allowance-adjustment-per-year.js b/migrations/20171219-allowance-adjustment-per-year.js index 19ef8e023..f4d014cdd 100644 --- a/migrations/20171219-allowance-adjustment-per-year.js +++ b/migrations/20171219-allowance-adjustment-per-year.js @@ -1,37 +1,34 @@ +'use strict' -'use strict'; - -var models = require('../lib/model/db'), - Promise = require('bluebird'); +const models = require('../lib/model/db'); + const Promise = require('bluebird') module.exports = { - up: function (queryInterface, Sequelize) { - + up: function(queryInterface, Sequelize) { return queryInterface .createTable( models.UserAllowanceAdjustment.tableName, models.UserAllowanceAdjustment.attributes ) .then(() => queryInterface.describeTable('Users')) - .then(function(attributes){ - - if ( ! attributes.hasOwnProperty('adjustment')) { - return Promise.resolve(); + .then(function(attributes) { + if (!attributes.hasOwnProperty('adjustment')) { + return Promise.resolve() } - let sql = 'INSERT INTO user_allowance_adjustment (year, adjustment, user_id, created_at) ' - + 'SELECT 2017 AS year, adjustment as adjustment, id as user_id, date() || \' \' || time() as created_at ' - + 'FROM users'; + const sql = + 'INSERT INTO user_allowance_adjustment (year, adjustment, user_id, created_at) ' + + "SELECT 2017 AS year, adjustment as adjustment, id as user_id, date() || ' ' || time() as created_at " + + 'FROM users' - return queryInterface.sequelize.query( sql ); + return queryInterface.sequelize.query(sql) }) - .then(() => Promise.resolve()); - + .then(() => Promise.resolve()) }, - down: function (queryInterface, Sequelize) { + down: function(queryInterface, Sequelize) { // No way back! - return Promise.resolve(); + return Promise.resolve() } -}; +} diff --git a/migrations/20171220-drop-adjustment-column-from-user.js b/migrations/20171220-drop-adjustment-column-from-user.js index 4385d3368..cae54d4a9 100644 --- a/migrations/20171220-drop-adjustment-column-from-user.js +++ b/migrations/20171220-drop-adjustment-column-from-user.js @@ -1,54 +1,54 @@ +'use strict' -'use strict'; - -var models = require('../lib/model/db'), - Promise = require('bluebird'); +const models = require('../lib/model/db'); + const Promise = require('bluebird') module.exports = { - up: function (queryInterface, Sequelize) { - - return queryInterface - .describeTable('Users') - .then(attributes => { + up: function(queryInterface, Sequelize) { + return queryInterface.describeTable('Users').then(attributes => { + if (!attributes.hasOwnProperty('adjustment')) { + return Promise.resolve() + } - if ( ! attributes.hasOwnProperty('adjustment')) { - return Promise.resolve(); - } + if (queryInterface.sequelize.getDialect() !== 'sqlite') { + // For non SQLite: it is easy + return queryInterface.removeColumn(models.User.tableName, 'adjustment') + } - if ('sqlite' !== queryInterface.sequelize.getDialect()) { - // For non SQLite: it is easy - return queryInterface.removeColumn( - models.User.tableName, - 'adjustment' - ); - } + // For SQLite it is "fun" - // For SQLite it is "fun" - - return queryInterface + return ( + queryInterface // Create Temp Users based on current model definitiom .createTable('Users_backup', models.User.attributes) - .then(function(){ - return queryInterface.sequelize.query('PRAGMA foreign_keys=off;'); + .then(function() { + return queryInterface.sequelize.query('PRAGMA foreign_keys=off;') }) // Copy data form original Users into new Temp one - .then(function(){ + .then(function() { return queryInterface.sequelize.query( - 'INSERT INTO `Users_backup` (`id`, `email`, `password`, `name`, `lastname`, `activated`, `admin`, `start_date`, `end_date`, `createdAt`, `updatedAt`, `companyId`, `DepartmentId`, `auto_approve`) SELECT `id`, `email`, `password`, `name`, `lastname`, `activated`, `admin`, `start_date`, `end_date`, `createdAt`, `updatedAt`, `companyId`, `DepartmentId`, `auto_approve` FROM `'+ models.User.tableName +'`'); + 'INSERT INTO `Users_backup` (`id`, `email`, `password`, `name`, `lastname`, `activated`, `admin`, `start_date`, `end_date`, `createdAt`, `updatedAt`, `company_id`, `department_id`, `auto_approve`) SELECT `id`, `email`, `password`, `name`, `lastname`, `activated`, `admin`, `start_date`, `end_date`, `createdAt`, `updatedAt`, `company_id`, `department_id`, `auto_approve` FROM `' + + models.User.tableName + + '`' + ) }) - .then(() => queryInterface.dropTable( models.User.tableName )) - .then(() => queryInterface.renameTable('Users_backup', models.User.tableName)) + .then(() => queryInterface.dropTable(models.User.tableName)) + .then(() => + queryInterface.renameTable('Users_backup', models.User.tableName) + ) .then(() => queryInterface.sequelize.query('PRAGMA foreign_keys=on;')) - .then(() => queryInterface.addIndex(models.User.tableName, ['companyId'])) - - }); + .then(() => + queryInterface.addIndex(models.User.tableName, ['company_id']) + ) + ) + }) }, - down: function (queryInterface, Sequelize) { + down: function(queryInterface, Sequelize) { // No way back! - return Promise.resolve(); + return Promise.resolve() } -}; +} diff --git a/migrations/20171222-add-carry-over-allowance-column.js b/migrations/20171222-add-carry-over-allowance-column.js index 4c91e9a5e..048ecd1fb 100644 --- a/migrations/20171222-add-carry-over-allowance-column.js +++ b/migrations/20171222-add-carry-over-allowance-column.js @@ -1,28 +1,28 @@ +'use strict' -'use strict'; - -var models = require('../lib/model/db'); +const models = require('../lib/model/db') module.exports = { - up: function (queryInterface, Sequelize) { - - return queryInterface.describeTable('user_allowance_adjustment') - .then(function(attributes){ - + up: function(queryInterface, Sequelize) { + return queryInterface + .describeTable('user_allowance_adjustment') + .then(function(attributes) { if (attributes.hasOwnProperty('carried_over_allowance')) { - return 1; + return 1 } return queryInterface.addColumn( 'user_allowance_adjustment', 'carried_over_allowance', models.UserAllowanceAdjustment.attributes.carried_over_allowance - ); - }); + ) + }) }, - down: function (queryInterface, Sequelize) { - return queryInterface - .removeColumn('user_allowance_adjustment', 'carried_over_allowance'); + down: function(queryInterface, Sequelize) { + return queryInterface.removeColumn( + 'user_allowance_adjustment', + 'carried_over_allowance' + ) } -}; +} diff --git a/migrations/20171228-add-time-zone-field-to-company.js b/migrations/20171228-add-time-zone-field-to-company.js index f6236f614..37db9ef98 100644 --- a/migrations/20171228-add-time-zone-field-to-company.js +++ b/migrations/20171228-add-time-zone-field-to-company.js @@ -1,28 +1,23 @@ +'use strict' -'use strict'; - -var models = require('../lib/model/db'); +const models = require('../lib/model/db') module.exports = { - up: function (queryInterface, Sequelize) { - - return queryInterface.describeTable('Companies') - .then(function(attributes){ - - if (attributes.hasOwnProperty('timezone')) { - return 1; - } + up: function(queryInterface, Sequelize) { + return queryInterface.describeTable('Companies').then(function(attributes) { + if (attributes.hasOwnProperty('timezone')) { + return 1 + } - return queryInterface.addColumn( - 'Companies', - 'timezone', - models.Company.attributes.timezone - ); - }); + return queryInterface.addColumn( + 'Companies', + 'timezone', + models.Company.attributes.timezone + ) + }) }, - down: function (queryInterface, Sequelize) { - return queryInterface - .removeColumn('Companies', 'timezone'); + down: function(queryInterface, Sequelize) { + return queryInterface.removeColumn('Companies', 'timezone') } -}; +} diff --git a/migrations/20180102-company-mode.js b/migrations/20180102-company-mode.js index 5cb5c6f80..3a7ba390c 100644 --- a/migrations/20180102-company-mode.js +++ b/migrations/20180102-company-mode.js @@ -1,27 +1,23 @@ +'use strict' -'use strict'; - -var models = require('../lib/model/db'); +const models = require('../lib/model/db') module.exports = { - up: function (queryInterface, Sequelize) { - - queryInterface.describeTable('Companies').then(function(attributes){ - + up: function(queryInterface, Sequelize) { + return queryInterface.describeTable('Companies').then(function(attributes) { if (attributes.hasOwnProperty('mode')) { - return 1; + return 1 } return queryInterface.addColumn( 'Companies', 'mode', models.Company.attributes.mode - ); - }); - + ) + }) }, - down: function (queryInterface, Sequelize) { - return queryInterface.removeColumn('Companies', 'mode'); + down: function(queryInterface, Sequelize) { + return queryInterface.removeColumn('Companies', 'mode') } -}; +} diff --git a/migrations/20180103-sort-order-for-leave-types.js b/migrations/20180103-sort-order-for-leave-types.js index 4899d3997..d7938c597 100644 --- a/migrations/20180103-sort-order-for-leave-types.js +++ b/migrations/20180103-sort-order-for-leave-types.js @@ -1,27 +1,25 @@ +'use strict' -'use strict'; - -var models = require('../lib/model/db'); +const models = require('../lib/model/db') module.exports = { - up: function (queryInterface, Sequelize) { - - queryInterface.describeTable('LeaveTypes').then(function(attributes){ - - if (attributes.hasOwnProperty('sort_order')) { - return 1; - } - - return queryInterface.addColumn( - 'LeaveTypes', - 'sort_order', - models.LeaveType.attributes.sort_order - ); - }); - + up: function(queryInterface, Sequelize) { + return queryInterface + .describeTable('LeaveTypes') + .then(function(attributes) { + if (attributes.hasOwnProperty('sort_order')) { + return 1 + } + + return queryInterface.addColumn( + 'LeaveTypes', + 'sort_order', + models.LeaveType.attributes.sort_order + ) + }) }, - down: function (queryInterface, Sequelize) { - return queryInterface.removeColumn('LeaveTypes', 'sort_order'); + down: function(queryInterface, Sequelize) { + return queryInterface.removeColumn('LeaveTypes', 'sort_order') } -}; +} diff --git a/migrations/20180427-add-is_accrued_allowance-to-department.js b/migrations/20180427-add-is_accrued_allowance-to-department.js index ae3525eab..ae9dbff3d 100644 --- a/migrations/20180427-add-is_accrued_allowance-to-department.js +++ b/migrations/20180427-add-is_accrued_allowance-to-department.js @@ -1,28 +1,25 @@ +'use strict' -'use strict'; - -var models = require('../lib/model/db'); +const models = require('../lib/model/db') module.exports = { - up: function (queryInterface, Sequelize) { - - return queryInterface.describeTable('Departments') - .then(function(attributes){ - + up: function(queryInterface, Sequelize) { + return queryInterface + .describeTable('Departments') + .then(function(attributes) { if (attributes.hasOwnProperty('is_accrued_allowance')) { - return 1; + return 1 } return queryInterface.addColumn( 'Departments', 'is_accrued_allowance', models.Department.attributes.is_accrued_allowance - ); - }); + ) + }) }, - down: function (queryInterface, Sequelize) { - return queryInterface - .removeColumn('Departments', 'is_accrued_allowance'); + down: function(queryInterface, Sequelize) { + return queryInterface.removeColumn('Departments', 'is_accrued_allowance') } -}; +} diff --git a/migrations/20181119-integration-api-token-per-company.js b/migrations/20181119-integration-api-token-per-company.js index ea55ab084..e7e50cd66 100644 --- a/migrations/20181119-integration-api-token-per-company.js +++ b/migrations/20181119-integration-api-token-per-company.js @@ -1,40 +1,39 @@ +'use strict' -'use strict'; - -var models = require('../lib/model/db'); +const models = require('../lib/model/db') module.exports = { - up: (queryInterface, Sequelize) => { - - queryInterface.describeTable('Companies').then(attributes => { - - if (attributes.hasOwnProperty('integration_api_token')) { - return 1; - } - - return queryInterface.addColumn( - 'Companies', - 'integration_api_token', - models.Company.attributes.integration_api_token - ); - }); - - queryInterface.describeTable('Companies').then(attributes => { - - if (attributes.hasOwnProperty('integration_api_enabled')) { - return 1; - } - - return queryInterface.addColumn( - 'Companies', - 'integration_api_enabled', - models.Company.attributes.integration_api_enabled - ); - }); - - }, - - down: (queryInterface, Sequelize) => queryInterface - .removeColumn('Companies', 'integration_api_token') - .then(() => queryInterface.removeColumn('Companies', 'integration_api_enabled')), -}; + up: (queryInterface, Sequelize) => queryInterface + .describeTable('Companies') + .then(attributes => { + if (attributes.hasOwnProperty('integration_api_token')) { + return 1 + } + + return queryInterface.addColumn( + 'Companies', + 'integration_api_token', + models.Company.attributes.integration_api_token + ) + }) + .then(() => + queryInterface.describeTable('Companies').then(attributes => { + if (attributes.hasOwnProperty('integration_api_enabled')) { + return 1 + } + + return queryInterface.addColumn( + 'Companies', + 'integration_api_enabled', + models.Company.attributes.integration_api_enabled + ) + }) + ), + + down: (queryInterface, Sequelize) => + queryInterface + .removeColumn('Companies', 'integration_api_token') + .then(() => + queryInterface.removeColumn('Companies', 'integration_api_enabled') + ) +} diff --git a/migrations/20181213-carry-over-conf.js b/migrations/20181213-carry-over-conf.js index 18b1a4281..5338f3620 100644 --- a/migrations/20181213-carry-over-conf.js +++ b/migrations/20181213-carry-over-conf.js @@ -1,26 +1,21 @@ +'use strict' -'use strict'; - -const models = require('../lib/model/db'); +const models = require('../lib/model/db') module.exports = { - up: (queryInterface, Sequelize) => { - - queryInterface.describeTable('Companies').then((attributes) => { - + up: (queryInterface, Sequelize) => queryInterface.describeTable('Companies').then(attributes => { if (attributes.hasOwnProperty('carry_over')) { - return 1; + return 1 } return queryInterface.addColumn( 'Companies', 'carry_over', models.Company.attributes.carry_over - ); - }); - }, + ) + }), - down: function (queryInterface, Sequelize) { - return queryInterface.removeColumn('Companies', 'carry_over'); + down: function(queryInterface, Sequelize) { + return queryInterface.removeColumn('Companies', 'carry_over') } -}; +} diff --git a/migrations/20190118-change-type-value-for-api-token.js b/migrations/20190118-change-type-value-for-api-token.js new file mode 100644 index 000000000..3c29a1f66 --- /dev/null +++ b/migrations/20190118-change-type-value-for-api-token.js @@ -0,0 +1,43 @@ +'use strict' + +const models = require('../lib/model/db') + +module.exports = { + up: function(queryInterface, Sequelize) { + return queryInterface.describeTable('Companies').then(attributes => { + if (attributes.integration_api_token.type === 'UUID') { + return 1 + } + + return ( + queryInterface + // Create Temp Compaies based on current model definitiom + .createTable('Companies_backup', models.Company.attributes) + .then(() => + queryInterface.sequelize.query('PRAGMA foreign_keys=off;') + ) + .then(() => + queryInterface.sequelize.query( + 'INSERT INTO `Companies_backup` (`id`,`name`,`country`,`start_of_new_year`,`createdAt`,`updatedAt`,share_all_absences,ldap_auth_enabled,ldap_auth_config,`date_format`,`company_wide_message`,`mode`,`timezone`,`integration_api_token`,`integration_api_enabled`,`carry_over`) SELECT `id`,`name`,`country`,`start_of_new_year`,`createdAt`,`updatedAt`,share_all_absences,ldap_auth_enabled,ldap_auth_config,`date_format`,`company_wide_message`,`mode`,`timezone`,`integration_api_token`,`integration_api_enabled`,`carry_over` FROM `' + + models.Company.tableName + + '`' + ) + ) + .then(() => queryInterface.dropTable(models.Company.tableName)) + .then(() => + queryInterface.renameTable( + 'Companies_backup', + models.Company.tableName + ) + ) + .then(() => queryInterface.sequelize.query('PRAGMA foreign_keys=on;')) + .then(() => queryInterface.addIndex(models.Company.tableName, ['id'])) + ) + }) + }, + + down: function(queryInterface, Sequelize) { + // No way back! + return Promise.resolve() + } +} diff --git a/migrations/20190118-chnage-type-value-for-api-token.js b/migrations/20190118-chnage-type-value-for-api-token.js index 7ab0b7c8f..3c29a1f66 100644 --- a/migrations/20190118-chnage-type-value-for-api-token.js +++ b/migrations/20190118-chnage-type-value-for-api-token.js @@ -1,32 +1,43 @@ +'use strict' -'use strict'; - -const models = require('../lib/model/db'); +const models = require('../lib/model/db') module.exports = { - up: function (queryInterface, Sequelize) { - + up: function(queryInterface, Sequelize) { return queryInterface.describeTable('Companies').then(attributes => { - if (attributes.integration_api_token.type === 'UUID') { - return 1; + return 1 } - - return queryInterface - // Create Temp Compaies based on current model definitiom - .createTable('Companies_backup', models.Company.attributes) - .then(() => queryInterface.sequelize.query('PRAGMA foreign_keys=off;')) - .then(() => queryInterface.sequelize.query( - 'INSERT INTO `Companies_backup` (`id`,`name`,`country`,`start_of_new_year`,`createdAt`,`updatedAt`,share_all_absences,ldap_auth_enabled,ldap_auth_config,`date_format`,`company_wide_message`,`mode`,`timezone`,`integration_api_token`,`integration_api_enabled`,`carry_over`) SELECT `id`,`name`,`country`,`start_of_new_year`,`createdAt`,`updatedAt`,share_all_absences,ldap_auth_enabled,ldap_auth_config,`date_format`,`company_wide_message`,`mode`,`timezone`,`integration_api_token`,`integration_api_enabled`,`carry_over` FROM `'+models.Company.tableName+'`')) - .then(() => queryInterface.dropTable( models.Company.tableName )) - .then(() => queryInterface.renameTable('Companies_backup', models.Company.tableName)) - .then(() => queryInterface.sequelize.query('PRAGMA foreign_keys=on;')) - .then(() => queryInterface.addIndex(models.Company.tableName, ['id'])); - }); + + return ( + queryInterface + // Create Temp Compaies based on current model definitiom + .createTable('Companies_backup', models.Company.attributes) + .then(() => + queryInterface.sequelize.query('PRAGMA foreign_keys=off;') + ) + .then(() => + queryInterface.sequelize.query( + 'INSERT INTO `Companies_backup` (`id`,`name`,`country`,`start_of_new_year`,`createdAt`,`updatedAt`,share_all_absences,ldap_auth_enabled,ldap_auth_config,`date_format`,`company_wide_message`,`mode`,`timezone`,`integration_api_token`,`integration_api_enabled`,`carry_over`) SELECT `id`,`name`,`country`,`start_of_new_year`,`createdAt`,`updatedAt`,share_all_absences,ldap_auth_enabled,ldap_auth_config,`date_format`,`company_wide_message`,`mode`,`timezone`,`integration_api_token`,`integration_api_enabled`,`carry_over` FROM `' + + models.Company.tableName + + '`' + ) + ) + .then(() => queryInterface.dropTable(models.Company.tableName)) + .then(() => + queryInterface.renameTable( + 'Companies_backup', + models.Company.tableName + ) + ) + .then(() => queryInterface.sequelize.query('PRAGMA foreign_keys=on;')) + .then(() => queryInterface.addIndex(models.Company.tableName, ['id'])) + ) + }) }, - down: function (queryInterface, Sequelize) { + down: function(queryInterface, Sequelize) { // No way back! - return Promise.resolve(); + return Promise.resolve() } -}; +} diff --git a/migrations/20190502-entity-types.js b/migrations/20190502-entity-types.js new file mode 100644 index 000000000..dc81f7a7d --- /dev/null +++ b/migrations/20190502-entity-types.js @@ -0,0 +1,220 @@ +'use strict' + +const models = require('../lib/model/db') + +module.exports = { + up: async function(queryInterface, Sequelize) { + await queryInterface.describeTable('Comment').then(async attributes => { + if (attributes.entityType) { + await queryInterface.renameColumn( + 'Comment', + 'entityType', + 'entity_type' + ) + } + + if (attributes.entityId) { + await queryInterface.renameColumn('Comment', 'entityId', 'entity_id') + } + + if (attributes.companyId) { + await queryInterface.renameColumn('Comment', 'companyId', 'company_id') + } + }) + + await queryInterface.describeTable('Audit').then(async attributes => { + if (attributes.entityType) { + await queryInterface.renameColumn('Audit', 'entityType', 'entity_type') + } + + if (attributes.entityId) { + await queryInterface.renameColumn('Audit', 'entityId', 'entity_id') + } + + if (attributes.oldValue) { + await queryInterface.renameColumn('Audit', 'oldValue', 'old_value') + } + + if (attributes.newValue) { + await queryInterface.renameColumn('Audit', 'newValue', 'new_value') + } + }) + + await queryInterface.describeTable('Company').then(async attributes => { + if (attributes.companyId) { + await queryInterface.renameColumn('Company', 'companyId', 'company_id') + } + + if (attributes.DepartmentId) { + await queryInterface.renameColumn( + 'Company', + 'DepartmentId', + 'department_id' + ) + } + }) + + await queryInterface.describeTable('Department').then(async attributes => { + if (attributes.companyId) { + await queryInterface.renameColumn( + 'Department', + 'companyId', + 'company_id' + ) + } + + if (attributes.DepartmentId) { + await queryInterface.renameColumn( + 'Department', + 'DepartmentId', + 'department_id' + ) + } + + if (attributes.bossId) { + await queryInterface.renameColumn('Department', 'bossId', 'manager_id') + } + }) + + await queryInterface.describeTable('BankHoliday').then(async attributes => { + if (attributes.companyId) { + await queryInterface.renameColumn( + 'BankHoliday', + 'companyId', + 'company_id' + ) + } + + if (attributes.DepartmentId) { + await queryInterface.renameColumn( + 'BankHoliday', + 'DepartmentId', + 'department_id' + ) + } + }) + + await queryInterface + .describeTable('DepartmentSupervisor') + .then(async attributes => { + if (attributes.companyId) { + await queryInterface.renameColumn( + 'DepartmentSupervisor', + 'companyId', + 'company_id' + ) + } + + if (attributes.DepartmentId) { + await queryInterface.renameColumn( + 'DepartmentSupervisor', + 'DepartmentId', + 'department_id' + ) + } + }) + + await queryInterface.describeTable('EmailAudit').then(async attributes => { + if (attributes.companyId) { + await queryInterface.renameColumn( + 'EmailAudit', + 'companyId', + 'company_id' + ) + } + + if (attributes.DepartmentId) { + await queryInterface.renameColumn( + 'EmailAudit', + 'DepartmentId', + 'department_id' + ) + } + }) + + await queryInterface.describeTable('Leave').then(async attributes => { + if (attributes.companyId) { + await queryInterface.renameColumn('Leave', 'companyId', 'company_id') + } + + if (attributes.DepartmentId) { + await queryInterface.renameColumn( + 'Leave', + 'DepartmentId', + 'department_id' + ) + } + }) + + await queryInterface.describeTable('LeaveType').then(async attributes => { + if (attributes.companyId) { + await queryInterface.renameColumn( + 'LeaveType', + 'companyId', + 'company_id' + ) + } + + if (attributes.DepartmentId) { + await queryInterface.renameColumn( + 'LeaveType', + 'DepartmentId', + 'department_id' + ) + } + }) + + await queryInterface.describeTable('Schedule').then(async attributes => { + if (attributes.companyId) { + await queryInterface.renameColumn('Schedule', 'companyId', 'company_id') + } + + if (attributes.DepartmentId) { + await queryInterface.renameColumn( + 'Schedule', + 'DepartmentId', + 'department_id' + ) + } + }) + + await queryInterface.describeTable('User').then(async attributes => { + if (attributes.companyId) { + await queryInterface.renameColumn('User', 'companyId', 'company_id') + } + + if (attributes.DepartmentId) { + await queryInterface.renameColumn( + 'User', + 'DepartmentId', + 'department_id' + ) + } + }) + + await queryInterface + .describeTable('UserAllowanceAdjustment') + .then(async attributes => { + if (attributes.companyId) { + await queryInterface.renameColumn( + 'UserAllowanceAdjustment', + 'companyId', + 'company_id' + ) + } + + if (attributes.DepartmentId) { + await queryInterface.renameColumn( + 'UserAllowanceAdjustment', + 'DepartmentId', + 'department_id' + ) + } + }) + }, + + down: function(queryInterface, Sequelize) { + // No way back! + return Promise.resolve() + } +} diff --git a/migrations/20190629-add-is_team_view_hidden_field.js b/migrations/20190629-add-is_team_view_hidden_field.js index 8ec5f7863..a82a1d365 100644 --- a/migrations/20190629-add-is_team_view_hidden_field.js +++ b/migrations/20190629-add-is_team_view_hidden_field.js @@ -1,25 +1,22 @@ +'use strict' -'use strict'; - -var models = require('../lib/model/db'); +const models = require('../lib/model/db') module.exports = { up: (queryInterface, Sequelize) => { - queryInterface.describeTable('Companies').then(attributes => { - if (attributes.hasOwnProperty('is_team_view_hidden')) { - return 1; + return 1 } return queryInterface.addColumn( 'Companies', 'is_team_view_hidden', models.Company.attributes.is_team_view_hidden - ); - }); + ) + }) }, - down: (queryInterface, Sequelize) => queryInterface - .removeColumn('Companies', 'is_team_view_hidden'), -}; + down: (queryInterface, Sequelize) => + queryInterface.removeColumn('Companies', 'is_team_view_hidden') +} diff --git a/migrations/20191030-compress-email-audit.js b/migrations/20191030-compress-email-audit.js index e04560fa2..46dccad69 100644 --- a/migrations/20191030-compress-email-audit.js +++ b/migrations/20191030-compress-email-audit.js @@ -1,18 +1,16 @@ +'use strict' -'use strict'; - -const - htmlToText = require('html-to-text'), - Promise = require('bluebird'), - models = require('../lib/model/db'); +const htmlToText = require('html-to-text'); + const Promise = require('bluebird'); + const models = require('../lib/model/db') module.exports = { - up: () => { - return models.EmailAudit.findAll() - .map(rec => rec.update({body : htmlToText.fromString(rec.body)}), {concurrency: 1}) - .then(() => console.log('Done!')); - }, + up: () => models.EmailAudit.findAll() + .map(rec => rec.update({ body: htmlToText.fromString(rec.body) }), { + concurrency: 1 + }) + .then(() => console.log('Done!')), // Do nothing - down: () => Promise.resolve(), -}; + down: () => Promise.resolve() +} diff --git a/migrations/20200204185448-add_auto_approve_flag_to_leave_type.js b/migrations/20200204185448-add_auto_approve_flag_to_leave_type.js index e504225de..201edd8ce 100644 --- a/migrations/20200204185448-add_auto_approve_flag_to_leave_type.js +++ b/migrations/20200204185448-add_auto_approve_flag_to_leave_type.js @@ -1,26 +1,23 @@ -'use strict'; +'use strict' -var models = require('../lib/model/db'); +const models = require('../lib/model/db') module.exports = { - up: function (queryInterface, Sequelize) { - - queryInterface.describeTable('LeaveTypes').then(function(attributes){ - + up: function(queryInterface, Sequelize) { + queryInterface.describeTable('LeaveTypes').then(function(attributes) { if (attributes.hasOwnProperty('auto_approve')) { - return 1; + return 1 } return queryInterface.addColumn( 'LeaveTypes', 'auto_approve', models.LeaveType.attributes.auto_approve - ); - }); - + ) + }) }, - down: function (queryInterface, Sequelize) { - return queryInterface.removeColumn('LeaveTypes', 'auto_approve'); + down: function(queryInterface, Sequelize) { + return queryInterface.removeColumn('LeaveTypes', 'auto_approve') } -}; +} diff --git a/package-lock.json b/package-lock.json index 19b885741..7c7bb2a50 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,34 +1,9631 @@ { "name": "TimeOff.Management", "version": "1.0.0", - "lockfileVersion": 1, + "lockfileVersion": 2, "requires": true, + "packages": { + "": { + "name": "TimeOff.Management", + "version": "1.0.0", + "hasInstallScript": true, + "dependencies": { + "passport-local": "^1.0.0", + "joi": "~14.3.1", + "html-to-text": "^5.1.1", + "connect-session-sequelize": "6.0.0", + "express-handlebars": "^3.0.2", + "serve-favicon": "^2.5.0", + "ical-generator": "^1.7.1", + "passport-http-bearer": "^1.0.1", + "body-parser": "^1.19.0", + "nodemailer": "^6.1.1", + "csv": "~5.1.1", + "ldapauth-fork": "^4.2.0", + "cookie-parser": "^1.4.4", + "nodemailer-smtp-transport": "^2.7.4", + "optimist": "^0.6.1", + "underscore": "^1.9.1", + "moment": "^2.24.0", + "uuid": "^3.3.2", + "@handlebars/allow-prototype-access": "^1.0.5", + "morgan": "^1.9.1", + "bluebird": "^3.5.4", + "debug": "~4.1.1", + "sequelize-cli": "5.4.0", + "passport": "^0.4.0", + "nconf": "^0.10.0", + "formidable": "~1.2.1", + "passport-google-oauth20": "^1.0.0", + "@slack/client": "^4.1.0", + "validator": "^13.11.0", + "node-uuid": "^1.4.8", + "express": "^4.16.4", + "multer": "^1.4.1", + "express-session": "^1.16.1", + "connect-redis": "^6.0.0", + "sequelize": "^5.8.2", + "moment-timezone": "^0.5.25" + }, + "devDependencies": { + "chai": "^4.2.0", + "eslint": "^8.51.0", + "eslint-config-prettier": "^9.0.0", + "eslint-config-standard": "^17.1.0", + "eslint-plugin-import": "^2.28.1", + "eslint-plugin-mocha": "^10.2.0", + "eslint-plugin-n": "^16.2.0", + "eslint-plugin-promise": "^6.1.1", + "mocha": "^6.2.2", + "node-sass": "^8.0.0", + "prettier": "1.17.0", + "request-promise": "^4.2.4", + "selenium-webdriver": "^3.6.0" + }, + "engines": { + "node": ">=16.0.0" + }, + "optionalDependencies": { + "mysql2": "^1.6.4", + "redis": "^3.1.2", + "sqlite3": "^5.1.6" + } + }, + "node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/base64url": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/base64url/-/base64url-3.0.1.tgz", + "integrity": "sha512-ir1UPr3dkwexU7FdV8qBBbNDRUhMmIekYMFZfi+C/sLNnRESKPl23nB9b2pltqfOQNnGzsDdId90AEtG5tCx4A==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/detect-libc": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.2.tgz", + "integrity": "sha512-UX6sGumvvqSaXgdKGUsgZWqcUyIXZ/vZTrlRT/iobiKhGL0zL4d3osHj3uqllWJK+i+sixDS/3COVEOFbupFyw==", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/html-to-text": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/html-to-text/-/html-to-text-5.1.1.tgz", + "integrity": "sha512-Bci6bD/JIfZSvG4s0gW/9mMKwBRoe/1RWLxUME/d6WUSZCdY7T60bssf/jFf7EYXRyqU4P5xdClVqiYU0/ypdA==", + "dependencies": { + "he": "^1.2.0", + "htmlparser2": "^3.10.1", + "lodash": "^4.17.11", + "minimist": "^1.2.0" + }, + "bin": { + "html-to-text": "bin/cli.js" + }, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "optional": true + }, + "node_modules/invert-kv": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", + "integrity": "sha512-xgs2NH9AE66ucSq4cNG1nhSFghr5l6tdL15Pk+jl46bmmBapgoaY/AacXyaDznAqmGL99TiLSQgO/XazFSKYeQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dependencies": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/sequelize-cli/node_modules/wrap-ansi/node_modules/string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha512-0XsVpQLnVCXHJfyEs8tC0zpTVIr5PKKsQtkT29IwupnPTjtPmQ3xT/4yCREF9hYkV/3M3kzcUTSAZT6a6h81tw==", + "dependencies": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/finalhandler/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/node-gyp/node_modules/@npmcli/fs": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-1.1.1.tgz", + "integrity": "sha512-8KG5RD0GVP4ydEzRn/I4BNDuxDtqVbOdm8675T49OIG/NGhaK0pjPX7ZcDlvKYbA+ulvVK3ztfcF4uBdOxuJbQ==", + "devOptional": true, + "dependencies": { + "@gar/promisify": "^1.0.1", + "semver": "^7.3.5" + } + }, + "node_modules/express/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/event-emitter": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", + "integrity": "sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA==", + "dependencies": { + "d": "1", + "es5-ext": "~0.10.14" + } + }, + "node_modules/sequelize/node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/nodemailer-smtp-transport": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/nodemailer-smtp-transport/-/nodemailer-smtp-transport-2.7.4.tgz", + "integrity": "sha512-1e86YhJ633OZWk3OHWS5TpuoYXG/LtY2/RzNiB5+EkFifDdqHCNHBnExd5cobx0ZSHJLNGM8EKnDuHRFIjFi6Q==", + "dependencies": { + "nodemailer-shared": "1.1.0", + "nodemailer-wellknown": "0.1.10", + "smtp-connection": "2.12.0" + } + }, + "node_modules/gauge": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-4.0.4.tgz", + "integrity": "sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==", + "devOptional": true, + "dependencies": { + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.3", + "console-control-strings": "^1.1.0", + "has-unicode": "^2.0.1", + "signal-exit": "^3.0.7", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.5" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/mocha/node_modules/debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "deprecated": "Debug versions >=3.2.0 <3.2.7 || >=4 <4.3.1 have a low-severity ReDos regression when used in a Node.js environment. It is recommended you upgrade to 3.2.7 or 4.3.1. (https://github.com/visionmedia/debug/issues/797)", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/internal-slot": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.5.tgz", + "integrity": "sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==", + "dependencies": { + "get-intrinsic": "^1.2.0", + "has": "^1.0.3", + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/asap": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", + "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==" + }, + "node_modules/array.prototype.flatmap": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz", + "integrity": "sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/node-sass": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/node-sass/-/node-sass-8.0.0.tgz", + "integrity": "sha512-jPzqCF2/e6JXw6r3VxfIqYc8tKQdkj5Z/BDATYyG6FL6b/LuYBNFGFVhus0mthcWifHm/JzBpKAd+3eXsWeK/A==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "async-foreach": "^0.1.3", + "chalk": "^4.1.2", + "cross-spawn": "^7.0.3", + "gaze": "^1.0.0", + "get-stdin": "^4.0.1", + "glob": "^7.0.3", + "lodash": "^4.17.15", + "make-fetch-happen": "^10.0.4", + "meow": "^9.0.0", + "nan": "^2.17.0", + "node-gyp": "^8.4.1", + "sass-graph": "^4.0.1", + "stdout-stream": "^1.4.0", + "true-case-path": "^2.2.1" + }, + "bin": { + "node-sass": "bin/node-sass" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q==", + "dev": true, + "peer": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/editorconfig/node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/eslint/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/flat": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/flat/-/flat-4.1.1.tgz", + "integrity": "sha512-FmTtBsHskrU6FJ2VxCnsDb84wu9zhmO3cUX2kGFb5tuwhfXxGciiT0oRY+cck35QmG+NmGh5eLz6lLCpWTqwpA==", + "dev": true, + "dependencies": { + "is-buffer": "~2.0.3" + }, + "bin": { + "flat": "cli.js" + } + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/tsconfig-paths": { + "version": "3.14.2", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.2.tgz", + "integrity": "sha512-o/9iXgCYc5L/JxCHPe3Hvh8Q/2xm5Z+p18PESBU6Ff33695QnCHBEjcytY2q19ua7Mbl/DavtBOLq+oG0RCL+g==", + "dev": true, + "dependencies": { + "@types/json5": "^0.0.29", + "json5": "^1.0.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" + } + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==", + "dev": true, + "peer": true + }, + "node_modules/cliui/node_modules/strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "dependencies": { + "ansi-regex": "^4.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/wkx": { + "version": "0.4.8", + "resolved": "https://registry.npmjs.org/wkx/-/wkx-0.4.8.tgz", + "integrity": "sha512-ikPXMM9IR/gy/LwiOSqWlSL3X/J5uk9EO2hHNRXS41eTLXaUFEVw9fn/593jW/tE5tedNg8YjT5HkCa4FqQZyQ==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/read-pkg-up/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/node-gyp/node_modules/make-fetch-happen": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-9.1.0.tgz", + "integrity": "sha512-+zopwDy7DNknmwPQplem5lAZX/eCOzSvSNNcSKm5eVwTkOBzoktEfXsa9L23J/GIRhxRsaxzkPEhrJEpE2F4Gg==", + "devOptional": true, + "dependencies": { + "minipass-flush": "^1.0.5", + "minipass-fetch": "^1.3.2", + "minipass": "^3.1.3", + "minipass-pipeline": "^1.2.4", + "is-lambda": "^1.0.1", + "lru-cache": "^6.0.0", + "http-cache-semantics": "^4.1.0", + "ssri": "^8.0.0", + "socks-proxy-agent": "^6.0.0", + "cacache": "^15.2.0", + "https-proxy-agent": "^5.0.0", + "promise-retry": "^2.0.1", + "minipass-collect": "^1.0.2", + "http-proxy-agent": "^4.0.1", + "agentkeepalive": "^4.1.3", + "negotiator": "^0.6.2" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "optional": true, + "dependencies": { + "semver": "^6.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/node-sass/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/node-gyp/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "devOptional": true + }, + "node_modules/p-retry": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-3.0.1.tgz", + "integrity": "sha512-XE6G4+YTTkT2a0UWb2kjZe8xNwf8bIbnqpc/IS/idOBVhyves0mK5OJgeocjx7q5pvX/6m23xuzVPYT1uGM73w==", + "dependencies": { + "retry": "^0.12.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/cli-color": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/cli-color/-/cli-color-1.4.0.tgz", + "integrity": "sha512-xu6RvQqqrWEo6MPR1eixqGPywhYBHRs653F9jfXB2Hx4jdM/3WxiNE1vppRmxtMIfl16SFYTpYlrnqH/HsK/2w==", + "dependencies": { + "ansi-regex": "^2.1.1", + "d": "1", + "es5-ext": "^0.10.46", + "es6-iterator": "^2.0.3", + "memoizee": "^0.4.14", + "timers-ext": "^0.1.5" + } + }, + "node_modules/hard-rejection": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/hard-rejection/-/hard-rejection-2.1.0.tgz", + "integrity": "sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@npmcli/fs/node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/eslint-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", + "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^2.0.0" + }, + "engines": { + "node": "^10.0.0 || ^12.0.0 || >= 14.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + }, + "peerDependencies": { + "eslint": ">=5" + } + }, + "node_modules/@eslint/eslintrc/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/handlebars": { + "version": "4.7.8", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz", + "integrity": "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==", + "dependencies": { + "minimist": "^1.2.5", + "neo-async": "^2.6.2", + "source-map": "^0.6.1", + "wordwrap": "^1.0.0" + }, + "bin": { + "handlebars": "bin/handlebars" + }, + "engines": { + "node": ">=0.4.7" + }, + "optionalDependencies": { + "uglify-js": "^3.1.4" + } + }, + "node_modules/builtins/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@mapbox/node-pre-gyp/node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "optional": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/deep-equal": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.1.tgz", + "integrity": "sha512-yd9c5AdiqVcR+JjcwUQb9DkhJc8ngNr0MahEBGvDiJw8puWab2yZlh+nkasOnZP+EGTAP6rRp2JzJhJZzvNF8g==", + "dependencies": { + "is-arguments": "^1.0.4", + "is-date-object": "^1.0.1", + "is-regex": "^1.0.4", + "object-is": "^1.0.1", + "object-keys": "^1.1.1", + "regexp.prototype.flags": "^1.2.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/nconf/node_modules/cliui": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", + "integrity": "sha512-0yayqDxWQbqk3ojkYqUKqaAQ6AfNKeKWRNA8kR0WXzAsdHpP4BIaOmMAG87JGuO6qcobyW4GjxHd9PmhEd+T9w==", + "dependencies": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wrap-ansi": "^2.0.0" + } + }, + "node_modules/make-fetch-happen/node_modules/lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" + }, + "node_modules/wrap-ansi/node_modules/string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "dependencies": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/nconf/node_modules/wrap-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "integrity": "sha512-vAaEaDM946gbNpH5pLVNR+vX2ht6n0Bt3GXwVB1AuAqZosOvHNF3P7wDnh8KLkSqgUh0uh77le7Owgoz+Z9XBw==", + "dependencies": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/are-we-there-yet": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-3.0.1.tgz", + "integrity": "sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg==", + "devOptional": true, + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/dicer/node_modules/string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ==" + }, + "node_modules/yargs-parser": { + "version": "13.1.2", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", + "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", + "dev": true, + "dependencies": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", + "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/diff": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", + "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", + "dev": true, + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/js-beautify/node_modules/nopt": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-6.0.0.tgz", + "integrity": "sha512-ZwLpbTgdhuZUnZzjd7nb1ZV+4DoiC6/sfiVKok72ym/4Tlf+DFdlHYmT2JPmcNNWV6Pi3SDf1kT+A4r9RTuT9g==", + "dependencies": { + "abbrev": "^1.0.0" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/eslint-plugin-import": { + "version": "2.28.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.28.1.tgz", + "integrity": "sha512-9I9hFlITvOV55alzoKBI+K9q74kv0iKMeY6av5+umsNwayt59fz692daGyjR+oStBQgx6nwR9rXldDev3Clw+A==", + "dev": true, + "dependencies": { + "semver": "^6.3.1", + "doctrine": "^2.1.0", + "object.values": "^1.1.6", + "is-glob": "^4.0.3", + "eslint-module-utils": "^2.8.0", + "array.prototype.flat": "^1.3.1", + "tsconfig-paths": "^3.14.2", + "eslint-import-resolver-node": "^0.3.7", + "object.groupby": "^1.0.0", + "array.prototype.flatmap": "^1.3.1", + "object.fromentries": "^2.0.6", + "debug": "^3.2.7", + "is-core-module": "^2.13.0", + "minimatch": "^3.1.2", + "has": "^1.0.3", + "array.prototype.findlastindex": "^1.2.2", + "array-includes": "^3.1.6" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8" + } + }, + "node_modules/decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eslint/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha512-nSVgobk4rv61R9PUSDtYt7mPVB2olxNR5RWJcAsH676/ef11bUZwvu7+RGYrYauVdDPcO519v68wRhXQtxsV9w==" + }, + "node_modules/string.prototype.trimstart": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.7.tgz", + "integrity": "sha512-NGhtDFu3jCEm7B4Fy0DpLewdJQOZcQ0rGbwQ/+stjnrp2i+rlKeCvos9hOIeCmqwratM47OBxY7uFZzjxHXmrg==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-negative-zero": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", + "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/@aashutoshrathi/word-wrap": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", + "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/p-is-promise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-2.1.0.tgz", + "integrity": "sha512-Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/cacache/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, + "node_modules/@slack/client": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/@slack/client/-/client-4.12.0.tgz", + "integrity": "sha512-ltbdkcIWk2eIptCCT/oPmeCGlG8xb3kXfwuPTtvNujioLMo2xXqiPdfl7xK+AeUfnvj3fJLYbpTPuBTscuhgzw==", + "deprecated": "Slack Client is deprecated - Use @slack/web-api, @slack/rtm-api, or @slack/webhook instead.", + "dependencies": { + "retry": "^0.12.0", + "@types/p-cancelable": "^1.0.0", + "p-retry": "^3.0.1", + "object.values": "^1.1.0", + "axios": "^0.18.0", + "@types/retry": "^0.12.0", + "@types/is-stream": "^1.1.0", + "@types/p-queue": "^2.3.2", + "is-stream": "^1.1.0", + "@types/node": ">=6.0.0", + "finity": "^0.5.4", + "@types/form-data": "^2.2.1", + "p-queue": "^2.4.2", + "object.entries": "^1.1.0", + "p-cancelable": "~1.0.0", + "eventemitter3": "^3.1.0", + "@types/p-retry": "^3.0.0", + "@types/ws": "^5.1.1", + "object.getownpropertydescriptors": "^2.0.3", + "ws": "^5.2.0", + "form-data": "^2.3.3" + }, + "engines": { + "node": ">= 6.9.0", + "npm": ">= 3.10.8" + } + }, + "node_modules/eslint": { + "version": "8.51.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.51.0.tgz", + "integrity": "sha512-2WuxRZBrlwnXi+/vFSJyjMqrNjtJqiasMzehF0shoLaW7DzS3/9Yvrmq5JiT66+pNjiX4UBnLDiKHcWAr/OInA==", + "dev": true, + "dependencies": { + "ignore": "^5.2.0", + "eslint-scope": "^7.2.2", + "js-yaml": "^4.1.0", + "natural-compare": "^1.4.0", + "doctrine": "^3.0.0", + "file-entry-cache": "^6.0.1", + "is-glob": "^4.0.0", + "lodash.merge": "^4.6.2", + "eslint-visitor-keys": "^3.4.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0", + "espree": "^9.6.1", + "imurmurhash": "^0.1.4", + "cross-spawn": "^7.0.2", + "@eslint/eslintrc": "^2.1.2", + "graphemer": "^1.4.0", + "is-path-inside": "^3.0.3", + "@nodelib/fs.walk": "^1.2.8", + "@eslint-community/regexpp": "^4.6.1", + "@humanwhocodes/module-importer": "^1.0.1", + "@eslint-community/eslint-utils": "^4.2.0", + "chalk": "^4.0.0", + "debug": "^4.3.2", + "ajv": "^6.12.4", + "@humanwhocodes/config-array": "^0.11.11", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "esutils": "^2.0.2", + "globals": "^13.19.0", + "minimatch": "^3.1.2", + "glob-parent": "^6.0.2", + "fast-deep-equal": "^3.1.3", + "esquery": "^1.4.2", + "find-up": "^5.0.0", + "optionator": "^0.9.3", + "escape-string-regexp": "^4.0.0", + "@eslint/js": "8.51.0" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/get-symbol-description": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", + "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/spdx-exceptions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", + "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", + "dev": true + }, + "node_modules/morgan": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.10.0.tgz", + "integrity": "sha512-AbegBVI4sh6El+1gNwvD5YIck7nSA36weD7xvIxG4in80j/UoK8AEGaWnnz8v1GxonMCltmlNs5ZKbGvl9b1XQ==", + "dependencies": { + "basic-auth": "~2.0.1", + "debug": "2.6.9", + "depd": "~2.0.0", + "on-finished": "~2.3.0", + "on-headers": "~1.0.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/typed-array-byte-length": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.0.tgz", + "integrity": "sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA==", + "dependencies": { + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "has-proto": "^1.0.1", + "is-typed-array": "^1.1.10" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/nconf/node_modules/string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha512-0XsVpQLnVCXHJfyEs8tC0zpTVIr5PKKsQtkT29IwupnPTjtPmQ3xT/4yCREF9hYkV/3M3kzcUTSAZT6a6h81tw==", + "dependencies": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/hosted-git-info": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", + "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/serve-favicon": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/serve-favicon/-/serve-favicon-2.5.0.tgz", + "integrity": "sha512-FMW2RvqNr03x+C0WxTyu6sOv21oOjkq5j8tjquWccwa6ScNyGFOGJVpuS1NmTVGBAHS07xnSKotgf2ehQmf9iA==", + "dependencies": { + "etag": "~1.8.1", + "fresh": "0.5.2", + "ms": "2.1.1", + "parseurl": "~1.3.2", + "safe-buffer": "5.1.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/sequelize-pool": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/sequelize-pool/-/sequelize-pool-2.3.0.tgz", + "integrity": "sha512-Ibz08vnXvkZ8LJTiUOxRcj1Ckdn7qafNZ2t59jYHMX1VIebTAOYefWdRYFt6z6+hy52WGthAHAoLc9hvk3onqA==", + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/aggregate-error": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "devOptional": true, + "dependencies": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/espree": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "dev": true, + "dependencies": { + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/is-bluebird": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-bluebird/-/is-bluebird-1.0.2.tgz", + "integrity": "sha512-PDRu1vVip5dGQg5tfn2qVCCyxbBYu5MhYUJwSfL/RoGBI97n1fxvilVazxzptZW0gcmsMH17H4EVZZI5E/RSeA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/passport-oauth2": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/passport-oauth2/-/passport-oauth2-1.7.0.tgz", + "integrity": "sha512-j2gf34szdTF2Onw3+76alNnaAExlUmHvkc7cL+cmaS5NzHzDP/BvFHJruueQ9XAeNOdpI+CH+PWid8RA7KCwAQ==", + "dependencies": { + "base64url": "3.x.x", + "oauth": "0.9.x", + "passport-strategy": "1.x.x", + "uid2": "0.0.x", + "utils-merge": "1.x.x" + }, + "engines": { + "node": ">= 0.4.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/jaredhanson" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", + "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true + }, + "node_modules/concat-stream/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/eslint-module-utils": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.0.tgz", + "integrity": "sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==", + "dev": true, + "dependencies": { + "debug": "^3.2.7" + }, + "engines": { + "node": ">=4" + }, + "peerDependenciesMeta": { + "eslint": { + "optional": true + } + } + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "devOptional": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/mem": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/mem/-/mem-4.3.0.tgz", + "integrity": "sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w==", + "dependencies": { + "map-age-cleaner": "^0.1.1", + "mimic-fn": "^2.0.0", + "p-is-promise": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/selenium-webdriver/node_modules/rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, + "node_modules/performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==", + "dev": true, + "peer": true + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/joi": { + "version": "14.3.1", + "resolved": "https://registry.npmjs.org/joi/-/joi-14.3.1.tgz", + "integrity": "sha512-LQDdM+pkOrpAn4Lp+neNIFV3axv1Vna3j38bisbQhETPMANYRbFJFUyOZcOClYvM/hppMhGWuKSFEK9vjrB+bQ==", + "deprecated": "This module has moved and is now available at @hapi/joi. Please update your dependencies as this version is no longer maintained an may contain bugs and security issues.", + "dependencies": { + "hoek": "6.x.x", + "isemail": "3.x.x", + "topo": "3.x.x" + } + }, + "node_modules/sqlstring": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.3.tgz", + "integrity": "sha512-qC9iz2FlN7DQl3+wjwn3802RTyjCx7sDvfQEXchwa6CWOx07/WVfh91gBmQ9fahw8snwGEWU3xGzOt4tFyHLxg==", + "optional": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/generate-function": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.3.1.tgz", + "integrity": "sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==", + "optional": true, + "dependencies": { + "is-property": "^1.0.2" + } + }, + "node_modules/optimist/node_modules/wordwrap": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", + "integrity": "sha512-1tMA907+V4QmxV7dbRvb4/8MaRALK6q9Abid3ndMYnbyo8piisCmeONVqVSXqQA3KaP4SLt5b7ud6E2sqP8TFw==", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==", + "dev": true + }, + "node_modules/quick-lru": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-4.0.1.tgz", + "integrity": "sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/sequelize-cli/node_modules/wrap-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "integrity": "sha512-vAaEaDM946gbNpH5pLVNR+vX2ht6n0Bt3GXwVB1AuAqZosOvHNF3P7wDnh8KLkSqgUh0uh77le7Owgoz+Z9XBw==", + "dependencies": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz", + "integrity": "sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==", + "dependencies": { + "get-intrinsic": "^1.1.3", + "has": "^1.0.3", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/uid-safe": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz", + "integrity": "sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA==", + "dependencies": { + "random-bytes": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/editorconfig/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/minipass-fetch": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-2.1.2.tgz", + "integrity": "sha512-LT49Zi2/WMROHYoqGgdlQIZh8mLPZmOrN2NdJjMXxYe4nkN6FUyuPuOAOedNJDrx0IRGg9+4guZewtp8hE6TxA==", + "dev": true, + "dependencies": { + "minipass": "^3.1.6", + "minipass-sized": "^1.0.3", + "minizlib": "^2.1.2" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + }, + "optionalDependencies": { + "encoding": "^0.1.13" + } + }, + "node_modules/entities": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz", + "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==" + }, + "node_modules/sqlite3": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/sqlite3/-/sqlite3-5.1.6.tgz", + "integrity": "sha512-olYkWoKFVNSSSQNvxVUfjiVbz3YtBwTJj+mfV5zpHmqW3sELx2Cf4QCdirMelhM5Zh+KDVaKgQHqCxrqiWHybw==", + "hasInstallScript": true, + "optional": true, + "dependencies": { + "@mapbox/node-pre-gyp": "^1.0.0", + "node-addon-api": "^4.2.0", + "tar": "^6.1.11" + }, + "optionalDependencies": { + "node-gyp": "8.x" + }, + "peerDependencies": { + "node-gyp": "8.x" + }, + "peerDependenciesMeta": { + "node-gyp": { + "optional": true + } + } + }, + "node_modules/prettier": { + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-1.17.0.tgz", + "integrity": "sha512-sXe5lSt2WQlCbydGETgfm1YBShgOX4HxQkFPvbxkcwgDvGDeqVau8h+12+lmSVlP3rHPz0oavfddSZg/q+Szjw==", + "dev": true, + "bin": { + "prettier": "bin-prettier.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/@mapbox/node-pre-gyp/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "optional": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/regexp.prototype.flags": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.1.tgz", + "integrity": "sha512-sy6TXMN+hnP/wMy+ISxg3krXx7BAtWVO4UouuCN/ziM9UEne0euamVNafDfvC83bRNr95y0V5iijeDQFUNpvrg==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "set-function-name": "^2.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/nconf/node_modules/camelcase": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", + "integrity": "sha512-DLIsRzJVBQu72meAKPkWQOLcujdXT32hwdfnkI1frSiSRMK1MofjKHf+MEx0SB6fjEFXL8fBDv1dKymBlOp4Qw==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@types/minimist": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.3.tgz", + "integrity": "sha512-ZYFzrvyWUNhaPomn80dsMNgMeXxNWZBdkuG/hWlUvXvbdUH8ZERNBGXnU87McuGcWDsyzX2aChCv/SVN348k3A==", + "dev": true + }, + "node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "optional": true, + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/eslint-import-resolver-node/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "engines": { + "node": ">=8" + } + }, + "node_modules/eslint/node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/execa/node_modules/cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dependencies": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + }, + "engines": { + "node": ">=4.8" + } + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/morgan/node_modules/on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/node-uuid": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.8.tgz", + "integrity": "sha512-TkCET/3rr9mUuRp+CpO7qfgT++aAxfDRaalQhwPFzI9BY/2rCDn6OfpZOVggi1AXfTPpfkTrg5f5WQx5G1uLxA==", + "deprecated": "Use uuid module instead", + "bin": { + "uuid": "bin/uuid" + } + }, + "node_modules/request": { + "version": "2.88.2", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", + "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", + "deprecated": "request has been deprecated, see https://github.com/request/request/issues/3142", + "dev": true, + "peer": true, + "dependencies": { + "isstream": "~0.1.2", + "oauth-sign": "~0.9.0", + "safe-buffer": "^5.1.2", + "is-typedarray": "~1.0.0", + "json-stringify-safe": "~5.0.1", + "performance-now": "^2.1.0", + "http-signature": "~1.2.0", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2", + "har-validator": "~5.1.3", + "extend": "~3.0.2", + "mime-types": "~2.1.19", + "tough-cookie": "~2.5.0", + "aws-sign2": "~0.7.0", + "caseless": "~0.12.0", + "aws4": "^1.8.0", + "forever-agent": "~0.6.1", + "combined-stream": "~1.0.6", + "form-data": "~2.3.2", + "qs": "~6.5.2" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/@mapbox/node-pre-gyp/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "optional": true + }, + "node_modules/serve-favicon/node_modules/safe-buffer": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", + "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==" + }, + "node_modules/minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "devOptional": true, + "dependencies": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/domutils": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.7.0.tgz", + "integrity": "sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==", + "dependencies": { + "dom-serializer": "0", + "domelementtype": "1" + } + }, + "node_modules/finity": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/finity/-/finity-0.5.4.tgz", + "integrity": "sha512-3l+5/1tuw616Lgb0QBimxfdd2TqaDGpfCBpfX6EqtFmqUV3FtQnVEX4Aa62DagYEqnsTIjZcTfbq9msDbXYgyA==" + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/eslint-plugin-n/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/stdout-stream/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-bigint": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", + "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "dependencies": { + "has-bigints": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.entries": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.7.tgz", + "integrity": "sha512-jCBs/0plmPsOnrKAfFQXRG2NFjlhZgjjcBLSmTnEhU8U6vVTsVe8ANeQJCHTl3gSsI4J+0emOoCgoKlmQPMgmA==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/eslint-plugin-import/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/get-func-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz", + "integrity": "sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/basic-auth/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/es6-weak-map": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.3.tgz", + "integrity": "sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==", + "dependencies": { + "d": "1", + "es5-ext": "^0.10.46", + "es6-iterator": "^2.0.3", + "es6-symbol": "^3.1.1" + } + }, + "node_modules/ldapjs": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/ldapjs/-/ldapjs-1.0.2.tgz", + "integrity": "sha512-Y8fRYFXOWWKBs9I2QRNXb0FncDcG0Gjc7YU6XI3kIV9hLMRaFKH5QHi2TZeB7FrpgXuabOgL0GdYALbssHxH5Q==", + "dependencies": { + "asn1": "0.2.3", + "assert-plus": "^1.0.0", + "backoff": "^2.5.0", + "bunyan": "^1.8.3", + "dashdash": "^1.14.0", + "ldap-filter": "0.2.2", + "once": "^1.4.0", + "vasync": "^1.6.4", + "verror": "^1.8.1" + }, + "bin": { + "ldapjs-add": "bin/ldapjs-add", + "ldapjs-compare": "bin/ldapjs-compare", + "ldapjs-delete": "bin/ldapjs-delete", + "ldapjs-modify": "bin/ldapjs-modify", + "ldapjs-search": "bin/ldapjs-search" + }, + "engines": { + "node": ">=0.10" + }, + "optionalDependencies": { + "dtrace-provider": "~0.8" + } + }, + "node_modules/concat-stream/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/body-parser/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/domhandler": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.2.tgz", + "integrity": "sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==", + "dependencies": { + "domelementtype": "1" + } + }, + "node_modules/available-typed-arrays": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", + "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/nodemailer-wellknown": { + "version": "0.1.10", + "resolved": "https://registry.npmjs.org/nodemailer-wellknown/-/nodemailer-wellknown-0.1.10.tgz", + "integrity": "sha512-/VV4mjAEjfm2fn0loUvrpjvugw5rgurNjPO4WU24CuVSoeumsyLOTgaEWG8WoGdPxh1biOAp5JxDoy1hlA2zsw==" + }, + "node_modules/request-promise-core": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.4.tgz", + "integrity": "sha512-TTbAfBBRdWD7aNNOoVOBH4pN/KigV6LyapYNNlAPA8JwbovRti1E88m3sYAwsLi5ryhPKsE9APwnjFTgdUjTpw==", + "dev": true, + "dependencies": { + "lodash": "^4.17.19" + }, + "engines": { + "node": ">=0.10.0" + }, + "peerDependencies": { + "request": "^2.34" + } + }, + "node_modules/is-symbol": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", + "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-boolean-object": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", + "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/js-beautify/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/js-base64": { + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.6.4.tgz", + "integrity": "sha512-pZe//GGmwJndub7ZghVHz7vjb2LgC1m8B07Au3eYqeqv9emhESByMXxaEgkUkEqJe87oBbSniGYoQNIBklc7IQ==", + "dev": true + }, + "node_modules/delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==", + "devOptional": true + }, + "node_modules/promise-retry": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", + "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", + "devOptional": true, + "dependencies": { + "err-code": "^2.0.2", + "retry": "^0.12.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/sequelize-cli/node_modules/wrap-ansi/node_modules/is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==", + "dependencies": { + "number-is-nan": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/array-buffer-byte-length": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz", + "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==", + "dependencies": { + "call-bind": "^1.0.2", + "is-array-buffer": "^3.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==", + "dev": true, + "peer": true, + "dependencies": { + "assert-plus": "^1.0.0" + } + }, + "node_modules/sequelize-cli/node_modules/os-locale": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.1.0.tgz", + "integrity": "sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==", + "dependencies": { + "execa": "^1.0.0", + "lcid": "^2.0.0", + "mem": "^4.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tar/node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "devOptional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/eslint-plugin-n": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-n/-/eslint-plugin-n-16.2.0.tgz", + "integrity": "sha512-AQER2jEyQOt1LG6JkGJCCIFotzmlcCZFur2wdKrp1JX2cNotC7Ae0BcD/4lLv3lUAArM9uNS8z/fsvXTd0L71g==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "builtins": "^5.0.1", + "eslint-plugin-es-x": "^7.1.0", + "get-tsconfig": "^4.7.0", + "ignore": "^5.2.4", + "is-core-module": "^2.12.1", + "minimatch": "^3.1.2", + "resolve": "^1.22.2", + "semver": "^7.5.3" + }, + "engines": { + "node": ">=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + }, + "peerDependencies": { + "eslint": ">=7.0.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "node_modules/growl": { + "version": "1.10.5", + "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", + "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", + "dev": true, + "engines": { + "node": ">=4.x" + } + }, + "node_modules/y18n": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==" + }, + "node_modules/axios": { + "version": "0.18.1", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.18.1.tgz", + "integrity": "sha512-0BfJq4NSfQXd+SkFdrvFbG7addhYSBA2mQwISr46pD6E5iqkWg02RAs8vyTT/j0RTnoYmeXauBuSv1qKwR179g==", + "deprecated": "Critical security vulnerability fixed in v0.21.1. For more information, see https://github.com/axios/axios/pull/3410", + "dependencies": { + "follow-redirects": "1.5.10", + "is-buffer": "^2.0.2" + } + }, + "node_modules/jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/@types/retry": { + "version": "0.12.3", + "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.3.tgz", + "integrity": "sha512-rkxEZUFIyDEZhC6EfHz6Hwos2zXewCOLBzhdgv7D55qu4OAySNwDZzxbaMpFI6XthdBa5oHhR5s6/9MSuTfw4g==" + }, + "node_modules/raw-body": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", + "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/read-pkg-up/node_modules/type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "devOptional": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, + "node_modules/array.prototype.findlastindex": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.3.tgz", + "integrity": "sha512-LzLoiOMAxvy+Gd3BAq3B7VeIgPdo+Q8hthvKtXybMvRV0jrXfJM/t8mw7nNlpEcVlVUnCnM2KSX4XU5HmpodOA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0", + "get-intrinsic": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/mocha/node_modules/minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/sequelize-cli/node_modules/cliui": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz", + "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==", + "dependencies": { + "string-width": "^2.1.1", + "strip-ansi": "^4.0.0", + "wrap-ansi": "^2.0.0" + } + }, + "node_modules/concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "engines": [ + "node >= 0.8" + ], + "dependencies": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, + "node_modules/is-regex": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/read-pkg/node_modules/normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, + "dependencies": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "node_modules/eslint-config-prettier": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.0.0.tgz", + "integrity": "sha512-IcJsTkJae2S35pRsRAwoCE+925rJJStOdkKnLVgtE+tEpqU0EVVM7OqrwxqgptKdX29NUwC82I5pXsGFIgSevw==", + "dev": true, + "bin": { + "eslint-config-prettier": "bin/cli.js" + }, + "peerDependencies": { + "eslint": ">=7.0.0" + } + }, + "node_modules/httpntlm": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/httpntlm/-/httpntlm-1.6.1.tgz", + "integrity": "sha512-Tcz3Ct9efvNqw3QdTl3h6IgRRlIQxwKkJELN/aAIGnzi2xvb3pDHdnMs8BrxWLV6OoT4DlVyhzSVhFt/tk0lIw==", + "dependencies": { + "httpreq": ">=0.4.22", + "underscore": "~1.7.0" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/csv-stringify": { + "version": "5.6.5", + "resolved": "https://registry.npmjs.org/csv-stringify/-/csv-stringify-5.6.5.tgz", + "integrity": "sha512-PjiQ659aQ+fUTQqSrd1XEDnOr52jh30RBurfzkscaE2tPaFsDH5wOAHJiw8XAHphRknCwMUE9KRayc4K/NbO8A==" + }, + "node_modules/sequelize/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/eslint-import-resolver-node": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", + "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==", + "dev": true, + "dependencies": { + "debug": "^3.2.7", + "is-core-module": "^2.13.0", + "resolve": "^1.22.4" + } + }, + "node_modules/find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dependencies": { + "locate-path": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/eslint/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "bin": { + "he": "bin/he" + } + }, + "node_modules/strip-ansi/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-property": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", + "integrity": "sha512-Ks/IoX00TtClbGQr4TWXemAnktAQvYB7HzcCxDGqEZU6oCmb2INHuOoKxbtR+HFkmYWBKv/dOZtGRiAjDhj92g==", + "optional": true + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, + "node_modules/@mapbox/node-pre-gyp/node_modules/gauge": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz", + "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==", + "optional": true, + "dependencies": { + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.2", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.1", + "object-assign": "^4.1.1", + "signal-exit": "^3.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/tar/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "devOptional": true + }, + "node_modules/node-environment-flags": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/node-environment-flags/-/node-environment-flags-1.0.5.tgz", + "integrity": "sha512-VNYPRfGfmZLx0Ye20jWzHUjyTW/c+6Wq+iLhDzUI4XmhrDd9l/FozXV3F2xOaXjvp0co0+v1YSR3CMP6g+VvLQ==", + "dev": true, + "dependencies": { + "object.getownpropertydescriptors": "^2.0.3", + "semver": "^5.7.0" + } + }, + "node_modules/flat-cache/node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "dependencies": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/ldap-filter": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/ldap-filter/-/ldap-filter-0.2.2.tgz", + "integrity": "sha512-HDnDRNY/z0E3qljSjDWtu7xXCUdiXzwadz7m1jIwl3XHhPMrqUyurOd32YWH5IZ3zZMP4PrG7gKdRIB2uZHKGA==", + "dependencies": { + "assert-plus": "0.1.5" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true + }, + "node_modules/unique-filename": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-2.0.1.tgz", + "integrity": "sha512-ODWHtkkdx3IAR+veKxFV+VBkUMcN+FaqzUUd7IZzt+0zhDZFPFxhlqwPF3YQvMHx1TD0tdgYl+kuPnJ8E6ql7A==", + "dev": true, + "dependencies": { + "unique-slug": "^3.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/express-handlebars": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/express-handlebars/-/express-handlebars-3.1.0.tgz", + "integrity": "sha512-7QlaXnSREMmN5P2o4gmpUZDfJlLtfBka9d6r7/ccXaU7rPp76odw9YYtwZYdIiha2JqwiaG6o2Wu6NZJQ0u7Fg==", + "dependencies": { + "glob": "^7.1.3", + "graceful-fs": "^4.1.2", + "handlebars": "^4.1.2", + "object.assign": "^4.1.0", + "promise": "^8.0.2" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/jsprim": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz", + "integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==", + "dev": true, + "peer": true, + "dependencies": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.4.0", + "verror": "1.10.0" + }, + "engines": { + "node": ">=0.6.0" + } + }, + "node_modules/dicer": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/dicer/-/dicer-0.2.5.tgz", + "integrity": "sha512-FDvbtnq7dzlPz0wyYlOExifDEZcu8h+rErEXgfxqmLfRfC/kJidEFh4+effJRO3P0xmfqyPbSMG0LveNRfTKVg==", + "dependencies": { + "readable-stream": "1.1.x", + "streamsearch": "0.1.2" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==" + }, + "node_modules/nice-try": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==" + }, + "node_modules/node-gyp/node_modules/http-proxy-agent": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", + "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", + "devOptional": true, + "dependencies": { + "@tootallnate/once": "1", + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/nodemailer-fetch": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/nodemailer-fetch/-/nodemailer-fetch-1.6.0.tgz", + "integrity": "sha512-P7S5CEVGAmDrrpn351aXOLYs1R/7fD5NamfMCHyi6WIkbjS2eeZUB/TkuvpOQr0bvRZicVqo59+8wbhR3yrJbQ==" + }, + "node_modules/require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==" + }, + "node_modules/ip": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz", + "integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==", + "devOptional": true + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "engines": { + "node": ">=8" + } + }, + "node_modules/fastq": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", + "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", + "dev": true, + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/is-buffer": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz", + "integrity": "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "engines": { + "node": ">=4" + } + }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.11.11", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.11.tgz", + "integrity": "sha512-N2brEuAadi0CcdeMXUkhbZB84eskAc8MEX1By6qEchoVywSgXPIjou4rYsl0V3Hj0ZnuGycGCjdNgockbzeWNA==", + "dev": true, + "dependencies": { + "@humanwhocodes/object-schema": "^1.2.1", + "debug": "^4.1.1", + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/morgan/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "devOptional": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/eslint-plugin-n/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/read-pkg": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", + "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", + "dev": true, + "dependencies": { + "@types/normalize-package-data": "^2.4.0", + "normalize-package-data": "^2.5.0", + "parse-json": "^5.0.0", + "type-fest": "^0.6.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/csv-generate": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/csv-generate/-/csv-generate-3.4.3.tgz", + "integrity": "sha512-w/T+rqR0vwvHqWs/1ZyMDWtHHSJaN06klRqJXBEpDJaM/+dZkso0OKh1VcuuYvK3XM53KysVNq8Ko/epCK8wOw==" + }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/is-array-buffer": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz", + "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==", + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.0", + "is-typed-array": "^1.1.10" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/smtp-connection": { + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/smtp-connection/-/smtp-connection-2.12.0.tgz", + "integrity": "sha512-UP5jK4s5SGcUcqPN4U9ingqKt9mXYSKa52YhqxPuMecAnUOsVJpOmtgGaOm1urUBJZlzDt1M9WhZZkgbhxQlvg==", + "dependencies": { + "httpntlm": "1.6.1", + "nodemailer-shared": "1.1.0" + } + }, + "node_modules/promise-inflight": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", + "integrity": "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==", + "devOptional": true + }, + "node_modules/is-lambda": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz", + "integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==", + "devOptional": true + }, + "node_modules/http-cache-semantics": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", + "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==", + "devOptional": true + }, + "node_modules/pako": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", + "dev": true + }, + "node_modules/globule/node_modules/minimatch": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.8.tgz", + "integrity": "sha512-6FsRAQsxQ61mw+qP1ZzbL9Bc78x2p5OqNgNpnoAFLTrX8n5Kxph0CsnhmKKNXTWjXqU5L0pGPR7hYk+XWZr60Q==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/min-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", + "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "deprecated": "Debug versions >=3.2.0 <3.2.7 || >=4 <4.3.1 have a low-severity ReDos regression when used in a Node.js environment. It is recommended you upgrade to 3.2.7 or 4.3.1. (https://github.com/visionmedia/debug/issues/797)", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/jszip/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true + }, + "node_modules/@eslint/eslintrc/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@mapbox/node-pre-gyp": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz", + "integrity": "sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==", + "optional": true, + "dependencies": { + "detect-libc": "^2.0.0", + "https-proxy-agent": "^5.0.0", + "make-dir": "^3.1.0", + "node-fetch": "^2.6.7", + "nopt": "^5.0.0", + "npmlog": "^5.0.1", + "rimraf": "^3.0.2", + "semver": "^7.3.5", + "tar": "^6.1.11" + }, + "bin": { + "node-pre-gyp": "bin/node-pre-gyp" + } + }, + "node_modules/strip-indent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", + "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", + "dev": true, + "dependencies": { + "min-indent": "^1.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/oauth": { + "version": "0.9.15", + "resolved": "https://registry.npmjs.org/oauth/-/oauth-0.9.15.tgz", + "integrity": "sha512-a5ERWK1kh38ExDEfoO6qUHJb32rd7aYmPHuyCu3Fta/cnICvYmgd2uhuKXvPD+PXB+gCEYYEaQdIRAjCOwAKNA==" + }, + "node_modules/make-fetch-happen": { + "version": "10.2.1", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-10.2.1.tgz", + "integrity": "sha512-NgOPbRiaQM10DYXvN3/hhGVI2M5MtITFryzBGxHM5p4wnFxsVCbxkrBrDsk+EZ5OB4jEOT7AjDxtdF+KVEFT7w==", + "dev": true, + "dependencies": { + "minipass-flush": "^1.0.5", + "minipass-fetch": "^2.0.3", + "minipass": "^3.1.6", + "minipass-pipeline": "^1.2.4", + "is-lambda": "^1.0.1", + "lru-cache": "^7.7.1", + "http-cache-semantics": "^4.1.0", + "ssri": "^9.0.0", + "socks-proxy-agent": "^7.0.0", + "cacache": "^16.1.0", + "https-proxy-agent": "^5.0.0", + "promise-retry": "^2.0.1", + "minipass-collect": "^1.0.2", + "http-proxy-agent": "^5.0.0", + "agentkeepalive": "^4.2.1", + "negotiator": "^0.6.3" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.22.13", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz", + "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==", + "dev": true, + "dependencies": { + "@babel/highlight": "^7.22.13", + "chalk": "^2.4.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/assertion-error": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", + "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/@babel/highlight": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.20.tgz", + "integrity": "sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.22.20", + "chalk": "^2.4.2", + "js-tokens": "^4.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/minizlib/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "devOptional": true + }, + "node_modules/aws4": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.12.0.tgz", + "integrity": "sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg==", + "dev": true, + "peer": true + }, + "node_modules/commander": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", + "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", + "engines": { + "node": ">=14" + } + }, + "node_modules/node-gyp/node_modules/ssri": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.1.tgz", + "integrity": "sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ==", + "devOptional": true, + "dependencies": { + "minipass": "^3.1.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/shimmer": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/shimmer/-/shimmer-1.2.1.tgz", + "integrity": "sha512-sQTKC1Re/rM6XyFM6fIAGHRPVGvyXfgzIDvzoq608vM+jeyVD0Tu1E6Np0Kc2zAIFWIj963V2800iF/9LPieQw==" + }, + "node_modules/vasync": { + "version": "1.6.4", + "resolved": "https://registry.npmjs.org/vasync/-/vasync-1.6.4.tgz", + "integrity": "sha512-3oQMomVgQgHzNe5iKuT8PGOhMCQcg1wfh00Nh/Kl39ERdTlw/uNS7kbrhEraDMDKWHdDdc0iBFahPEd/Ft2b+A==", + "engines": [ + "node >=0.6.0" + ], + "dependencies": { + "verror": "1.6.0" + } + }, + "node_modules/tar/node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "devOptional": true, + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==" + }, + "node_modules/lcid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", + "integrity": "sha512-YiGkH6EnGrDGqLMITnGjXtGmNtjoXw9SVUzcaos8RBi7Ps0VBylkq+vOcY9QE5poLasPCR849ucFUkl0UzUyOw==", + "dependencies": { + "invert-kv": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/send/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/nodemailer-shared": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/nodemailer-shared/-/nodemailer-shared-1.1.0.tgz", + "integrity": "sha512-68xW5LSyPWv8R0GLm6veAvm7E+XFXkVgvE3FW0FGxNMMZqMkPFeGDVALfR1DPdSfcoO36PnW7q5AAOgFImEZGg==", + "dependencies": { + "nodemailer-fetch": "1.6.0" + } + }, + "node_modules/cacache/node_modules/glob": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "engines": { + "node": ">=0.4" + } + }, + "node_modules/node-gyp/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "devOptional": true + }, + "node_modules/morgan/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/psl": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", + "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==", + "dev": true + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "engines": { + "node": ">=6" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/ldap-filter/node_modules/assert-plus": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.1.5.tgz", + "integrity": "sha512-brU24g7ryhRwGCI2y+1dGQmQXiZF7TtIj583S96y0jjdajIe6wn8BuXyELYhvD22dtIxDQVFk04YTJwwdwOYJw==", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/unique-slug": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-3.0.0.tgz", + "integrity": "sha512-8EyMynh679x/0gqE9fT9oilG+qEt+ibFyqjuVTsZn1+CMxH+XLlpvr2UZx4nVcCwTpx81nICr2JQFkM+HPLq4w==", + "dev": true, + "dependencies": { + "imurmurhash": "^0.1.4" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/env-paths": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", + "devOptional": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/lie": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz", + "integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==", + "dev": true, + "dependencies": { + "immediate": "~3.0.5" + } + }, + "node_modules/chai": { + "version": "4.3.10", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.10.tgz", + "integrity": "sha512-0UXG04VuVbruMUYbJ6JctvH0YnC/4q3/AkT18q4NaITo91CUm0liMS9VqzT9vZhVQ/1eqPanMWjBM+Juhfb/9g==", + "dev": true, + "dependencies": { + "assertion-error": "^1.1.0", + "check-error": "^1.0.3", + "deep-eql": "^4.1.3", + "get-func-name": "^2.0.2", + "loupe": "^2.3.6", + "pathval": "^1.1.1", + "type-detect": "^4.0.8" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/passport-google-oauth20": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/passport-google-oauth20/-/passport-google-oauth20-1.0.0.tgz", + "integrity": "sha512-asv9bVBYf0F6OBP/17dBbHq74KpKVrIQLKPpPmUoR2Wwxv9ZlmNv6QpIX2m0VPkAilLtQeWewWESsqZeh7ZSWQ==", + "dependencies": { + "passport-oauth2": "1.x.x" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==", + "dev": true, + "peer": true, + "dependencies": { + "tweetnacl": "^0.14.3" + } + }, + "node_modules/locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dependencies": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/nconf/node_modules/strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==", + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/mkdirp": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.4.tgz", + "integrity": "sha512-iG9AK/dJLtJ0XNgTuDbSyNS3zECqDlAhnQW4CsNxBG3LQJBbHmRX1egw39DmtOdCAqY+dKXV+sgPgilNWUKMVw==", + "deprecated": "Legacy versions of mkdirp are no longer supported. Please update to mkdirp 1.x. (Note that the API surface has changed to use Promises in 1.x.)", + "dependencies": { + "minimist": "^1.2.5" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/@types/p-queue": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/@types/p-queue/-/p-queue-2.3.2.tgz", + "integrity": "sha512-eKAv5Ql6k78dh3ULCsSBxX6bFNuGjTmof5Q/T6PiECDq0Yf8IIn46jCyp3RJvCi8owaEmm3DZH1PEImjBMd/vQ==" + }, + "node_modules/wide-align/node_modules/string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "devOptional": true, + "dependencies": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/trim-newlines": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-3.0.1.tgz", + "integrity": "sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-sized": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz", + "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==", + "devOptional": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dev": true, + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/object-is": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.5.tgz", + "integrity": "sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "node_modules/editorconfig/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "node_modules/ext/node_modules/type": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/type/-/type-2.7.2.tgz", + "integrity": "sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw==" + }, + "node_modules/nconf": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/nconf/-/nconf-0.10.0.tgz", + "integrity": "sha512-fKiXMQrpP7CYWJQzKkPPx9hPgmq+YLDyxcG9N8RpiE9FoCkCbzD0NyW0YhE3xn3Aupe7nnDeIx4PFzYehpHT9Q==", + "dependencies": { + "async": "^1.4.0", + "ini": "^1.3.0", + "secure-keys": "^1.0.0", + "yargs": "^3.19.0" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/globalthis": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", + "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", + "dependencies": { + "define-properties": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==", + "dev": true, + "peer": true + }, + "node_modules/globals/node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/node-gyp/node_modules/unique-slug": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz", + "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==", + "devOptional": true, + "dependencies": { + "imurmurhash": "^0.1.4" + } + }, + "node_modules/redis-commands": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/redis-commands/-/redis-commands-1.7.0.tgz", + "integrity": "sha512-nJWqw3bTFy21hX/CPKHth6sfhZbdiHP6bTawSgQBlKOVRG7EZkfHbbHwQJnrE4vsQf0CMNE+3gJ4Fmm16vdVlQ==", + "optional": true + }, + "node_modules/serve-static": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", + "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", + "dependencies": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.18.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/@one-ini/wasm": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@one-ini/wasm/-/wasm-0.1.1.tgz", + "integrity": "sha512-XuySG1E38YScSJoMlqovLru4KTUNSjgVTIjyh7qMX6aNN5HY5Ct5LhRJdxO79JtTzKfzV/bnWpz+zquYrISsvw==" + }, + "node_modules/@mapbox/node-pre-gyp/node_modules/npmlog": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz", + "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==", + "optional": true, + "dependencies": { + "are-we-there-yet": "^2.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^3.0.0", + "set-blocking": "^2.0.0" + } + }, + "node_modules/npm-run-path": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", + "integrity": "sha512-lJxZYlT4DW/bRUtFh1MQIWqmLwQfAxnqWG4HhEdjMlkrJYnJn0Jrr2u3mgxqaWsdiBc76TYkTG/mhrnYTuzfHw==", + "dependencies": { + "path-key": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/which-typed-array": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.11.tgz", + "integrity": "sha512-qe9UWWpkeG5yzZ0tNYxDmd7vo58HDBc39mZ0xWWpolAGADdFOzkfamWLDxkOWcvHQKVmdTyQdLD4NOfjLWTKew==", + "dependencies": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/eslint-plugin-n/node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/object.fromentries": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.7.tgz", + "integrity": "sha512-UPbPHML6sL8PI/mOqPwsH4G6iyXcCGzLin8KvEPenOZN5lpCNBZZQ+V62vdjB1mQHrmqGQt5/OJzemUA+KJmEA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dependencies": { + "get-intrinsic": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/nconf/node_modules/is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==", + "dependencies": { + "number-is-nan": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/spdx-correct": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", + "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", + "dev": true, + "dependencies": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/@npmcli/move-file/node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@eslint/eslintrc/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/node-gyp": { + "version": "8.4.1", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-8.4.1.tgz", + "integrity": "sha512-olTJRgUtAb/hOXG0E93wZDs5YiJlgbXxTwQAFHyNlRsXQnYzUaF2aGgujZbw+hR8aF4ZG/rST57bWMWD16jr9w==", + "devOptional": true, + "dependencies": { + "env-paths": "^2.2.0", + "glob": "^7.1.4", + "graceful-fs": "^4.2.6", + "make-fetch-happen": "^9.1.0", + "nopt": "^5.0.0", + "npmlog": "^6.0.0", + "rimraf": "^3.0.2", + "semver": "^7.3.5", + "tar": "^6.1.2", + "which": "^2.0.2" + }, + "bin": { + "node-gyp": "bin/node-gyp.js" + }, + "engines": { + "node": ">= 10.12.0" + } + }, + "node_modules/execa/node_modules/path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==", + "engines": { + "node": ">=4" + } + }, + "node_modules/httpreq": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/httpreq/-/httpreq-1.1.1.tgz", + "integrity": "sha512-uhSZLPPD2VXXOSN8Cni3kIsoFHaU2pT/nySEU/fHr/ePbqHYr0jeiQRmUKLEirC09SFPsdMoA7LU7UXMd/w0Kw==", + "engines": { + "node": ">= 6.15.1" + } + }, + "node_modules/uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", + "bin": { + "uuid": "bin/uuid" + } + }, + "node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", + "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", + "dev": true + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" + }, + "node_modules/aproba": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", + "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==", + "devOptional": true + }, + "node_modules/is-weakref": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", + "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/esquery": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", + "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", + "dev": true, + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/js-beautify": { + "version": "1.14.9", + "resolved": "https://registry.npmjs.org/js-beautify/-/js-beautify-1.14.9.tgz", + "integrity": "sha512-coM7xq1syLcMyuVGyToxcj2AlzhkDjmfklL8r0JgJ7A76wyGMpJ1oA35mr4APdYNO/o/4YY8H54NQIJzhMbhBg==", + "dependencies": { + "config-chain": "^1.1.13", + "editorconfig": "^1.0.3", + "glob": "^8.1.0", + "nopt": "^6.0.0" + }, + "bin": { + "css-beautify": "js/bin/css-beautify.js", + "html-beautify": "js/bin/html-beautify.js", + "js-beautify": "js/bin/js-beautify.js" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" + }, + "node_modules/rimraf/node_modules/glob": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/glob/-/glob-6.0.4.tgz", + "integrity": "sha512-MKZeRNyYZAVVVG1oZeLaWie1uweH40m9AZwIwxyPbTSX4hHrVYSzLg0Ro5Z5R7XKkIX+Cc6oD1rqeDJnwsB8/A==", + "optional": true, + "dependencies": { + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "2 || 3", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + } + }, + "node_modules/csv": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/csv/-/csv-5.1.3.tgz", + "integrity": "sha512-uHPF5nxxFgcBQ/Mkicjh+IcQJeooIcN8gS/5mnvIdIccLh3Qf792jXE00ovdYDmABhE0yTMNCZgx3ZsBrR2GoQ==", + "dependencies": { + "csv-generate": "^3.2.3", + "csv-parse": "^4.4.6", + "csv-stringify": "^5.3.3", + "stream-transform": "^2.0.1" + }, + "engines": { + "node": ">= 0.1.90" + } + }, + "node_modules/yargs": { + "version": "13.3.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", + "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", + "dev": true, + "dependencies": { + "cliui": "^5.0.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^13.1.2" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "dev": true, + "peer": true + }, + "node_modules/for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "dependencies": { + "is-callable": "^1.1.3" + } + }, + "node_modules/sequelize-cli/node_modules/yargs": { + "version": "12.0.5", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-12.0.5.tgz", + "integrity": "sha512-Lhz8TLaYnxq/2ObqHDql8dX8CJi97oHxrjUcYtzKbbykPtVW9WB+poxI+NM2UIzsMgNCZTIf0AQwsjK5yMAqZw==", + "dependencies": { + "cliui": "^4.0.0", + "decamelize": "^1.2.0", + "find-up": "^3.0.0", + "get-caller-file": "^1.0.1", + "os-locale": "^3.0.0", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^2.0.0", + "which-module": "^2.0.0", + "y18n": "^3.2.1 || ^4.0.0", + "yargs-parser": "^11.1.1" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mv": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/mv/-/mv-2.1.1.tgz", + "integrity": "sha512-at/ZndSy3xEGJ8i0ygALh8ru9qy7gWW1cmkaqBN29JmMlIvM//MEO9y1sk/avxuwnPcfhkejkLsuPxH81BrkSg==", + "optional": true, + "dependencies": { + "mkdirp": "~0.5.1", + "ncp": "~2.0.0", + "rimraf": "~2.4.0" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/tmp": { + "version": "0.0.30", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.30.tgz", + "integrity": "sha512-HXdTB7lvMwcb55XFfrTM8CPr/IYREk4hVBFaQ4b/6nInrluSL86hfHm7vu0luYKCfyBZp2trCjpc8caC3vVM3w==", + "dev": true, + "dependencies": { + "os-tmpdir": "~1.0.1" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/seq-queue": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/seq-queue/-/seq-queue-0.0.5.tgz", + "integrity": "sha512-hr3Wtp/GZIc/6DAGPDcV4/9WoZhjrkXsi5B/07QgX8tsdc6ilr7BFM6PM6rbdAX1kFSDYeZGLipIZZKyQP0O5Q==", + "optional": true + }, + "node_modules/optimist": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", + "integrity": "sha512-snN4O4TkigujZphWLN0E//nQmm7790RYaE53DdL7ZYwee2D8DDo9/EyYiKUfN3rneWUjhJnueija3G9I2i0h3g==", + "dependencies": { + "minimist": "~0.0.1", + "wordwrap": "~0.0.2" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/inflection": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/inflection/-/inflection-1.12.0.tgz", + "integrity": "sha512-lRy4DxuIFWXlJU7ed8UiTJOSTqStqYdEb4CEbtXfNbkdj3nH1L+reUWiE10VWcJS2yR7tge8Z74pJjtBjNwj0w==", + "engines": [ + "node >= 0.4.0" + ] + }, + "node_modules/@npmcli/move-file": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-2.0.1.tgz", + "integrity": "sha512-mJd2Z5TjYWq/ttPLLGqArdtnC74J6bOzg4rMDnN+p1xTacZ2yPRCk2y0oSWQtygLR9YVQXgOcONrwtnk3JupxQ==", + "deprecated": "This functionality has been moved to @npmcli/fs", + "dev": true, + "dependencies": { + "mkdirp": "^1.0.4", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/yargs/node_modules/ansi-regex": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", + "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/cacache/node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true, + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/eslint-scope": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/long": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", + "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==", + "optional": true + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/ansi-colors": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.3.tgz", + "integrity": "sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/json-schema": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", + "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==", + "dev": true, + "peer": true + }, + "node_modules/body-parser": { + "version": "1.20.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", + "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", + "dependencies": { + "bytes": "3.1.2", + "content-type": "~1.0.5", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.11.0", + "raw-body": "2.5.2", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/sass-graph/node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/nconf/node_modules/yargs": { + "version": "3.32.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.32.0.tgz", + "integrity": "sha512-ONJZiimStfZzhKamYvR/xvmgW3uEkAUFSP91y2caTEPhzF6uP2JfPiVZcq66b/YR0C3uitxSV7+T1x8p5bkmMg==", + "dependencies": { + "camelcase": "^2.0.1", + "cliui": "^3.0.3", + "decamelize": "^1.1.1", + "os-locale": "^1.4.0", + "string-width": "^1.0.1", + "window-size": "^0.1.4", + "y18n": "^3.2.0" + } + }, + "node_modules/ignore": { + "version": "5.2.4", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", + "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" + }, + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/node-sass/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/log-symbols": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", + "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==", + "dev": true, + "dependencies": { + "chalk": "^2.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==", + "dependencies": { + "assert-plus": "^1.0.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "dev": true + }, + "node_modules/editorconfig/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/random-bytes": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz", + "integrity": "sha512-iv7LhNVO047HzYR3InF6pUcUsPQiHTM1Qal51DcGSuZFBil1aBBWG5eHPNek7bvILMaYJ/8RU1e8w1AMdHmLQQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/wrap-ansi/node_modules/strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "dependencies": { + "ansi-regex": "^4.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "node_modules/is-shared-array-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", + "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/p-defer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz", + "integrity": "sha512-wB3wfAxZpk2AzOfUMJNL+d36xothRSyj8EXOa4f6GMqYDN9BJaaSISbsk+wS9abmnebVw95C2Kb5t85UmpCxuw==", + "engines": { + "node": ">=4" + } + }, + "node_modules/eslint-module-utils/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/express-session/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/sequelize-cli/node_modules/wrap-ansi/node_modules/strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==", + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/builtins/node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@types/node": { + "version": "20.8.6", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.6.tgz", + "integrity": "sha512-eWO4K2Ji70QzKUqRy6oyJWUeB7+g2cRagT3T/nxYibYcT4y2BDL8lqolRXjTHmkZCdJfIPaY73KbJAZmcryxTQ==", + "dependencies": { + "undici-types": "~5.25.1" + } + }, + "node_modules/npm-run-path/node_modules/path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==", + "engines": { + "node": ">=4" + } + }, + "node_modules/mysql2/node_modules/iconv-lite": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.5.2.tgz", + "integrity": "sha512-kERHXvpSaB4aU3eANwidg79K8FlrN77m8G9V+0vOR3HYaRifrlwMEpT7ZBJqLSEIHnEgJTHcWK82wwLwwKwtag==", + "optional": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/smart-buffer": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", + "devOptional": true, + "engines": { + "node": ">= 6.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/pause": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz", + "integrity": "sha512-KG8UEiEVkR3wGEb4m5yZkVCzigAD+cVEJck2CzYZO37ZGJfctvVptVO192MwrtPhzONn6go8ylnOdMhKqi4nfg==" + }, + "node_modules/get-intrinsic": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz", + "integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==", + "dependencies": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.groupby": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.1.tgz", + "integrity": "sha512-HqaQtqLnp/8Bn4GL16cj+CUYbnpe1bh0TtEaWvybszDG4tgxCJuRpV8VGuvNaI1fAnI4lUJzDG55MXcOH4JZcQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "get-intrinsic": "^1.2.1" + } + }, + "node_modules/ical-generator": { + "version": "1.15.4", + "resolved": "https://registry.npmjs.org/ical-generator/-/ical-generator-1.15.4.tgz", + "integrity": "sha512-drXe4RLkfNlvDvdy/E6BUI9p+01L3ySK1ufNEYI9TxNKG9ZA3G60QWoZvD1dtmH4scwDxYu6/sZBPJvYVNrj8A==", + "dependencies": { + "moment-timezone": "^0.5.32" + }, + "engines": { + "node": ">=6.0.0" + }, + "peerDependencies": { + "@types/node": ">= 8.0.0" + } + }, + "node_modules/eslint/node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/es6-iterator": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", + "integrity": "sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==", + "dependencies": { + "d": "1", + "es5-ext": "^0.10.35", + "es6-symbol": "^3.1.1" + } + }, + "node_modules/@npmcli/move-file/node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true, + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/nconf/node_modules/y18n": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.2.tgz", + "integrity": "sha512-uGZHXkHnhF0XeeAPgnKfPv1bgKAYyVvmNL1xlKsPYZPaIHxGti2hHqvOCQv71XMsLxu1QjergkqogUnms5D3YQ==" + }, + "node_modules/uglify-js": { + "version": "3.17.4", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.17.4.tgz", + "integrity": "sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==", + "optional": true, + "bin": { + "uglifyjs": "bin/uglifyjs" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/es-array-method-boxes-properly": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz", + "integrity": "sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA==" + }, + "node_modules/editorconfig": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/editorconfig/-/editorconfig-1.0.4.tgz", + "integrity": "sha512-L9Qe08KWTlqYMVvMcTIvMAdl1cDUubzRNYL+WfA4bLDMHe4nemKkpmYzkznE1FwLKu0EEmy6obgQKzMJrg4x9Q==", + "dependencies": { + "@one-ini/wasm": "0.1.1", + "commander": "^10.0.0", + "minimatch": "9.0.1", + "semver": "^7.5.3" + }, + "bin": { + "editorconfig": "bin/editorconfig" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/cacache": { + "version": "16.1.3", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-16.1.3.tgz", + "integrity": "sha512-/+Emcj9DAXxX4cwlLmRI9c166RuL3w30zp4R7Joiv2cQTtTtA+jeuCAjH3ZlGnYS3tKENSrKhAzVVP9GVyzeYQ==", + "dev": true, + "dependencies": { + "minipass-flush": "^1.0.5", + "unique-filename": "^2.0.0", + "infer-owner": "^1.0.4", + "@npmcli/move-file": "^2.0.0", + "promise-inflight": "^1.0.1", + "tar": "^6.1.11", + "minipass": "^3.1.6", + "minipass-pipeline": "^1.2.4", + "lru-cache": "^7.7.1", + "ssri": "^9.0.0", + "chownr": "^2.0.0", + "mkdirp": "^1.0.4", + "minipass-collect": "^1.0.2", + "fs-minipass": "^2.1.0", + "@npmcli/fs": "^2.1.0", + "p-map": "^4.0.0", + "rimraf": "^3.0.2", + "glob": "^8.0.1" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/bluebird": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" + }, + "node_modules/retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", + "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", + "engines": { + "node": ">= 4" + } + }, + "node_modules/node-sass/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/true-case-path": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/true-case-path/-/true-case-path-2.2.1.tgz", + "integrity": "sha512-0z3j8R7MCjy10kc/g+qg7Ln3alJTodw9aDuVWZa3uiWqfuBMKeAeP2ocWcxoyM3D73yz3Jt/Pu4qPr4wHSdB/Q==", + "dev": true + }, + "node_modules/execa/node_modules/shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==", + "dependencies": { + "shebang-regex": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/editorconfig/node_modules/minimatch": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.1.tgz", + "integrity": "sha512-0jWhJpD/MdhPXwPuiRkCbfYfSKp2qnn2eOc279qI7f+osl/l+prKSrvhg157zSYvx/1nmgn2NqdT6k2Z7zSH9w==", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz", + "integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==" + }, + "node_modules/backoff": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/backoff/-/backoff-2.5.0.tgz", + "integrity": "sha512-wC5ihrnUXmR2douXmXLCe5O3zg3GKIyvRi/hi58a/XyRxVI+3/yM0PYueQOZXPXQ9pxBislYkw+sF9b7C/RuMA==", + "dependencies": { + "precond": "0.2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/passport-strategy": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/passport-strategy/-/passport-strategy-1.0.0.tgz", + "integrity": "sha512-CB97UUvDKJde2V0KDWWB3lyf6PC3FaZP7YxZ2G8OAtn9p4HI9j9JLP9qjOGZFvyl8uwNT8qM+hGnz/n16NI7oA==", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/punycode": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", + "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/function.prototype.name": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz", + "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "functions-have-names": "^1.2.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve": { + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/fs-extra": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", + "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", + "dependencies": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "engines": { + "node": ">=6 <7 || >=8" + } + }, + "node_modules/read-pkg-up/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/tough-cookie": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", + "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", + "dev": true, + "dependencies": { + "psl": "^1.1.28", + "punycode": "^2.1.1" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/umzug": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/umzug/-/umzug-2.3.0.tgz", + "integrity": "sha512-Z274K+e8goZK8QJxmbRPhl89HPO1K+ORFtm6rySPhFKfKc5GHhqdzD0SGhSWHkzoXasqJuItdhorSvY7/Cgflw==", + "dependencies": { + "bluebird": "^3.7.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/which-module": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.1.tgz", + "integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==" + }, + "node_modules/mysql2": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/mysql2/-/mysql2-1.7.0.tgz", + "integrity": "sha512-xTWWQPjP5rcrceZQ7CSTKR/4XIDeH/cRkNH/uzvVGQ7W5c7EJ0dXeJUusk7OKhIoHj7uFKUxDVSCfLIl+jluog==", + "optional": true, + "dependencies": { + "denque": "^1.4.1", + "generate-function": "^2.3.1", + "iconv-lite": "^0.5.0", + "long": "^4.0.0", + "lru-cache": "^5.1.1", + "named-placeholders": "^1.1.2", + "seq-queue": "^0.0.5", + "sqlstring": "^2.3.1" + }, + "engines": { + "node": ">= 8.0" + } + }, + "node_modules/eslint/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/flat-cache": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.1.1.tgz", + "integrity": "sha512-/qM2b3LUIaIgviBQovTLvijfyOQXPtSRnRK26ksj2J7rzPIecePUIpJsZ4T02Qg+xiAEKIs5K8dsHEd+VaKa/Q==", + "dev": true, + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.3", + "rimraf": "^3.0.2" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/@types/p-cancelable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@types/p-cancelable/-/p-cancelable-1.0.1.tgz", + "integrity": "sha512-MGdhuVx7X2yJe4dgOnDQcZQAYgiC/QK1O5HUPgTMTxWYiOlyWEO5DWmPBlXQBU1F6/JM7aSgYBDrpt7kurC6dw==", + "deprecated": "This is a stub types definition. p-cancelable provides its own type definitions, so you do not need this installed.", + "dependencies": { + "p-cancelable": "*" + } + }, + "node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==", + "engines": [ + "node >=0.6.0" + ] + }, + "node_modules/infer-owner": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", + "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", + "devOptional": true + }, + "node_modules/builtins": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/builtins/-/builtins-5.0.1.tgz", + "integrity": "sha512-qwVpFEHNfhYJIzNRBvd2C1kyo6jz3ZSMPyyuR47OPdiKWlbYnZNyDWuyR175qDnAJLiCo5fBBqPb3RiXgWlkOQ==", + "dev": true, + "dependencies": { + "semver": "^7.0.0" + } + }, + "node_modules/@types/events": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@types/events/-/events-3.0.1.tgz", + "integrity": "sha512-QfUFdKjGSc+iCf8OFZhqJKfDuqB6lP57kSMkPw8ba3yNDANicUwCdaPt5ytZ4nDXXVFxQkvT8v73I4stSVrCxA==" + }, + "node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "devOptional": true, + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/yargs/node_modules/emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "dev": true + }, + "node_modules/cliui/node_modules/string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "dependencies": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/node-gyp/node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "devOptional": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/cls-bluebird": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cls-bluebird/-/cls-bluebird-2.1.0.tgz", + "integrity": "sha512-XVb0RPmHQyy35Tz9z34gvtUcBKUK8A/1xkGCyeFc9B0C7Zr5SysgFaswRVdwI5NEMcO+3JKlIDGIOgERSn9NdA==", + "dependencies": { + "is-bluebird": "^1.0.2", + "shimmer": "^1.1.0" + } + }, + "node_modules/@types/form-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@types/form-data/-/form-data-2.5.0.tgz", + "integrity": "sha512-23/wYiuckYYtFpL+4RPWiWmRQH2BjFuqCUi2+N3amB1a1Drv+i/byTrGvlLwRVLFNAZbwpbQ7JvTK+VCAPMbcg==", + "deprecated": "This is a stub types definition. form-data provides its own type definitions, so you do not need this installed.", + "dependencies": { + "form-data": "*" + } + }, + "node_modules/cliui/node_modules/ansi-regex": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", + "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/node-addon-api": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-4.3.0.tgz", + "integrity": "sha512-73sE9+3UaLYYFmDsFZnqCInzPyh3MqIwZO9cw58yIqAZhONrrabrYyYe3TuIqtIiOuTXVhsGau8hcrhhwSsDIQ==", + "optional": true + }, + "node_modules/es-shim-unscopables": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz", + "integrity": "sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==", + "dev": true, + "dependencies": { + "has": "^1.0.3" + } + }, + "node_modules/has": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.4.tgz", + "integrity": "sha512-qdSAmqLF6209RFj4VVItywPMbm3vWylknmB3nvNiUIs72xAimcM8nVYxYr7ncvZq5qzk9MKIZR8ijqD/1QuYjQ==", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/minipass/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "devOptional": true + }, + "node_modules/@types/p-retry": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@types/p-retry/-/p-retry-3.0.1.tgz", + "integrity": "sha512-LkZCWg4JxFdQR/nGNZcMiyKAbNG3DKBRS6nn6Hg4dLS82zxkdBJJcvf4zXFvDCEI+e4dZdQX6wreqs9RDGMRfw==", + "deprecated": "This is a stub types definition. p-retry provides its own type definitions, so you do not need this installed.", + "dependencies": { + "p-retry": "*" + } + }, + "node_modules/es-abstract": { + "version": "1.22.2", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.2.tgz", + "integrity": "sha512-YoxfFcDmhjOgWPWsV13+2RNjq1F6UQnfs+8TftwNqtzlmFzEXvlUwdrNrYeaizfjQzRMxkZ6ElWMOJIFKdVqwA==", + "dependencies": { + "gopd": "^1.0.1", + "regexp.prototype.flags": "^1.5.1", + "object-keys": "^1.1.1", + "has-proto": "^1.0.1", + "is-array-buffer": "^3.0.2", + "es-set-tostringtag": "^2.0.1", + "internal-slot": "^1.0.5", + "typed-array-buffer": "^1.0.0", + "es-to-primitive": "^1.2.1", + "get-intrinsic": "^1.2.1", + "is-weakref": "^1.0.2", + "is-callable": "^1.2.7", + "string.prototype.trimend": "^1.0.7", + "available-typed-arrays": "^1.0.5", + "is-shared-array-buffer": "^1.0.2", + "object.assign": "^4.1.4", + "arraybuffer.prototype.slice": "^1.0.2", + "is-regex": "^1.1.4", + "is-typed-array": "^1.1.12", + "has-symbols": "^1.0.3", + "array-buffer-byte-length": "^1.0.0", + "string.prototype.trim": "^1.2.8", + "get-symbol-description": "^1.0.0", + "safe-regex-test": "^1.0.0", + "unbox-primitive": "^1.0.2", + "safe-array-concat": "^1.0.1", + "is-string": "^1.0.7", + "call-bind": "^1.0.2", + "function.prototype.name": "^1.1.6", + "typed-array-byte-length": "^1.0.0", + "object-inspect": "^1.12.3", + "has": "^1.0.3", + "globalthis": "^1.0.3", + "typed-array-length": "^1.0.4", + "which-typed-array": "^1.1.11", + "has-property-descriptors": "^1.0.0", + "typed-array-byte-offset": "^1.0.0", + "string.prototype.trimstart": "^1.0.7", + "is-negative-zero": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/busboy/node_modules/readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha512-+MeVjFf4L44XUkhM1eYbD8fyEsxcV81pqMSR5gblfcLCHfZvbrqy4/qYHE+/R5HoBUT11WV5O08Cr1n3YXkWVQ==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "node_modules/follow-redirects/node_modules/debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==", + "dev": true, + "peer": true, + "dependencies": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, + "node_modules/is-date-object": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", + "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==" + }, + "node_modules/dom-serializer/node_modules/domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ] + }, + "node_modules/define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "dependencies": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/redis-parser": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/redis-parser/-/redis-parser-3.0.0.tgz", + "integrity": "sha512-DJnGAeenTdpMEH6uAJRK/uiyEIH9WVsUmoLwzudwGJUwZPp80PDBWPHXSAGNPwNvIXAbe7MSUB1zQFugFml66A==", + "optional": true, + "dependencies": { + "redis-errors": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/eslint/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/err-code": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", + "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==", + "devOptional": true + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "node_modules/pathval": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", + "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/js-beautify/node_modules/glob": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/redent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", + "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", + "dev": true, + "dependencies": { + "indent-string": "^4.0.0", + "strip-indent": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/window-size": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.4.tgz", + "integrity": "sha512-2thx4pB0cV3h+Bw7QmMXcEbdmOzv9t0HFplJH/Lz6yu60hXYy5RT8rUu+wlIreVxWsGN20mo+MHeCSfUpQBwPw==", + "bin": { + "window-size": "cli.js" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/rimraf": { + "version": "2.4.5", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.4.5.tgz", + "integrity": "sha512-J5xnxTyqaiw06JjMftq7L9ouA448dw/E7dKghkP9WpKNuwmARNNg+Gk8/u5ryb9N/Yo2+z3MCwuqFK/+qPOPfQ==", + "optional": true, + "dependencies": { + "glob": "^6.0.1" + }, + "bin": { + "rimraf": "bin.js" + } + }, + "node_modules/@mapbox/node-pre-gyp/node_modules/are-we-there-yet": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz", + "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==", + "optional": true, + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/minipass-collect": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz", + "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", + "devOptional": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/vasync/node_modules/extsprintf": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.2.0.tgz", + "integrity": "sha512-T3PYC6HucmF4OfunfZb5d1nRvTSvWYhsr/Og33HANcCuCtGPUtWVyt/tTs8SU9sR0SGh5Z/xQCuX/D72ph2H+A==", + "engines": [ + "node >=0.6.0" + ] + }, + "node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/map-age-cleaner": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz", + "integrity": "sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==", + "dependencies": { + "p-defer": "^1.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==", + "dev": true, + "peer": true, + "engines": { + "node": "*" + } + }, + "node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "devOptional": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/sshpk": { + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.17.0.tgz", + "integrity": "sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ==", + "dev": true, + "peer": true, + "dependencies": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + }, + "bin": { + "sshpk-conv": "bin/sshpk-conv", + "sshpk-sign": "bin/sshpk-sign", + "sshpk-verify": "bin/sshpk-verify" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/globule": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/globule/-/globule-1.3.4.tgz", + "integrity": "sha512-OPTIfhMBh7JbBYDpa5b+Q5ptmMWKwcNcFSR/0c6t8V4f3ZAVBEsKNY37QdVqmLRYSMhOUGYrY0QhSoEpzGr/Eg==", + "dev": true, + "dependencies": { + "glob": "~7.1.1", + "lodash": "^4.17.21", + "minimatch": "~3.0.2" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/hosted-git-info/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/execa": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", + "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", + "dependencies": { + "cross-spawn": "^6.0.0", + "get-stream": "^4.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/encoding": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", + "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", + "optional": true, + "dependencies": { + "iconv-lite": "^0.6.2" + } + }, + "node_modules/@eslint/eslintrc/node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-number-object": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", + "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-arguments": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", + "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/spdx-license-ids": { + "version": "3.0.16", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.16.tgz", + "integrity": "sha512-eWN+LnM3GR6gPu35WxNgbGl8rmY1AEmoMDvL/QD6zYmPWgywxWqJWNdLGT+ke8dKNWrcYgYjPpG5gbTfghP8rw==", + "dev": true + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/eslint-plugin-promise": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-6.1.1.tgz", + "integrity": "sha512-tjqWDwVZQo7UIPMeDReOpUgHCmCiH+ePnVT+5zVapL0uuHnegBUs2smM13CzOs2Xb5+MHMRFTs9v24yjba4Oig==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + } + }, + "node_modules/arraybuffer.prototype.slice": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.2.tgz", + "integrity": "sha512-yMBKppFur/fbHu9/6USUe03bZ4knMYiwFBcyiaXB8Go0qNehwX6inYPzK9U0NeQvGxKthcmHcaR8P5MStSRBAw==", + "dependencies": { + "array-buffer-byte-length": "^1.0.0", + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "get-intrinsic": "^1.2.1", + "is-array-buffer": "^3.0.2", + "is-shared-array-buffer": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "node_modules/deep-eql": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.3.tgz", + "integrity": "sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==", + "dev": true, + "dependencies": { + "type-detect": "^4.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "node_modules/safe-regex-test": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz", + "integrity": "sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==", + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.3", + "is-regex": "^1.1.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/passport": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/passport/-/passport-0.4.1.tgz", + "integrity": "sha512-IxXgZZs8d7uFSt3eqNjM9NQ3g3uQCW5avD8mRNoXV99Yig50vjuaez6dQK2qC0kVWPRTujxY0dWgGfT09adjYg==", + "dependencies": { + "passport-strategy": "1.x.x", + "pause": "0.0.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + }, + "node_modules/type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/typed-array-byte-offset": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.0.tgz", + "integrity": "sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg==", + "dependencies": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "has-proto": "^1.0.1", + "is-typed-array": "^1.1.10" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", + "engines": { + "node": ">=4" + } + }, + "node_modules/is-promise": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz", + "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==" + }, + "node_modules/wrap-ansi/node_modules/ansi-regex": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", + "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/json5": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "dev": true, + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" + } + }, + "node_modules/which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "dependencies": { + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" + }, + "node_modules/eventemitter3": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-3.1.2.tgz", + "integrity": "sha512-tvtQIeLVHjDkJYnzf2dgVMxfuSGJeM/7UCG17TT4EumTfNtF+0nebF/4zWOIkCreAbtNqhGEboB6BWrwqNaw4Q==" + }, + "node_modules/immediate": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", + "integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==", + "dev": true + }, + "node_modules/@mapbox/node-pre-gyp/node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "optional": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@npmcli/fs/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/bunyan": { + "version": "1.8.15", + "resolved": "https://registry.npmjs.org/bunyan/-/bunyan-1.8.15.tgz", + "integrity": "sha512-0tECWShh6wUysgucJcBAoYegf3JJoZWibxdqhTm7OHPeT42qdjkZ29QCMcKwbgU1kiH+auSIasNRXMLWXafXig==", + "engines": [ + "node >=0.10.0" + ], + "bin": { + "bunyan": "bin/bunyan" + }, + "optionalDependencies": { + "dtrace-provider": "~0.8", + "moment": "^2.19.3", + "mv": "~2", + "safe-json-stringify": "~1" + } + }, + "node_modules/optimist/node_modules/minimist": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", + "integrity": "sha512-iotkTvxc+TwOm5Ieim8VnSNvCDjCK9S8G3scJ50ZthspSxa7jx50jkhYduuAtAjvfDUwSgOwf8+If99AlOEhyw==" + }, + "node_modules/csv-parse": { + "version": "4.16.3", + "resolved": "https://registry.npmjs.org/csv-parse/-/csv-parse-4.16.3.tgz", + "integrity": "sha512-cO1I/zmz4w2dcKHVvpCr7JVRu8/FymG5OEpmvsZYlccYolPBLoVGKUHgNoc4ZGkFeFlWGEDmMyBM+TTqRdW/wg==" + }, + "node_modules/streamsearch": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-0.1.2.tgz", + "integrity": "sha512-jos8u++JKm0ARcSUTAZXOVC0mSox7Bhn6sBgty73P1f3JGf7yG2clTbBNHUdde/kdvP2FESam+vM6l8jBrNxHA==", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/redis-errors": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/redis-errors/-/redis-errors-1.2.0.tgz", + "integrity": "sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w==", + "optional": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minipass-pipeline": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", + "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", + "devOptional": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@eslint/eslintrc/node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/isemail": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/isemail/-/isemail-3.2.0.tgz", + "integrity": "sha512-zKqkK+O+dGqevc93KNsbZ/TqTUFd46MwWjYOoMrjIMZ51eU7DtQG3Wmd9SQQT7i7RVnuTPEiYEWHU3MSbxC1Tg==", + "dependencies": { + "punycode": "2.x.x" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/node-sass/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", + "dev": true, + "peer": true + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + }, + "node_modules/forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==", + "dev": true, + "peer": true, + "engines": { + "node": "*" + } + }, + "node_modules/check-error": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.3.tgz", + "integrity": "sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==", + "dev": true, + "dependencies": { + "get-func-name": "^2.0.2" + }, + "engines": { + "node": "*" + } + }, + "node_modules/camelcase-keys": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-6.2.2.tgz", + "integrity": "sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==", + "dev": true, + "dependencies": { + "camelcase": "^5.3.1", + "map-obj": "^4.0.0", + "quick-lru": "^4.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/stream-transform": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/stream-transform/-/stream-transform-2.1.3.tgz", + "integrity": "sha512-9GHUiM5hMiCi6Y03jD2ARC1ettBXkQBoQAe7nJsPknnI0ow10aXjTnew8QtYQmLjzn974BnmWEAJgCY6ZP1DeQ==", + "dependencies": { + "mixme": "^0.5.1" + } + }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/express/node_modules/cookie": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", + "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/http-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", + "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", + "dev": true, + "dependencies": { + "@tootallnate/once": "2", + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/promise": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/promise/-/promise-8.3.0.tgz", + "integrity": "sha512-rZPNPKTOYVNEEKFaq1HqTgOwZD+4/YHS5ukLzQCypkj+OkYx7iv0mA91lJlpPPZ8vMau3IIGj5Qlwrx+8iiSmg==", + "dependencies": { + "asap": "~2.0.6" + } + }, + "node_modules/oauth-sign": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", + "dev": true, + "peer": true, + "engines": { + "node": "*" + } + }, + "node_modules/globals": { + "version": "13.23.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.23.0.tgz", + "integrity": "sha512-XAmF0RjlrjY23MA51q3HltdlGxUpXPvg0GioKiD9X6HD28iMjo2dKC8Vqwm7lne4GNr78+RHTfliktR6ZH09wA==", + "dev": true, + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@tootallnate/once": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", + "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", + "dev": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/stealthy-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/stealthy-require/-/stealthy-require-1.1.1.tgz", + "integrity": "sha512-ZnWpYnYugiOVEY5GkcuJK1io5V8QmNYChG62gSit9pQVGErXtrKuPC55ITaVSukmMta5qpMU7vqLt2Lnni4f/g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==" + }, + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" + }, + "node_modules/@handlebars/allow-prototype-access": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@handlebars/allow-prototype-access/-/allow-prototype-access-1.0.5.tgz", + "integrity": "sha512-D5AJO9dM6B+1scVVQ4ma05cAku5M2dEnlycggIg6RW539TdQlgbNg1G1r86fNqqNI0CHv/TVwKEB9M6ILJQCWQ==", + "peerDependencies": { + "handlebars": "^4.7.2" + } + }, + "node_modules/acorn": { + "version": "8.10.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", + "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/minipass-flush": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", + "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", + "devOptional": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==" + }, + "node_modules/node-gyp/node_modules/socks-proxy-agent": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-6.2.1.tgz", + "integrity": "sha512-a6KW9G+6B3nWZ1yB8G7pJwL3ggLy1uTzKAgCb7ttblwqdz9fMGJUuTy3uFzEP48FAs9FLILlmzDlE2JJhVQaXQ==", + "devOptional": true, + "dependencies": { + "agent-base": "^6.0.2", + "debug": "^4.3.3", + "socks": "^2.6.2" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/decamelize-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.1.tgz", + "integrity": "sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==", + "dev": true, + "dependencies": { + "decamelize": "^1.1.0", + "map-obj": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/uid2": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/uid2/-/uid2-0.0.4.tgz", + "integrity": "sha512-IevTus0SbGwQzYh3+fRsAMTVVPOoIVufzacXcHPmdlle1jUpq7BRL+mw3dgeLanvGZdwwbWhRV6XrcFNdBmjWA==" + }, + "node_modules/npmlog": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-6.0.2.tgz", + "integrity": "sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==", + "devOptional": true, + "dependencies": { + "are-we-there-yet": "^3.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^4.0.3", + "set-blocking": "^2.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/validator": { + "version": "13.11.0", + "resolved": "https://registry.npmjs.org/validator/-/validator-13.11.0.tgz", + "integrity": "sha512-Ii+sehpSfZy+At5nPdnyMhx78fEoPDkR2XW/zimHEL3MyGJQOCQ7WeP20jPYRz7ZCpcKLB21NxuXHF3bxjStBQ==", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-plain-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", + "integrity": "sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/sax": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.3.0.tgz", + "integrity": "sha512-0s+oAmw9zLl1V1cS9BtZN7JAd0cW5e0QH4W3LWEK6a4LaLEA2OTpGYWDY+6XasBLtz6wkm3u1xRw95mRuJ59WA==", + "dev": true + }, + "node_modules/@npmcli/fs": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-2.1.2.tgz", + "integrity": "sha512-yOJKRvohFOaLqipNtwYB9WugyZKhC/DZC4VYPmpaCzDBrA8YpK3qHZ8/HGscMnE4GqbkLNuVcCnxkeQEdGt6LQ==", + "dev": true, + "dependencies": { + "@gar/promisify": "^1.1.3", + "semver": "^7.3.5" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "optional": true, + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/concat-stream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/object.getownpropertydescriptors": { + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.7.tgz", + "integrity": "sha512-PrJz0C2xJ58FNn11XV2lr4Jt5Gzl94qpy9Lu0JlfEj14z88sqbSBJCBEzdlNUCzY2gburhbrwOZ5BHCmuNUy0g==", + "dependencies": { + "array.prototype.reduce": "^1.0.6", + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "safe-array-concat": "^1.0.0" + }, + "engines": { + "node": ">= 0.8" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/node-gyp/node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "devOptional": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/htmlparser2": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.10.1.tgz", + "integrity": "sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ==", + "dependencies": { + "domelementtype": "^1.3.1", + "domhandler": "^2.3.0", + "domutils": "^1.5.1", + "entities": "^1.1.1", + "inherits": "^2.0.1", + "readable-stream": "^3.1.1" + } + }, + "node_modules/get-tsconfig": { + "version": "4.7.2", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.7.2.tgz", + "integrity": "sha512-wuMsz4leaj5hbGgg4IvDU0bqJagpftG5l5cXIAvo8uZrqn0NJqwtfupTN00VnkQJPcIRrxYrm1Ue24btpCha2A==", + "dev": true, + "dependencies": { + "resolve-pkg-maps": "^1.0.0" + }, + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + } + }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/cacache/node_modules/rimraf/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/har-validator": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", + "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", + "deprecated": "this library is no longer supported", + "dev": true, + "peer": true, + "dependencies": { + "ajv": "^6.12.3", + "har-schema": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/es5-ext": { + "version": "0.10.62", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.62.tgz", + "integrity": "sha512-BHLqn0klhEpnOKSrzn/Xsz2UIW8j+cGmo9JLzr8BiUapV8hPL9+FliFqjwr9ngW7jWdnxv6eO+/LqyhJVqgrjA==", + "hasInstallScript": true, + "dependencies": { + "es6-iterator": "^2.0.3", + "es6-symbol": "^3.1.3", + "next-tick": "^1.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/js-yaml": { + "version": "3.13.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", + "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", + "dev": true, + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/unbox-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", + "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", + "dependencies": { + "call-bind": "^1.0.2", + "has-bigints": "^1.0.2", + "has-symbols": "^1.0.3", + "which-boxed-primitive": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/safe-array-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.0.1.tgz", + "integrity": "sha512-6XbUAseYE2KtOuGueyeobCySj9L4+66Tn6KQMOPQJrAJEowYKW/YR/MGJZl7FdydUdaFu4LYyDZjxf4/Nmo23Q==", + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.1", + "has-symbols": "^1.0.3", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">=0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/eslint-plugin-import/node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/proto-list": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", + "integrity": "sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==" + }, + "node_modules/xmlbuilder": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", + "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/@npmcli/fs/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/is-typed-array": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.12.tgz", + "integrity": "sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==", + "dependencies": { + "which-typed-array": "^1.1.11" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/eslint/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true + }, + "node_modules/connect-redis": { + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/connect-redis/-/connect-redis-6.1.3.tgz", + "integrity": "sha512-aaNluLlAn/3JPxRwdzw7lhvEoU6Enb+d83xnokUNhC9dktqBoawKWL+WuxinxvBLTz6q9vReTnUDnUslaz74aw==", + "engines": { + "node": ">=12" + } + }, + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "devOptional": true, + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true + }, + "node_modules/call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dependencies": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/mocha": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-6.2.3.tgz", + "integrity": "sha512-0R/3FvjIGH3eEuG17ccFPk117XL2rWxatr81a57D+r/x2uTYZRbdZ4oVidEUMh2W2TJDa7MdAb12Lm2/qrKajg==", + "dev": true, + "dependencies": { + "yargs-unparser": "1.6.0", + "js-yaml": "3.13.1", + "yargs": "13.3.2", + "which": "1.3.1", + "ansi-colors": "3.2.3", + "log-symbols": "2.2.0", + "wide-align": "1.1.3", + "growl": "1.10.5", + "diff": "3.5.0", + "object.assign": "4.1.0", + "node-environment-flags": "1.0.5", + "yargs-parser": "13.1.2", + "ms": "2.1.1", + "supports-color": "6.0.0", + "strip-json-comments": "2.0.1", + "debug": "3.2.6", + "minimatch": "3.0.4", + "mkdirp": "0.5.4", + "find-up": "3.0.0", + "browser-stdout": "1.3.1", + "escape-string-regexp": "1.0.5", + "glob": "7.1.3", + "he": "1.2.0" + }, + "bin": { + "_mocha": "bin/_mocha", + "mocha": "bin/mocha" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/is-string": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", + "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/yargs/node_modules/string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "dependencies": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "optional": true + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true, + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/sequelize-cli": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/sequelize-cli/-/sequelize-cli-5.4.0.tgz", + "integrity": "sha512-4Gvl0yH0T3hhSdiiOci3+IKIfVG9x2os0hGWsbfa8QuyGgk9mZOqgTBnSCRtuxsdAyzUix9kfcTnfNolVNtprg==", + "dependencies": { + "bluebird": "^3.5.3", + "cli-color": "^1.4.0", + "fs-extra": "^7.0.1", + "js-beautify": "^1.8.8", + "lodash": "^4.17.5", + "resolve": "^1.5.0", + "umzug": "^2.1.0", + "yargs": "^12.0.5" + }, + "bin": { + "sequelize": "lib/sequelize" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/cross-spawn/node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/redis": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/redis/-/redis-3.1.2.tgz", + "integrity": "sha512-grn5KoZLr/qrRQVwoSkmzdbw6pwF+/rwODtrOr6vuBRiR/f3rjSTGupbF90Zpqm2oenix8Do6RV7pYEkGwlKkw==", + "optional": true, + "dependencies": { + "denque": "^1.5.0", + "redis-commands": "^1.7.0", + "redis-errors": "^1.2.0", + "redis-parser": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/node-redis" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.9.1.tgz", + "integrity": "sha512-Y27x+MBLjXa+0JWDhykM3+JE+il3kHKAEqabfEWq3SDhZjLYb6/BHL/JKFnH3fe207JaXkyDo685Oc2Glt6ifA==", + "dev": true, + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/has-bigints": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", + "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/globule/node_modules/glob": { + "version": "7.1.7", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", + "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/eslint/node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/meow": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/meow/-/meow-9.0.0.tgz", + "integrity": "sha512-+obSblOQmRhcyBt62furQqRAQpNyWXo8BuQ5bN7dG8wmwQ+vwHKp/rCFD4CrTP8CsDQD1sjoZ94K417XEUk8IQ==", + "dev": true, + "dependencies": { + "@types/minimist": "^1.2.0", + "camelcase-keys": "^6.2.2", + "decamelize": "^1.2.0", + "decamelize-keys": "^1.1.0", + "hard-rejection": "^2.1.0", + "minimist-options": "4.1.0", + "normalize-package-data": "^3.0.0", + "read-pkg-up": "^7.0.1", + "redent": "^3.0.0", + "trim-newlines": "^3.0.0", + "type-fest": "^0.18.0", + "yargs-parser": "^20.2.3" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/yargs/node_modules/strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "dependencies": { + "ansi-regex": "^4.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/mocha/node_modules/ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/set-function-name": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.1.tgz", + "integrity": "sha512-tMNCiqYVkXIZgc2Hnoy2IvC/f8ezc5koaRFkCjrpWzGpCd3qbZXPzVy9MAZzK1ch/X0jvSkojys3oqJN0qCmdA==", + "dependencies": { + "define-data-property": "^1.0.1", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "devOptional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" + }, + "node_modules/eslint-plugin-mocha": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-mocha/-/eslint-plugin-mocha-10.2.0.tgz", + "integrity": "sha512-ZhdxzSZnd1P9LqDPF0DBcFLpRIGdh1zkF2JHnQklKQOvrQtT73kdP5K9V2mzvbLR+cCAO9OI48NXK/Ax9/ciCQ==", + "dev": true, + "dependencies": { + "eslint-utils": "^3.0.0", + "rambda": "^7.4.0" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "eslint": ">=7.0.0" + } + }, + "node_modules/@types/ws": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-5.1.2.tgz", + "integrity": "sha512-NkTXUKTYdXdnPE2aUUbGOXE1XfMK527SCvU/9bj86kyFF6kZ9ZnOQ3mK5jADn98Y2vEUD/7wKDgZa7Qst2wYOg==", + "dependencies": { + "@types/events": "*", + "@types/node": "*" + } + }, + "node_modules/cacache/node_modules/lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/socks": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.1.tgz", + "integrity": "sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==", + "devOptional": true, + "dependencies": { + "ip": "^2.0.0", + "smart-buffer": "^4.2.0" + }, + "engines": { + "node": ">= 10.13.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/topo": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/topo/-/topo-3.0.3.tgz", + "integrity": "sha512-IgpPtvD4kjrJ7CRA3ov2FhWQADwv+Tdqbsf1ZnPUSAtCJ9e1Z44MmoSGDXGk4IppoZA7jd/QRkNddlLJWlUZsQ==", + "deprecated": "This module has moved and is now available at @hapi/topo. Please update your dependencies as this version is no longer maintained an may contain bugs and security issues.", + "dependencies": { + "hoek": "6.x.x" + } + }, + "node_modules/p-queue": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/p-queue/-/p-queue-2.4.2.tgz", + "integrity": "sha512-n8/y+yDJwBjoLQe1GSJbbaYQLTI7QHNZI2+rpmCDbe++WLf9HC3gf6iqj5yfPAV71W4UF3ql5W1+UBPXoXTxng==", + "engines": { + "node": ">=4" + } + }, + "node_modules/color-support": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", + "devOptional": true, + "bin": { + "color-support": "bin.js" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/flatted": { + "version": "3.2.9", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.9.tgz", + "integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==", + "dev": true + }, + "node_modules/type": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", + "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==" + }, + "node_modules/hoek": { + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-6.1.3.tgz", + "integrity": "sha512-YXXAAhmF9zpQbC7LEcREFtXfGq5K1fmd+4PHkBq8NUqmzW3G+Dq10bI/i0KucLRwss3YYFQ0fSfoxBZYiGUqtQ==", + "deprecated": "This module has moved and is now available at @hapi/hoek. Please update your dependencies as this version is no longer maintained an may contain bugs and security issues." + }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/node-gyp/node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "devOptional": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/moment": { + "version": "2.29.4", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz", + "integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==", + "engines": { + "node": "*" + } + }, + "node_modules/cliui": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", + "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", + "dev": true, + "dependencies": { + "string-width": "^3.1.0", + "strip-ansi": "^5.2.0", + "wrap-ansi": "^5.1.0" + } + }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/request-promise": { + "version": "4.2.6", + "resolved": "https://registry.npmjs.org/request-promise/-/request-promise-4.2.6.tgz", + "integrity": "sha512-HCHI3DJJUakkOr8fNoCc73E5nU5bqITjOYFMDrKHYOXWXrgD/SBaC7LjwuPymUprRyuF06UK7hd/lMHkmUXglQ==", + "deprecated": "request-promise has been deprecated because it extends the now deprecated request package, see https://github.com/request/request/issues/3142", + "dev": true, + "dependencies": { + "bluebird": "^3.5.0", + "request-promise-core": "1.1.4", + "stealthy-require": "^1.1.1", + "tough-cookie": "^2.3.3" + }, + "engines": { + "node": ">=0.10.0" + }, + "peerDependencies": { + "request": "^2.34" + } + }, + "node_modules/nan": { + "version": "2.18.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.18.0.tgz", + "integrity": "sha512-W7tfG7vMOGtD30sHoZSSc/JVYiyDPEyQVso/Zz+/uQd0B0L46gtC+pHha5FFMRpil6fm/AoEcRWyOVi4+E/f8w==", + "devOptional": true + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/precond": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/precond/-/precond-0.2.3.tgz", + "integrity": "sha512-QCYG84SgGyGzqJ/vlMsxeXd/pgL/I94ixdNFyh1PusWmTCyVfPJjZ1K1jvHtsbfnXQs2TSkEP2fR7QiMZAnKFQ==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-parser": { + "version": "1.4.6", + "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.6.tgz", + "integrity": "sha512-z3IzaNjdwUC2olLIB5/ITd0/setiaFMLYiZJle7xg5Fe9KWAceil7xszYfHHBtDFYLSgJduS2Ty0P1uJdPDJeA==", + "dependencies": { + "cookie": "0.4.1", + "cookie-signature": "1.0.6" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/eslint-plugin-import/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/busboy/node_modules/isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==" + }, + "node_modules/passport-local": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/passport-local/-/passport-local-1.0.0.tgz", + "integrity": "sha512-9wCE6qKznvf9mQYYbgJ3sVOHmCWoUNMVFoZzNoznmISbhnNNPhN9xfY3sLmScHMetEJeoY7CXwfhCe7argfQow==", + "dependencies": { + "passport-strategy": "1.x.x" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==", + "dev": true, + "peer": true + }, + "node_modules/normalize-package-data/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/body-parser/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/eslint/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/socks-proxy-agent/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/eslint/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/mocha/node_modules/object.assign": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", + "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", + "dev": true, + "dependencies": { + "define-properties": "^1.1.2", + "function-bind": "^1.1.1", + "has-symbols": "^1.0.0", + "object-keys": "^1.0.11" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/cacache/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/read-pkg-up": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", + "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", + "dev": true, + "dependencies": { + "find-up": "^4.1.0", + "read-pkg": "^5.2.0", + "type-fest": "^0.8.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/next-tick": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz", + "integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==" + }, + "node_modules/request/node_modules/form-data": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "dev": true, + "peer": true, + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 0.12" + } + }, + "node_modules/browser-stdout": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", + "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", + "dev": true + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==", + "dev": true, + "peer": true + }, + "node_modules/express/node_modules/body-parser": { + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", + "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", + "dependencies": { + "bytes": "3.1.2", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.11.0", + "raw-body": "2.5.1", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/passport-http-bearer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/passport-http-bearer/-/passport-http-bearer-1.0.1.tgz", + "integrity": "sha512-SELQM+dOTuMigr9yu8Wo4Fm3ciFfkMq5h/ZQ8ffi4ELgZrX1xh9PlglqZdcUZ1upzJD/whVyt+YWF62s3U6Ipw==", + "dependencies": { + "passport-strategy": "1.x.x" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/eslint/node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/vasync/node_modules/verror": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.6.0.tgz", + "integrity": "sha512-bIOaZx4+Bf6a7sIORfmYnyKLDLk/lhVym6rjYlq+vkitYKnhFmUpmPpDTCltWFrUTlGKs6sCeoDWfMA0oOOneA==", + "engines": [ + "node >=0.6.0" + ], + "dependencies": { + "extsprintf": "1.2.0" + } + }, + "node_modules/has-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", + "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/sequelize-cli/node_modules/lcid": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz", + "integrity": "sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==", + "dependencies": { + "invert-kv": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/dtrace-provider": { + "version": "0.8.8", + "resolved": "https://registry.npmjs.org/dtrace-provider/-/dtrace-provider-0.8.8.tgz", + "integrity": "sha512-b7Z7cNtHPhH9EJhNNbbeqTcXB8LGFFZhq1PGgEvpeHlzd36bhbdTWoE/Ba/YguqpBSlAPKnARWhVlhunCMwfxg==", + "hasInstallScript": true, + "optional": true, + "dependencies": { + "nan": "^2.14.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" + }, + "node_modules/hosted-git-info/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/os-locale": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", + "integrity": "sha512-PRT7ZORmwu2MEFt4/fv3Q+mEfN4zetKxufQrkShY2oGvUms9r8otu5HfdyIFHkYXjO7laNsoVGmM2MANfuTA8g==", + "dependencies": { + "lcid": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ldapauth-fork": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/ldapauth-fork/-/ldapauth-fork-4.3.3.tgz", + "integrity": "sha512-x76VpQ5ZqkwAJmqwcD6KIwDiNEbgIGIPGwC/eA17e1dxWhlTx36w0DlLOFwjTuZ2iuaLTsZsUprlVqvSlwc/1Q==", + "dependencies": { + "@types/ldapjs": "^1.0.0", + "@types/node": "*", + "bcryptjs": "^2.4.0", + "ldapjs": "^1.0.2", + "lru-cache": "^5.1.1" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "node_modules/httpntlm/node_modules/underscore": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.7.0.tgz", + "integrity": "sha512-cp0oQQyZhUM1kpJDLdGO1jPZHgS/MpzoWYfe9+CM2h/QGDZlqwT2T3YGukuBdaNJ/CAPoeyAZRRHz8JFo176vA==" + }, + "node_modules/mixme": { + "version": "0.5.9", + "resolved": "https://registry.npmjs.org/mixme/-/mixme-0.5.9.tgz", + "integrity": "sha512-VC5fg6ySUscaWUpI4gxCBTQMH2RdUpNrk+MsbpCYtIvf9SBJdiUey4qE7BXviJsJR4nDQxCZ+3yaYNW3guz/Pw==", + "engines": { + "node": ">= 8.0.0" + } + }, + "node_modules/p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dependencies": { + "p-limit": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/jsprim/node_modules/verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==", + "dev": true, + "engines": [ + "node >=0.6.0" + ], + "peer": true, + "dependencies": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, + "node_modules/array-includes": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.7.tgz", + "integrity": "sha512-dlcsNBIiWhPkHdOEEKnehA+RNUWDc4UqFtnIXU4uuYDPtA4LDkr7qip2p0VvFAEXNDr0yWZ9PJyIRiGjRLQzwQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "get-intrinsic": "^1.2.1", + "is-string": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/node-gyp/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "devOptional": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/node-gyp/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "devOptional": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/named-placeholders": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/named-placeholders/-/named-placeholders-1.1.3.tgz", + "integrity": "sha512-eLoBxg6wE/rZkJPhU/xRX1WTpkFEwDJEN96oxFrTsqBdbT5ec295Q+CoHrL9IT0DipqKhmGcaZmwOt8OON5x1w==", + "optional": true, + "dependencies": { + "lru-cache": "^7.14.1" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/nopt": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", + "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", + "devOptional": true, + "dependencies": { + "abbrev": "1" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/string.prototype.trim": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.8.tgz", + "integrity": "sha512-lfjY4HcixfQXOfaqCvcBuOIapyaroTXhbkfJN3gcB1OtyupngWK4sEET9Knd0cXd28kTUqu/kHoV4HKSJdnjiQ==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-stdin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", + "integrity": "sha512-F5aQMywwJ2n85s4hJPTT9RPxGmubonuB10MNYo17/xph174n2MIR33HRguhzVag10O/npM7SPk73LMZNP+FaWw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/formidable": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/formidable/-/formidable-1.2.6.tgz", + "integrity": "sha512-KcpbcpuLNOwrEjnbpMC0gS+X8ciDoZE1kkqzat4a8vrprf+s9pKNQ/QIwWfbfs4ltgmFl3MD177SNTkve3BwGQ==", + "deprecated": "Please upgrade to latest, formidable@v2 or formidable@v3! Check these notes: https://bit.ly/2ZEqIau", + "funding": { + "url": "https://ko-fi.com/tunnckoCore/commissions" + } + }, + "node_modules/jszip/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" + }, + "node_modules/node-gyp/node_modules/@tootallnate/once": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", + "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", + "devOptional": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/ncp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ncp/-/ncp-2.0.0.tgz", + "integrity": "sha512-zIdGUrPRFTUELUvr3Gmc7KZ2Sw/h1PiVM0Af/oHB6zgnV1ikqSfRk+TOufi79aHYCW3NiOXmr1BP5nWbzojLaA==", + "optional": true, + "bin": { + "ncp": "bin/ncp" + } + }, + "node_modules/moment-timezone": { + "version": "0.5.43", + "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.43.tgz", + "integrity": "sha512-72j3aNyuIsDxdF1i7CEgV2FfxM1r6aaqJyLB2vwb33mXYyoyLly+F1zbWqhA3/bVIoJ4szlUoMbUnVdid32NUQ==", + "dependencies": { + "moment": "^2.29.4" + }, + "engines": { + "node": "*" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/dicer/node_modules/readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha512-+MeVjFf4L44XUkhM1eYbD8fyEsxcV81pqMSR5gblfcLCHfZvbrqy4/qYHE+/R5HoBUT11WV5O08Cr1n3YXkWVQ==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "node_modules/request/node_modules/qs": { + "version": "6.5.3", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz", + "integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==", + "dev": true, + "peer": true, + "engines": { + "node": ">=0.6" + } + }, + "node_modules/nodemailer": { + "version": "6.9.6", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.6.tgz", + "integrity": "sha512-s7pDtWwe5fLMkQUhw8TkWB/wnZ7SRdd9HRZslq/s24hlZvBP3j32N/ETLmnqTpmj4xoBZL9fOWyCIZ7r2HORHg==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true, + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/scss-tokenizer": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/scss-tokenizer/-/scss-tokenizer-0.4.3.tgz", + "integrity": "sha512-raKLgf1LI5QMQnG+RxHz6oK0sL3x3I4FN2UDLqgLOGO8hodECNnNh5BXn7fAyBxrA8zVzdQizQ6XjNJQ+uBwMw==", + "dev": true, + "dependencies": { + "js-base64": "^2.4.9", + "source-map": "^0.7.3" + } + }, + "node_modules/express": { + "version": "4.18.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", + "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==", + "dependencies": { + "type-is": "~1.6.18", + "safe-buffer": "5.2.1", + "finalhandler": "1.2.0", + "fresh": "0.5.2", + "body-parser": "1.20.1", + "content-type": "~1.0.4", + "send": "0.18.0", + "cookie": "0.5.0", + "methods": "~1.1.2", + "proxy-addr": "~2.0.7", + "accepts": "~1.3.8", + "range-parser": "~1.2.1", + "on-finished": "2.4.1", + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "etag": "~1.8.1", + "path-to-regexp": "0.1.7", + "statuses": "2.0.1", + "parseurl": "~1.3.3", + "setprototypeof": "1.2.0", + "merge-descriptors": "1.0.1", + "vary": "~1.1.2", + "serve-static": "1.15.0", + "content-disposition": "0.5.4", + "escape-html": "~1.0.3", + "http-errors": "2.0.0", + "cookie-signature": "1.0.6", + "utils-merge": "1.0.1", + "array-flatten": "1.1.1", + "depd": "2.0.0", + "qs": "6.11.0" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/node-gyp/node_modules/cacache": { + "version": "15.3.0", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-15.3.0.tgz", + "integrity": "sha512-VVdYzXEn+cnbXpFgWs5hTT7OScegHVmLhJIR8Ufqk3iFD6A6j5iSX1KuBTfNEv4tdJWE2PzA6IVFtcLC7fN9wQ==", + "devOptional": true, + "dependencies": { + "minipass-flush": "^1.0.5", + "unique-filename": "^1.1.1", + "infer-owner": "^1.0.4", + "@npmcli/move-file": "^1.0.1", + "promise-inflight": "^1.0.1", + "tar": "^6.0.2", + "minipass": "^3.1.1", + "minipass-pipeline": "^1.2.2", + "lru-cache": "^6.0.0", + "ssri": "^8.0.1", + "chownr": "^2.0.0", + "mkdirp": "^1.0.3", + "minipass-collect": "^1.0.2", + "fs-minipass": "^2.0.0", + "@npmcli/fs": "^1.0.0", + "p-map": "^4.0.0", + "rimraf": "^3.0.2", + "glob": "^7.1.4" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", + "dev": true, + "peer": true, + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/node-gyp/node_modules/@npmcli/move-file": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-1.1.2.tgz", + "integrity": "sha512-1SUf/Cg2GzGDyaf15aR9St9TWlb+XvbZXWpDx8YKs7MLzMH/BCeopv+y9vzrzgkfykCGuWOlSu3mZhj2+FQcrg==", + "deprecated": "This functionality has been moved to @npmcli/fs", + "devOptional": true, + "dependencies": { + "mkdirp": "^1.0.4", + "rimraf": "^3.0.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.2.tgz", + "integrity": "sha512-+wvgpDsrB1YqAMdEUCcnTlpfVBH7Vqn6A/NT3D8WVXFIaKMlErPIZT3oCIAVCOtarRpMtelZLqJeU3t7WY6X6g==", + "dev": true, + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/timers-ext": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/timers-ext/-/timers-ext-0.1.7.tgz", + "integrity": "sha512-b85NUNzTSdodShTIbky6ZF02e8STtVVfD+fu4aXXShEELpozH+bCpJLYMPZbsABN2wDH7fJpqIoXxJpzbf0NqQ==", + "dependencies": { + "es5-ext": "~0.10.46", + "next-tick": "1" + } + }, + "node_modules/p-cancelable": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.0.0.tgz", + "integrity": "sha512-USgPoaC6tkTGlS831CxsVdmZmyb8tR1D+hStI84MyckLOzfJlYQUweomrwE3D8T7u5u5GVuW064LT501wHTYYA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/stdout-stream/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true + }, + "node_modules/jszip": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.10.1.tgz", + "integrity": "sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==", + "dev": true, + "dependencies": { + "lie": "~3.3.0", + "pako": "~1.0.2", + "readable-stream": "~2.3.6", + "setimmediate": "^1.0.5" + } + }, + "node_modules/ext": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/ext/-/ext-1.7.0.tgz", + "integrity": "sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw==", + "dependencies": { + "type": "^2.7.2" + } + }, + "node_modules/array.prototype.flat": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz", + "integrity": "sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/dicer/node_modules/isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==" + }, + "node_modules/d": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", + "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", + "dependencies": { + "es5-ext": "^0.10.50", + "type": "^1.0.1" + } + }, + "node_modules/append-field": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz", + "integrity": "sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==" + }, + "node_modules/toposort-class": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toposort-class/-/toposort-class-1.0.1.tgz", + "integrity": "sha512-OsLcGGbYF3rMjPUf8oKktyvCiUxSbqMMS39m33MAjLTC1DVIH6x3WSt63/M77ihI09+Sdfk1AXvfhCEeUmC7mg==" + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/wrap-ansi": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", + "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.0", + "string-width": "^3.0.0", + "strip-ansi": "^5.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/es6-symbol": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", + "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", + "dependencies": { + "d": "^1.0.1", + "ext": "^1.1.2" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" + }, + "node_modules/finalhandler": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", + "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "statuses": "2.0.1", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/selenium-webdriver": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/selenium-webdriver/-/selenium-webdriver-3.6.0.tgz", + "integrity": "sha512-WH7Aldse+2P5bbFBO4Gle/nuQOdVwpHMTL6raL3uuBj/vPG07k6uzt3aiahu352ONBr5xXh0hDlM3LhtXPOC4Q==", + "dev": true, + "dependencies": { + "jszip": "^3.1.3", + "rimraf": "^2.5.4", + "tmp": "0.0.30", + "xml2js": "^0.4.17" + }, + "engines": { + "node": ">= 6.9.0" + } + }, + "node_modules/chalk/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/eslint/node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/memoizee": { + "version": "0.4.15", + "resolved": "https://registry.npmjs.org/memoizee/-/memoizee-0.4.15.tgz", + "integrity": "sha512-UBWmJpLZd5STPm7PMUlOw/TSy972M+z8gcyQ5veOnSDRREz/0bmpyTfKt3/51DhEBqCZQn1udM/5flcSPYhkdQ==", + "dependencies": { + "d": "^1.0.1", + "es5-ext": "^0.10.53", + "es6-weak-map": "^2.0.3", + "event-emitter": "^0.3.5", + "is-promise": "^2.2.2", + "lru-queue": "^0.1.0", + "next-tick": "^1.1.0", + "timers-ext": "^0.1.7" + } + }, + "node_modules/on-headers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", + "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/socks-proxy-agent": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-7.0.0.tgz", + "integrity": "sha512-Fgl0YPZ902wEsAyiQ+idGd1A7rSFx/ayC1CQVMw5P+EQx2V0SgpGtf6OKFhVjPflPUl9YMmEOnmfjCdMUsygww==", + "dev": true, + "dependencies": { + "agent-base": "^6.0.2", + "debug": "^4.3.3", + "socks": "^2.6.2" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/follow-redirects": { + "version": "1.5.10", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.10.tgz", + "integrity": "sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ==", + "dependencies": { + "debug": "=3.1.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/domelementtype": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", + "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==" + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "node_modules/node-gyp/node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "devOptional": true, + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/scss-tokenizer/node_modules/source-map": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", + "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/type-fest": { + "version": "0.18.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.18.1.tgz", + "integrity": "sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/send": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", + "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/express-session": { + "version": "1.17.3", + "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.17.3.tgz", + "integrity": "sha512-4+otWXlShYlG1Ma+2Jnn+xgKUZTMJ5QD3YvfilX3AcocOAbIkVylSWEklzALe/+Pu4qV6TYBj5GwOBFfdKqLBw==", + "dependencies": { + "cookie": "0.4.2", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "~2.0.0", + "on-headers": "~1.0.2", + "parseurl": "~1.3.3", + "safe-buffer": "5.2.1", + "uid-safe": "~2.1.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true + }, + "node_modules/@gar/promisify": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz", + "integrity": "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==", + "devOptional": true + }, + "node_modules/yargs/node_modules/is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/concat-stream/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/sass-graph": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/sass-graph/-/sass-graph-4.0.1.tgz", + "integrity": "sha512-5YCfmGBmxoIRYHnKK2AKzrAkCoQ8ozO+iumT8K4tXJXRVCPf+7s1/9KxTSW3Rbvf+7Y7b4FR3mWyLnQr3PHocA==", + "dev": true, + "dependencies": { + "glob": "^7.0.0", + "lodash": "^4.17.11", + "scss-tokenizer": "^0.4.3", + "yargs": "^17.2.1" + }, + "bin": { + "sassgraph": "bin/sassgraph" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/dom-serializer/node_modules/entities": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", + "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/stdout-stream": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/stdout-stream/-/stdout-stream-1.4.1.tgz", + "integrity": "sha512-j4emi03KXqJWcIeF8eIXkjMFN1Cmb8gUlDYGeBALLPo5qdyTfA9bOtl8m33lRoC+vFMkP3gl0WsDr6+gzxbbTA==", + "dev": true, + "dependencies": { + "readable-stream": "^2.0.1" + } + }, + "node_modules/has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==", + "devOptional": true + }, + "node_modules/define-data-property": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.1.tgz", + "integrity": "sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ==", + "dependencies": { + "get-intrinsic": "^1.2.1", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "dev": true + }, + "node_modules/supports-color": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.0.0.tgz", + "integrity": "sha512-on9Kwidc1IUQo+bQdhi8+Tijpo0e1SS6RoGo2guUwn5vdaxw8RXOF9Vb2ws+ihWOmh4JnCJOvaziZWP1VABaLg==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" + }, + "node_modules/multer": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/multer/-/multer-1.4.4.tgz", + "integrity": "sha512-2wY2+xD4udX612aMqMcB8Ws2Voq6NIUPEtD1be6m411T4uDH/VtL9i//xvcyFlTVfRdaBsk7hV5tgrGQqhuBiw==", + "deprecated": "Multer 1.x is affected by CVE-2022-24434. This is fixed in v1.4.4-lts.1 which drops support for versions of Node.js before 6. Please upgrade to at least Node.js 6 and version 1.4.4-lts.1 of Multer. If you need support for older versions of Node.js, we are open to accepting patches that would fix the CVE on the main 1.x release line, whilst maintaining compatibility with Node.js 0.10.", + "dependencies": { + "append-field": "^1.0.0", + "busboy": "^0.2.11", + "concat-stream": "^1.5.2", + "mkdirp": "^0.5.4", + "object-assign": "^4.1.1", + "on-finished": "^2.3.0", + "type-is": "^1.6.4", + "xtend": "^4.0.0" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "dependencies": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "node_modules/has-property-descriptors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", + "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", + "dependencies": { + "get-intrinsic": "^1.1.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", + "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/config-chain": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.13.tgz", + "integrity": "sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==", + "dependencies": { + "ini": "^1.3.4", + "proto-list": "~1.2.1" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/optionator": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", + "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", + "dev": true, + "dependencies": { + "@aashutoshrathi/word-wrap": "^1.2.3", + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/@eslint/js": { + "version": "8.51.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.51.0.tgz", + "integrity": "sha512-HxjQ8Qn+4SI3/AFv6sOrDB+g6PpUTDwSJiQqOrnneEk8L71161srI9gjzzZvYVbzHiVg/BvcH95+cK/zfIt4pg==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/bcryptjs": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-2.4.3.tgz", + "integrity": "sha512-V/Hy/X9Vt7f3BbPJEi8BdVFMByHi+jNXrYkW3huaybV/kQ0KJg0Y6PkEMbn+zeT+i+SiKZ/HMqJGIIt4LZDqNQ==" + }, + "node_modules/xml2js": { + "version": "0.4.23", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.23.tgz", + "integrity": "sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug==", + "dev": true, + "dependencies": { + "sax": ">=0.6.0", + "xmlbuilder": "~11.0.0" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/humanize-ms": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", + "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==", + "devOptional": true, + "dependencies": { + "ms": "^2.0.0" + } + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/decamelize-keys/node_modules/map-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", + "integrity": "sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/async-foreach": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/async-foreach/-/async-foreach-0.1.3.tgz", + "integrity": "sha512-VUeSMD8nEGBWaZK4lizI1sf3yEC7pnAQ/mrI7pC2fBz2s/tq5jWWEngTwaf0Gruu/OoXRGLGg1XFqpYBiGTYJA==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==", + "dev": true, + "peer": true + }, + "node_modules/busboy": { + "version": "0.2.14", + "resolved": "https://registry.npmjs.org/busboy/-/busboy-0.2.14.tgz", + "integrity": "sha512-InWFDomvlkEj+xWLBfU3AvnbVYqeTWmQopiW0tWWEy5yehYm2YkGEc59sUmw/4ty5Zj/b0WHGs1LgecuBSBGrg==", + "dependencies": { + "dicer": "0.2.5", + "readable-stream": "1.1.x" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/verror": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.1.tgz", + "integrity": "sha512-veufcmxri4e3XSrT0xwfUR7kguIkaxBeosDg00yDWhk49wdwkSUrvvsm7nc75e1PUyvIeZj6nS8VQRYz2/S4Xg==", + "dependencies": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + }, + "engines": { + "node": ">=0.6.0" + } + }, + "node_modules/http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ==", + "dev": true, + "peer": true, + "dependencies": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + }, + "engines": { + "node": ">=0.8", + "npm": ">=1.3.7" + } + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/rambda": { + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/rambda/-/rambda-7.5.0.tgz", + "integrity": "sha512-y/M9weqWAH4iopRd7EHDEQQvpFPHj1AA3oHozE9tfITHUtTR7Z9PSlIRRG2l1GuW7sefC1cXFfIcF+cgnShdBA==", + "dev": true + }, + "node_modules/eslint/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/safe-json-stringify": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/safe-json-stringify/-/safe-json-stringify-1.2.0.tgz", + "integrity": "sha512-gH8eh2nZudPQO6TytOvbxnuhYBOvDBBLW52tz5q6X58lJcd/tkmqFR+5Z9adS8aJtURSXWThWy/xJtJwixErvg==", + "optional": true + }, + "node_modules/express-session/node_modules/cookie": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", + "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/node-gyp/node_modules/unique-filename": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", + "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", + "devOptional": true, + "dependencies": { + "unique-slug": "^2.0.0" + } + }, + "node_modules/typed-array-length": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz", + "integrity": "sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==", + "dependencies": { + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "is-typed-array": "^1.1.9" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==", + "engines": { + "node": ">=4" + } + }, + "node_modules/assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/send/node_modules/debug/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/node-sass/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/connect-session-sequelize": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/connect-session-sequelize/-/connect-session-sequelize-6.0.0.tgz", + "integrity": "sha512-XC71xJd5rqObdL7700S/qFD+gSRA4o6WVJAyFY0Vjah73id5bBElM0SHQR1ME5Bxrt4JL8alvggseNDVTlKyxA==", + "dependencies": { + "debug": "^3.1.0", + "deep-equal": "^1.0.1" + }, + "engines": { + "node": ">= 5" + }, + "peerDependencies": { + "sequelize": ">= 3.24.5" + } + }, + "node_modules/yargs-unparser": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-1.6.0.tgz", + "integrity": "sha512-W9tKgmSn0DpSatfri0nx52Joq5hVXgeLiqR/5G0sZNDoLZFOr/xjBUDcShCOGNsBnEMNo1KAMBkTej1Hm62HTw==", + "dev": true, + "dependencies": { + "flat": "^4.1.0", + "lodash": "^4.17.15", + "yargs": "^13.3.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@types/is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@types/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha512-jkZatu4QVbR60mpIzjINmtS1ZF4a/FqdTUTBeQDVOQ2PYyidtwFKr0B5G6ERukKwliq+7mIXvxyppwzG5EgRYg==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/mocha/node_modules/glob": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", + "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + } + }, + "node_modules/is-core-module": { + "version": "2.13.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.0.tgz", + "integrity": "sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ==", + "dependencies": { + "has": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.values": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.7.tgz", + "integrity": "sha512-aU6xnDFYT3x17e/f0IiiwlGPTy2jzMySGfUB4fq6z7CV8l85CWHDk5ErhyhpfDHhrOMwGFhSQkhMGHaIotA6Ng==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/js-beautify/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/typed-array-buffer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.0.tgz", + "integrity": "sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw==", + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.1", + "is-typed-array": "^1.1.10" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/make-dir/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "optional": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" + }, + "node_modules/finalhandler/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/eslint/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/minimist-options": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-4.1.0.tgz", + "integrity": "sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==", + "dev": true, + "dependencies": { + "arrify": "^1.0.1", + "is-plain-obj": "^1.1.0", + "kind-of": "^6.0.3" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "devOptional": true, + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/denque": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/denque/-/denque-1.5.1.tgz", + "integrity": "sha512-XwE+iZ4D6ZUB7mfYRMb5wByE8L74HCn30FBN7sWnXksWc1LO1bPDl67pBR9o/kC4z/xSNAwkMYcGgqDV3BE3Hw==", + "optional": true, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/cacache/node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/strip-eof": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", + "integrity": "sha512-7FCwGGmx8mD5xQd3RPUvnSpUXHM3BWuzjtpD4TXsfcZ9EL4azvVVUscFYwD9nx8Kh+uCBC00XBtAykoMHwTh8Q==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/sequelize-cli/node_modules/wrap-ansi/node_modules/ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/form-data": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.1.tgz", + "integrity": "sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 0.12" + } + }, + "node_modules/@types/ldapjs": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@types/ldapjs/-/ldapjs-1.0.11.tgz", + "integrity": "sha512-O4D1frY6xy2mQr5WouNPeltMe5EHdmU4FxbLDC6TMDX5HXOuafusGu+7Y9WAoqBaYHZ5hcFa7jfkpggyexfeXQ==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==", + "devOptional": true + }, + "node_modules/secure-keys": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/secure-keys/-/secure-keys-1.0.0.tgz", + "integrity": "sha512-nZi59hW3Sl5P3+wOO89eHBAAGwmCPd2aE1+dLZV5MO+ItQctIvAqihzaAXIQhvtH4KJPxM080HsnqltR2y8cWg==" + }, + "node_modules/eslint-plugin-es-x": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-es-x/-/eslint-plugin-es-x-7.2.0.tgz", + "integrity": "sha512-9dvv5CcvNjSJPqnS5uZkqb3xmbeqRLnvXKK7iI5+oK/yTusyc46zbBZKENGsOfojm/mKfszyZb+wNqNPAPeGXA==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.1.2", + "@eslint-community/regexpp": "^4.6.0" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ota-meshi" + }, + "peerDependencies": { + "eslint": ">=8" + } + }, + "node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, + "node_modules/undici-types": { + "version": "5.25.3", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.25.3.tgz", + "integrity": "sha512-Ga1jfYwRn7+cP9v8auvEXN1rX3sWqlayd4HP7OKk4mZWylEmu3KzXDUGrQUN6Ol7qo1gPvB2e5gX6udnyEPgdA==" + }, + "node_modules/string.prototype.trimend": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.7.tgz", + "integrity": "sha512-Ni79DqeB72ZFq1uH/L6zJ+DKZTkOtPIHovb3YZHQViE+HDouuU4mBrLOLDn5Dde3RF8qw5qVETEjhu9locMLvA==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/p-map": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", + "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "devOptional": true, + "dependencies": { + "aggregate-error": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==" + }, + "node_modules/object-inspect": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.0.tgz", + "integrity": "sha512-HQ4J+ic8hKrgIt3mqk6cVOVrW2ozL4KdvHlqpBv9vDYWx9ysAgENAdvy4FoGF+KFdhR7nQTNm5J0ctAeOwn+3g==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/dottie": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/dottie/-/dottie-2.0.6.tgz", + "integrity": "sha512-iGCHkfUc5kFekGiqhe8B/mdaurD+lakO9txNnTvKtA6PISrw86LgqHvRzWYPyoE2Ph5aMIrCw9/uko6XHTKCwA==" + }, + "node_modules/read-pkg-up/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/async-limiter": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", + "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==" + }, + "node_modules/underscore": { + "version": "1.13.6", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.6.tgz", + "integrity": "sha512-+A5Sja4HP1M08MaXya7p5LvjuM7K6q/2EaC0+iovj/wOcMsTzMvDFbasi/oSapiwOlt252IqsKqPjCl7huKS0A==" + }, + "node_modules/sequelize-cli/node_modules/yargs-parser": { + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-11.1.1.tgz", + "integrity": "sha512-C6kB/WJDiaxONLJQnF8ccx9SEeoTTLek8RVbaOIsrAUS8VrBEXfmeSnCZxygc+XC2sNMBIwOOnfcxiynjHsVSQ==", + "dependencies": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + }, + "node_modules/stdout-stream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/cliui/node_modules/emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "dev": true + }, + "node_modules/sequelize-cli/node_modules/get-caller-file": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", + "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==" + }, + "node_modules/@types/json5": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", + "dev": true + }, + "node_modules/node-sass/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/normalize-package-data": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.3.tgz", + "integrity": "sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==", + "dev": true, + "dependencies": { + "hosted-git-info": "^4.0.1", + "is-core-module": "^2.5.0", + "semver": "^7.3.4", + "validate-npm-package-license": "^3.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@types/normalize-package-data": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.2.tgz", + "integrity": "sha512-lqa4UEhhv/2sjjIQgjX8B+RBjj47eo0mzGasklVJ78UKGQY1r0VpB9XHDaZZO9qzEFDdy4MrXLuEaSmPrPSe/A==", + "dev": true + }, + "node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/retry-as-promised": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/retry-as-promised/-/retry-as-promised-3.2.0.tgz", + "integrity": "sha512-CybGs60B7oYU/qSQ6kuaFmRd9sTZ6oXSc0toqePvV74Ac6/IFZSI1ReFQmtCN+uvW1Mtqdwpvt/LGOiCBAY2Mg==", + "dependencies": { + "any-promise": "^1.3.0" + } + }, + "node_modules/asn1": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz", + "integrity": "sha512-6i37w/+EhlWlGUJff3T/Q8u1RGmP5wgbiwYnOnbOqvtrPxT63/sYFyP9RcpxtxGymtfA075IvmOnL7ycNOWl3w==" + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + }, + "node_modules/named-placeholders/node_modules/lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "optional": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/node-gyp/node_modules/minipass-fetch": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-1.4.1.tgz", + "integrity": "sha512-CGH1eblLq26Y15+Azk7ey4xh0J/XfJfrCox5LDJiKqI2Q2iwOLOKrlmIaODiSQS8d18jalF6y2K2ePUm0CmShw==", + "devOptional": true, + "dependencies": { + "minipass": "^3.1.0", + "minipass-sized": "^1.0.3", + "minizlib": "^2.0.0" + }, + "engines": { + "node": ">=8" + }, + "optionalDependencies": { + "encoding": "^0.1.12" + } + }, + "node_modules/meow/node_modules/yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/eslint-config-standard": { + "version": "17.1.0", + "resolved": "https://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-17.1.0.tgz", + "integrity": "sha512-IwHwmaBNtDK4zDHQukFDW5u/aTb8+meQWZvNFWkiGmbWjD6bqyuSSBxxXKkCftCUzc1zwCH2m/baCNDLGmuO5Q==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "eslint": "^8.0.1", + "eslint-plugin-import": "^2.25.2", + "eslint-plugin-n": "^15.0.0 || ^16.0.0 ", + "eslint-plugin-promise": "^6.0.0" + } + }, + "node_modules/object.assign": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", + "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "has-symbols": "^1.0.3", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/agentkeepalive": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.5.0.tgz", + "integrity": "sha512-5GG/5IbQQpC9FpkRGsSvZI5QYeSCzlJHdpBQntCsuTOxhKD8lqKhrleg2Yi7yvMIf82Ycmmqln9U8V9qwEiJew==", + "devOptional": true, + "dependencies": { + "humanize-ms": "^1.2.1" + }, + "engines": { + "node": ">= 8.0.0" + } + }, + "node_modules/tar": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.0.tgz", + "integrity": "sha512-/Wo7DcT0u5HUV486xg675HtjNd3BXZ6xDbzsCUZPt5iw8bTQ63bP0Raut3mvro9u+CUyq7YQd8Cx55fsZXxqLQ==", + "devOptional": true, + "dependencies": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/loupe": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.7.tgz", + "integrity": "sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==", + "dev": true, + "dependencies": { + "get-func-name": "^2.0.1" + } + }, + "node_modules/sequelize-cli/node_modules/invert-kv": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz", + "integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==", + "engines": { + "node": ">=4" + } + }, + "node_modules/eslint/node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/encoding/node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "optional": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve-pkg-maps": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", + "dev": true, + "funding": { + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/map-obj": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.3.0.tgz", + "integrity": "sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/gaze": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/gaze/-/gaze-1.1.3.tgz", + "integrity": "sha512-BRdNm8hbWzFzWHERTrejLqwHDfS4GibPoq5wjTPIoJHoBtKGPg3xAFfxmM+9ztbXelxcf2hwQcaz1PtmFeue8g==", + "dev": true, + "dependencies": { + "globule": "^1.0.0" + }, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/normalize-package-data/node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/array.prototype.reduce": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/array.prototype.reduce/-/array.prototype.reduce-1.0.6.tgz", + "integrity": "sha512-UW+Mz8LG/sPSU8jRDCjVr6J/ZKAGpHfwrZ6kWTG5qCxIEiXdVshqGnu5vEZA8S1y6X4aCSbQZ0/EEsfvEvBiSg==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-array-method-boxes-properly": "^1.0.0", + "is-string": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/ssri": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-9.0.1.tgz", + "integrity": "sha512-o57Wcn66jMQvfHG1FlYbWeZWW/dHZhJXjpIcTfXldXEk5nz5lStPo3mK0OJQfGR3RbZUlbISexbljkJzuEj/8Q==", + "dev": true, + "dependencies": { + "minipass": "^3.1.1" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/ws": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-5.2.3.tgz", + "integrity": "sha512-jZArVERrMsKUatIdnLzqvcfydI85dvd/Fp1u/VOpfdDWQ4c9qWXe+VIeAbQ5FrDwciAkr+lzofXLz3Kuf26AOA==", + "dependencies": { + "async-limiter": "~1.0.0" + } + }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true + }, + "node_modules/dom-serializer": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.2.tgz", + "integrity": "sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==", + "dependencies": { + "domelementtype": "^2.0.1", + "entities": "^2.0.0" + } + }, + "node_modules/builtins/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/basic-auth": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz", + "integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==", + "dependencies": { + "safe-buffer": "5.1.2" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/serve-favicon/node_modules/ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" + }, + "node_modules/wide-align": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", + "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", + "devOptional": true, + "dependencies": { + "string-width": "^1.0.2 || 2" + } + }, + "node_modules/lru-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/lru-queue/-/lru-queue-0.1.0.tgz", + "integrity": "sha512-BpdYkt9EvGl8OfWHDQPISVpcl5xZthb+XPsbELj5AQXxIC8IriDZIQYjBJPEm5rS420sjZ0TLEzRcq5KdBhYrQ==", + "dependencies": { + "es5-ext": "~0.10.2" + } + }, + "node_modules/gauge/node_modules/wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "devOptional": true, + "dependencies": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "node_modules/qs": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", + "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "dependencies": { + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/jszip/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/sequelize": { + "version": "5.22.5", + "resolved": "https://registry.npmjs.org/sequelize/-/sequelize-5.22.5.tgz", + "integrity": "sha512-ySIHof18sJbeVG4zjEvsDL490cd9S14/IhkCrZR/g0C/FPlZq1AzEJVeSAo++9/sgJH2eERltAIGqYQNgVqX/A==", + "deprecated": "Please update to v6 or higher! A migration guide can be found here: https://sequelize.org/v6/manual/upgrade-to-v6.html", + "dependencies": { + "bluebird": "^3.5.0", + "cls-bluebird": "^2.1.0", + "debug": "^4.1.1", + "dottie": "^2.0.0", + "inflection": "1.12.0", + "lodash": "^4.17.15", + "moment": "^2.24.0", + "moment-timezone": "^0.5.21", + "retry-as-promised": "^3.2.0", + "semver": "^6.3.0", + "sequelize-pool": "^2.3.0", + "toposort-class": "^1.0.1", + "uuid": "^8.3.2", + "validator": "^13.7.0", + "wkx": "^0.4.8" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/connect-session-sequelize/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/read-pkg/node_modules/type-fest": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", + "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", + "dev": true, + "engines": { + "node": ">=8" + } + } + }, "dependencies": { - "@mdn/browser-compat-data": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/@mdn/browser-compat-data/-/browser-compat-data-2.0.7.tgz", - "integrity": "sha512-GeeM827DlzFFidn1eKkMBiqXFD2oLsnZbaiGhByPl0vcapsRzUL+t9hDoov1swc9rB2jw64R+ihtzC8qOE9wXw==", + "@aashutoshrathi/word-wrap": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", + "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", + "dev": true + }, + "@babel/code-frame": { + "version": "7.22.13", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz", + "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==", + "dev": true, + "requires": { + "@babel/highlight": "^7.22.13", + "chalk": "^2.4.2" + } + }, + "@babel/helper-validator-identifier": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", + "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", + "dev": true + }, + "@babel/highlight": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.20.tgz", + "integrity": "sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.22.20", + "chalk": "^2.4.2", + "js-tokens": "^4.0.0" + } + }, + "@eslint-community/eslint-utils": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^3.3.0" + } + }, + "@eslint-community/regexpp": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.9.1.tgz", + "integrity": "sha512-Y27x+MBLjXa+0JWDhykM3+JE+il3kHKAEqabfEWq3SDhZjLYb6/BHL/JKFnH3fe207JaXkyDo685Oc2Glt6ifA==", + "dev": true + }, + "@eslint/eslintrc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.2.tgz", + "integrity": "sha512-+wvgpDsrB1YqAMdEUCcnTlpfVBH7Vqn6A/NT3D8WVXFIaKMlErPIZT3oCIAVCOtarRpMtelZLqJeU3t7WY6X6g==", + "dev": true, + "requires": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "dependencies": { + "argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "requires": { + "argparse": "^2.0.1" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true + } + } + }, + "@eslint/js": { + "version": "8.51.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.51.0.tgz", + "integrity": "sha512-HxjQ8Qn+4SI3/AFv6sOrDB+g6PpUTDwSJiQqOrnneEk8L71161srI9gjzzZvYVbzHiVg/BvcH95+cK/zfIt4pg==", + "dev": true + }, + "@gar/promisify": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz", + "integrity": "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==", + "devOptional": true + }, + "@handlebars/allow-prototype-access": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@handlebars/allow-prototype-access/-/allow-prototype-access-1.0.5.tgz", + "integrity": "sha512-D5AJO9dM6B+1scVVQ4ma05cAku5M2dEnlycggIg6RW539TdQlgbNg1G1r86fNqqNI0CHv/TVwKEB9M6ILJQCWQ==" + }, + "@humanwhocodes/config-array": { + "version": "0.11.11", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.11.tgz", + "integrity": "sha512-N2brEuAadi0CcdeMXUkhbZB84eskAc8MEX1By6qEchoVywSgXPIjou4rYsl0V3Hj0ZnuGycGCjdNgockbzeWNA==", + "dev": true, + "requires": { + "@humanwhocodes/object-schema": "^1.2.1", + "debug": "^4.1.1", + "minimatch": "^3.0.5" + } + }, + "@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true + }, + "@humanwhocodes/object-schema": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", + "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", + "dev": true + }, + "@mapbox/node-pre-gyp": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz", + "integrity": "sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==", + "optional": true, + "requires": { + "detect-libc": "^2.0.0", + "https-proxy-agent": "^5.0.0", + "make-dir": "^3.1.0", + "node-fetch": "^2.6.7", + "nopt": "^5.0.0", + "npmlog": "^5.0.1", + "rimraf": "^3.0.2", + "semver": "^7.3.5", + "tar": "^6.1.11" + }, + "dependencies": { + "are-we-there-yet": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz", + "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==", + "optional": true, + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^3.6.0" + } + }, + "gauge": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz", + "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==", + "optional": true, + "requires": { + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.2", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.1", + "object-assign": "^4.1.1", + "signal-exit": "^3.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.2" + } + }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "optional": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "npmlog": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz", + "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==", + "optional": true, + "requires": { + "are-we-there-yet": "^2.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^3.0.0", + "set-blocking": "^2.0.0" + } + }, + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "optional": true, + "requires": { + "glob": "^7.1.3" + } + }, + "semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "optional": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "optional": true + } + } + }, + "@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "requires": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + } + }, + "@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true + }, + "@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "requires": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + } + }, + "@npmcli/fs": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-2.1.2.tgz", + "integrity": "sha512-yOJKRvohFOaLqipNtwYB9WugyZKhC/DZC4VYPmpaCzDBrA8YpK3qHZ8/HGscMnE4GqbkLNuVcCnxkeQEdGt6LQ==", + "dev": true, + "requires": { + "@gar/promisify": "^1.1.3", + "semver": "^7.3.5" + }, + "dependencies": { + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + } + } + }, + "@npmcli/move-file": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-2.0.1.tgz", + "integrity": "sha512-mJd2Z5TjYWq/ttPLLGqArdtnC74J6bOzg4rMDnN+p1xTacZ2yPRCk2y0oSWQtygLR9YVQXgOcONrwtnk3JupxQ==", + "dev": true, + "requires": { + "mkdirp": "^1.0.4", + "rimraf": "^3.0.2" + }, + "dependencies": { + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true + }, + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + } + } + }, + "@one-ini/wasm": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@one-ini/wasm/-/wasm-0.1.1.tgz", + "integrity": "sha512-XuySG1E38YScSJoMlqovLru4KTUNSjgVTIjyh7qMX6aNN5HY5Ct5LhRJdxO79JtTzKfzV/bnWpz+zquYrISsvw==" + }, + "@slack/client": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/@slack/client/-/client-4.12.0.tgz", + "integrity": "sha512-ltbdkcIWk2eIptCCT/oPmeCGlG8xb3kXfwuPTtvNujioLMo2xXqiPdfl7xK+AeUfnvj3fJLYbpTPuBTscuhgzw==", + "requires": { + "@types/form-data": "^2.2.1", + "@types/is-stream": "^1.1.0", + "@types/node": ">=6.0.0", + "@types/p-cancelable": "^1.0.0", + "@types/p-queue": "^2.3.2", + "@types/p-retry": "^3.0.0", + "@types/retry": "^0.12.0", + "@types/ws": "^5.1.1", + "axios": "^0.18.0", + "eventemitter3": "^3.1.0", + "finity": "^0.5.4", + "form-data": "^2.3.3", + "is-stream": "^1.1.0", + "object.entries": "^1.1.0", + "object.getownpropertydescriptors": "^2.0.3", + "object.values": "^1.1.0", + "p-cancelable": "~1.0.0", + "p-queue": "^2.4.2", + "p-retry": "^3.0.1", + "retry": "^0.12.0", + "ws": "^5.2.0" + } + }, + "@tootallnate/once": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", + "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", + "dev": true + }, + "@types/events": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@types/events/-/events-3.0.1.tgz", + "integrity": "sha512-QfUFdKjGSc+iCf8OFZhqJKfDuqB6lP57kSMkPw8ba3yNDANicUwCdaPt5ytZ4nDXXVFxQkvT8v73I4stSVrCxA==" + }, + "@types/form-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@types/form-data/-/form-data-2.5.0.tgz", + "integrity": "sha512-23/wYiuckYYtFpL+4RPWiWmRQH2BjFuqCUi2+N3amB1a1Drv+i/byTrGvlLwRVLFNAZbwpbQ7JvTK+VCAPMbcg==", "requires": { - "extend": "3.0.2" + "form-data": "*" } }, - "@types/geojson": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-1.0.6.tgz", - "integrity": "sha512-Xqg/lIZMrUd0VRmSRbCAewtwGZiAk3mEUDvV4op1tGl+LvyPcb/MIOSxTl9z+9+J+R4/vpjiCAT4xeKzH9ji1w==" + "@types/is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@types/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha512-jkZatu4QVbR60mpIzjINmtS1ZF4a/FqdTUTBeQDVOQ2PYyidtwFKr0B5G6ERukKwliq+7mIXvxyppwzG5EgRYg==", + "requires": { + "@types/node": "*" + } + }, + "@types/json5": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", + "dev": true }, "@types/ldapjs": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/@types/ldapjs/-/ldapjs-1.0.9.tgz", - "integrity": "sha512-3PvY7Drp1zoLbcGlothCAkoc5o6Jp9KvUPwHadlHyKp3yPvyeIh7w2zQc9UXMzgDRkoeGXUEODtbEs5XCh9ZyA==", + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@types/ldapjs/-/ldapjs-1.0.11.tgz", + "integrity": "sha512-O4D1frY6xy2mQr5WouNPeltMe5EHdmU4FxbLDC6TMDX5HXOuafusGu+7Y9WAoqBaYHZ5hcFa7jfkpggyexfeXQ==", "requires": { "@types/node": "*" } }, + "@types/minimist": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.3.tgz", + "integrity": "sha512-ZYFzrvyWUNhaPomn80dsMNgMeXxNWZBdkuG/hWlUvXvbdUH8ZERNBGXnU87McuGcWDsyzX2aChCv/SVN348k3A==", + "dev": true + }, "@types/node": { - "version": "14.14.25", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.25.tgz", - "integrity": "sha512-EPpXLOVqDvisVxtlbvzfyqSsFeQxltFbluZNRndIb8tr9KiBnYNLzrc1N3pyKUCww2RNrfHDViqDWWE1LCJQtQ==" + "version": "20.8.6", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.6.tgz", + "integrity": "sha512-eWO4K2Ji70QzKUqRy6oyJWUeB7+g2cRagT3T/nxYibYcT4y2BDL8lqolRXjTHmkZCdJfIPaY73KbJAZmcryxTQ==", + "requires": { + "undici-types": "~5.25.1" + } + }, + "@types/normalize-package-data": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.2.tgz", + "integrity": "sha512-lqa4UEhhv/2sjjIQgjX8B+RBjj47eo0mzGasklVJ78UKGQY1r0VpB9XHDaZZO9qzEFDdy4MrXLuEaSmPrPSe/A==", + "dev": true + }, + "@types/p-cancelable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@types/p-cancelable/-/p-cancelable-1.0.1.tgz", + "integrity": "sha512-MGdhuVx7X2yJe4dgOnDQcZQAYgiC/QK1O5HUPgTMTxWYiOlyWEO5DWmPBlXQBU1F6/JM7aSgYBDrpt7kurC6dw==", + "requires": { + "p-cancelable": "*" + } + }, + "@types/p-queue": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/@types/p-queue/-/p-queue-2.3.2.tgz", + "integrity": "sha512-eKAv5Ql6k78dh3ULCsSBxX6bFNuGjTmof5Q/T6PiECDq0Yf8IIn46jCyp3RJvCi8owaEmm3DZH1PEImjBMd/vQ==" + }, + "@types/p-retry": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@types/p-retry/-/p-retry-3.0.1.tgz", + "integrity": "sha512-LkZCWg4JxFdQR/nGNZcMiyKAbNG3DKBRS6nn6Hg4dLS82zxkdBJJcvf4zXFvDCEI+e4dZdQX6wreqs9RDGMRfw==", + "requires": { + "p-retry": "*" + } + }, + "@types/retry": { + "version": "0.12.3", + "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.3.tgz", + "integrity": "sha512-rkxEZUFIyDEZhC6EfHz6Hwos2zXewCOLBzhdgv7D55qu4OAySNwDZzxbaMpFI6XthdBa5oHhR5s6/9MSuTfw4g==" + }, + "@types/ws": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-5.1.2.tgz", + "integrity": "sha512-NkTXUKTYdXdnPE2aUUbGOXE1XfMK527SCvU/9bj86kyFF6kZ9ZnOQ3mK5jADn98Y2vEUD/7wKDgZa7Qst2wYOg==", + "requires": { + "@types/events": "*", + "@types/node": "*" + } }, "abbrev": { "version": "1.1.1", @@ -36,25 +9633,54 @@ "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" }, "accepts": { - "version": "1.3.7", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", - "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", "requires": { - "mime-types": "~2.1.24", - "negotiator": "0.6.2" + "mime-types": "~2.1.34", + "negotiator": "0.6.3" } }, - "addressparser": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/addressparser/-/addressparser-0.3.2.tgz", - "integrity": "sha1-WYc/Nej89sc2HBAjkmHXbhU0i7I=" + "acorn": { + "version": "8.10.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", + "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==", + "dev": true }, - "adm-zip": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.4.4.tgz", - "integrity": "sha1-ph7VrmkFw66lizplfSUDMJEFJzY=", + "acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", "dev": true }, + "agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "devOptional": true, + "requires": { + "debug": "4" + } + }, + "agentkeepalive": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.5.0.tgz", + "integrity": "sha512-5GG/5IbQQpC9FpkRGsSvZI5QYeSCzlJHdpBQntCsuTOxhKD8lqKhrleg2Yi7yvMIf82Ycmmqln9U8V9qwEiJew==", + "devOptional": true, + "requires": { + "humanize-ms": "^1.2.1" + } + }, + "aggregate-error": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "devOptional": true, + "requires": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + } + }, "ajv": { "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", @@ -67,82 +9693,50 @@ "uri-js": "^4.2.2" } }, - "amdefine": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", - "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", - "dev": true - }, "ansi-colors": { "version": "3.2.3", "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.3.tgz", "integrity": "sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw==", "dev": true }, - "ansi-gray": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/ansi-gray/-/ansi-gray-0.1.1.tgz", - "integrity": "sha1-KWLPVOyXksSFEKPetSRDaGHvclE=", - "requires": { - "ansi-wrap": "0.1.0" - } - }, "ansi-regex": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==" }, "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" - }, - "ansi-wrap": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/ansi-wrap/-/ansi-wrap-0.1.0.tgz", - "integrity": "sha1-qCJQ3bABXponyoLoLqYDu/pF768=" + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } }, - "aproba": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", - "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" + "any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==" }, - "archy": { + "append-field": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", - "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=" + "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz", + "integrity": "sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==" + }, + "aproba": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", + "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==", + "devOptional": true }, "are-we-there-yet": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz", - "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-3.0.1.tgz", + "integrity": "sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg==", + "devOptional": true, "requires": { "delegates": "^1.0.0", - "readable-stream": "^2.0.6" - }, - "dependencies": { - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - } - } + "readable-stream": "^3.6.0" } }, "argparse": { @@ -152,207 +9746,191 @@ "dev": true, "requires": { "sprintf-js": "~1.0.2" - }, - "dependencies": { - "sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", - "dev": true - } } }, - "arr-diff": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", - "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", + "array-buffer-byte-length": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz", + "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==", "requires": { - "arr-flatten": "^1.0.1" + "call-bind": "^1.0.2", + "is-array-buffer": "^3.0.1" } }, - "arr-flatten": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", - "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==" - }, - "arr-union": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", - "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=" + "array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" }, - "array-differ": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-1.0.0.tgz", - "integrity": "sha1-7/UuN1gknTO+QCuLuOVkuytdQDE=" + "array-includes": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.7.tgz", + "integrity": "sha512-dlcsNBIiWhPkHdOEEKnehA+RNUWDc4UqFtnIXU4uuYDPtA4LDkr7qip2p0VvFAEXNDr0yWZ9PJyIRiGjRLQzwQ==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "get-intrinsic": "^1.2.1", + "is-string": "^1.0.7" + } }, - "array-each": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/array-each/-/array-each-1.0.1.tgz", - "integrity": "sha1-p5SvDAWrF1KEbudTofIRoFugxE8=" + "array.prototype.findlastindex": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.3.tgz", + "integrity": "sha512-LzLoiOMAxvy+Gd3BAq3B7VeIgPdo+Q8hthvKtXybMvRV0jrXfJM/t8mw7nNlpEcVlVUnCnM2KSX4XU5HmpodOA==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0", + "get-intrinsic": "^1.2.1" + } }, - "array-find-index": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", - "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=", - "dev": true + "array.prototype.flat": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz", + "integrity": "sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0" + } }, - "array-flatten": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" + "array.prototype.flatmap": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz", + "integrity": "sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0" + } }, - "array-slice": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-1.1.0.tgz", - "integrity": "sha512-B1qMD3RBP7O8o0H2KbrXDyB0IccejMF15+87Lvlor12ONPRHP6gTjXMNkt/d3ZuOGbAe66hFmaCfECI24Ufp6w==" + "array.prototype.reduce": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/array.prototype.reduce/-/array.prototype.reduce-1.0.6.tgz", + "integrity": "sha512-UW+Mz8LG/sPSU8jRDCjVr6J/ZKAGpHfwrZ6kWTG5qCxIEiXdVshqGnu5vEZA8S1y6X4aCSbQZ0/EEsfvEvBiSg==", + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-array-method-boxes-properly": "^1.0.0", + "is-string": "^1.0.7" + } }, - "array-uniq": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", - "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=" + "arraybuffer.prototype.slice": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.2.tgz", + "integrity": "sha512-yMBKppFur/fbHu9/6USUe03bZ4knMYiwFBcyiaXB8Go0qNehwX6inYPzK9U0NeQvGxKthcmHcaR8P5MStSRBAw==", + "requires": { + "array-buffer-byte-length": "^1.0.0", + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "get-intrinsic": "^1.2.1", + "is-array-buffer": "^3.0.2", + "is-shared-array-buffer": "^1.0.2" + } }, - "array-unique": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", - "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=" + "arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==", + "dev": true }, "asap": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", - "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=" + "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==" }, "asn1": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz", - "integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=" + "integrity": "sha512-6i37w/+EhlWlGUJff3T/Q8u1RGmP5wgbiwYnOnbOqvtrPxT63/sYFyP9RcpxtxGymtfA075IvmOnL7ycNOWl3w==" }, "assert-plus": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" + "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==" }, "assertion-error": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.0.0.tgz", - "integrity": "sha1-x/hUOP3UZrx8oWq5DIFRN5el0js=", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", + "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", "dev": true }, - "assign-symbols": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", - "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=" - }, - "ast-metadata-inferer": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/ast-metadata-inferer/-/ast-metadata-inferer-0.4.0.tgz", - "integrity": "sha512-tKHdBe8N/Vq2nLAm4YPBVREVZjMux6KrqyPfNQgIbDl0t7HaNSmy8w4OyVHYg/cvyn5BW7o7pVwpjPte89Zhcg==" - }, "async": { "version": "1.5.2", "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", - "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=" + "integrity": "sha512-nSVgobk4rv61R9PUSDtYt7mPVB2olxNR5RWJcAsH676/ef11bUZwvu7+RGYrYauVdDPcO519v68wRhXQtxsV9w==" }, "async-foreach": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/async-foreach/-/async-foreach-0.1.3.tgz", - "integrity": "sha1-NhIfhFwFeBct5Bmpfb6x0W7DRUI=", + "integrity": "sha512-VUeSMD8nEGBWaZK4lizI1sf3yEC7pnAQ/mrI7pC2fBz2s/tq5jWWEngTwaf0Gruu/OoXRGLGg1XFqpYBiGTYJA==", "dev": true }, + "async-limiter": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", + "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==" + }, "asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", - "dev": true + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" }, - "atob": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", - "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==" + "available-typed-arrays": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", + "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==" }, "aws-sign2": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", - "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", - "dev": true + "integrity": "sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==", + "dev": true, + "peer": true }, "aws4": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz", - "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==", - "dev": true + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.12.0.tgz", + "integrity": "sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg==", + "dev": true, + "peer": true + }, + "axios": { + "version": "0.18.1", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.18.1.tgz", + "integrity": "sha512-0BfJq4NSfQXd+SkFdrvFbG7addhYSBA2mQwISr46pD6E5iqkWg02RAs8vyTT/j0RTnoYmeXauBuSv1qKwR179g==", + "requires": { + "follow-redirects": "1.5.10", + "is-buffer": "^2.0.2" + } }, "backoff": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/backoff/-/backoff-2.5.0.tgz", - "integrity": "sha1-9hbtqdPktmuMp/ynn2lXIsX44m8=", + "integrity": "sha512-wC5ihrnUXmR2douXmXLCe5O3zg3GKIyvRi/hi58a/XyRxVI+3/yM0PYueQOZXPXQ9pxBislYkw+sF9b7C/RuMA==", "requires": { "precond": "0.2" } }, "balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, - "base": { - "version": "0.11.2", - "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", - "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", - "requires": { - "cache-base": "^1.0.1", - "class-utils": "^0.3.5", - "component-emitter": "^1.2.1", - "define-property": "^1.0.0", - "isobject": "^3.0.1", - "mixin-deep": "^1.2.0", - "pascalcase": "^0.1.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" - }, - "kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==" - } - } + "base64url": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/base64url/-/base64url-3.0.1.tgz", + "integrity": "sha512-ir1UPr3dkwexU7FdV8qBBbNDRUhMmIekYMFZfi+C/sLNnRESKPl23nB9b2pltqfOQNnGzsDdId90AEtG5tCx4A==" }, "basic-auth": { "version": "2.0.1", @@ -360,13 +9938,21 @@ "integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==", "requires": { "safe-buffer": "5.1.2" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + } } }, "bcrypt-pbkdf": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", - "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", + "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==", "dev": true, + "peer": true, "requires": { "tweetnacl": "^0.14.3" } @@ -374,42 +9960,30 @@ "bcryptjs": { "version": "2.4.3", "resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-2.4.3.tgz", - "integrity": "sha1-mrVie5PmBiH/fNrF2pczAn3x0Ms=" - }, - "beeper": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/beeper/-/beeper-1.1.1.tgz", - "integrity": "sha1-5tXqjF2tABMEpwsiY4RH9pyy+Ak=" - }, - "block-stream": { - "version": "0.0.9", - "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz", - "integrity": "sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=", - "dev": true, - "requires": { - "inherits": "~2.0.0" - } + "integrity": "sha512-V/Hy/X9Vt7f3BbPJEi8BdVFMByHi+jNXrYkW3huaybV/kQ0KJg0Y6PkEMbn+zeT+i+SiKZ/HMqJGIIt4LZDqNQ==" }, "bluebird": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-2.11.0.tgz", - "integrity": "sha1-U0uQM8AiyVecVro7Plpcqvu2UOE=" + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" }, "body-parser": { - "version": "1.19.0", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", - "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", + "version": "1.20.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", + "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", "requires": { - "bytes": "3.1.0", - "content-type": "~1.0.4", + "bytes": "3.1.2", + "content-type": "~1.0.5", "debug": "2.6.9", - "depd": "~1.1.2", - "http-errors": "1.7.2", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", "iconv-lite": "0.4.24", - "on-finished": "~2.3.0", - "qs": "6.7.0", - "raw-body": "2.4.0", - "type-is": "~1.6.17" + "on-finished": "2.4.1", + "qs": "6.11.0", + "raw-body": "2.5.2", + "type-is": "~1.6.18", + "unpipe": "1.0.0" }, "dependencies": { "debug": { @@ -419,6 +9993,11 @@ "requires": { "ms": "2.0.0" } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" } } }, @@ -431,62 +10010,49 @@ "concat-map": "0.0.1" } }, - "braces": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", - "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", - "requires": { - "expand-range": "^1.8.1", - "preserve": "^0.2.0", - "repeat-element": "^1.1.2" - } - }, "browser-stdout": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", "dev": true }, - "browserslist": { - "version": "4.16.3", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.16.3.tgz", - "integrity": "sha512-vIyhWmIkULaq04Gt93txdh+j02yX/JzlyhLYbV3YQCn/zvES3JnY7TifHHvvr1w5hTDluNKMkV05cs4vy8Q7sw==", - "requires": { - "caniuse-lite": "^1.0.30001181", - "colorette": "^1.2.1", - "electron-to-chromium": "^1.3.649", - "escalade": "^3.1.1", - "node-releases": "^1.1.70" - } + "buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" }, - "buildmail": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/buildmail/-/buildmail-2.0.0.tgz", - "integrity": "sha1-8LewpZ6aShtQZrv6BR0kjzgy7s4=", + "builtins": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/builtins/-/builtins-5.0.1.tgz", + "integrity": "sha512-qwVpFEHNfhYJIzNRBvd2C1kyo6jz3ZSMPyyuR47OPdiKWlbYnZNyDWuyR175qDnAJLiCo5fBBqPb3RiXgWlkOQ==", + "dev": true, "requires": { - "addressparser": "^0.3.2", - "libbase64": "^0.1.0", - "libmime": "^1.2.0", - "libqp": "^1.1.0", - "needle": "^0.10.0" + "semver": "^7.0.0" }, "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, "requires": { - "ms": "2.0.0" + "yallist": "^4.0.0" } }, - "needle": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/needle/-/needle-0.10.0.tgz", - "integrity": "sha1-FqJNY/KmEVLrdMzh0Sr4XFB1d9Q=", + "semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, "requires": { - "debug": "^2.1.2", - "iconv-lite": "^0.4.4" + "lru-cache": "^6.0.0" } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true } } }, @@ -501,31 +10067,131 @@ "safe-json-stringify": "~1" } }, + "busboy": { + "version": "0.2.14", + "resolved": "https://registry.npmjs.org/busboy/-/busboy-0.2.14.tgz", + "integrity": "sha512-InWFDomvlkEj+xWLBfU3AvnbVYqeTWmQopiW0tWWEy5yehYm2YkGEc59sUmw/4ty5Zj/b0WHGs1LgecuBSBGrg==", + "requires": { + "dicer": "0.2.5", + "readable-stream": "1.1.x" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==" + }, + "readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha512-+MeVjFf4L44XUkhM1eYbD8fyEsxcV81pqMSR5gblfcLCHfZvbrqy4/qYHE+/R5HoBUT11WV5O08Cr1n3YXkWVQ==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + } + } + }, "bytes": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", - "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==" + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==" }, - "cache-base": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", - "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", + "cacache": { + "version": "16.1.3", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-16.1.3.tgz", + "integrity": "sha512-/+Emcj9DAXxX4cwlLmRI9c166RuL3w30zp4R7Joiv2cQTtTtA+jeuCAjH3ZlGnYS3tKENSrKhAzVVP9GVyzeYQ==", + "dev": true, "requires": { - "collection-visit": "^1.0.0", - "component-emitter": "^1.2.1", - "get-value": "^2.0.6", - "has-value": "^1.0.0", - "isobject": "^3.0.1", - "set-value": "^2.0.0", - "to-object-path": "^0.3.0", - "union-value": "^1.0.0", - "unset-value": "^1.0.0" + "@npmcli/fs": "^2.1.0", + "@npmcli/move-file": "^2.0.0", + "chownr": "^2.0.0", + "fs-minipass": "^2.1.0", + "glob": "^8.0.1", + "infer-owner": "^1.0.4", + "lru-cache": "^7.7.1", + "minipass": "^3.1.6", + "minipass-collect": "^1.0.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "mkdirp": "^1.0.4", + "p-map": "^4.0.0", + "promise-inflight": "^1.0.1", + "rimraf": "^3.0.2", + "ssri": "^9.0.0", + "tar": "^6.1.11", + "unique-filename": "^2.0.0" }, "dependencies": { - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + "brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0" + } + }, + "glob": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" + } + }, + "lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "dev": true + }, + "minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dev": true, + "requires": { + "brace-expansion": "^2.0.1" + } + }, + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true + }, + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + }, + "dependencies": { + "glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + } + } } } }, @@ -538,129 +10204,164 @@ "get-intrinsic": "^1.0.2" } }, + "callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true + }, "camelcase": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", - "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=" + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==" }, "camelcase-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", - "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=", + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-6.2.2.tgz", + "integrity": "sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==", "dev": true, "requires": { - "camelcase": "^2.0.0", - "map-obj": "^1.0.0" + "camelcase": "^5.3.1", + "map-obj": "^4.0.0", + "quick-lru": "^4.0.1" } }, - "caniuse-lite": { - "version": "1.0.30001185", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001185.tgz", - "integrity": "sha512-Fpi4kVNtNvJ15H0F6vwmXtb3tukv3Zg3qhKkOGUq7KJ1J6b9kf4dnNgtEAFXhRsJo0gNj9W60+wBvn0JcTvdTg==" - }, "caseless": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", - "dev": true + "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==", + "dev": true, + "peer": true }, "chai": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/chai/-/chai-2.3.0.tgz", - "integrity": "sha1-ii9qNHSNqAEJD9cyh7Kqc5pOkJo=", + "version": "4.3.10", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.10.tgz", + "integrity": "sha512-0UXG04VuVbruMUYbJ6JctvH0YnC/4q3/AkT18q4NaITo91CUm0liMS9VqzT9vZhVQ/1eqPanMWjBM+Juhfb/9g==", "dev": true, "requires": { - "assertion-error": "1.0.0", - "deep-eql": "0.1.3" + "assertion-error": "^1.1.0", + "check-error": "^1.0.3", + "deep-eql": "^4.1.3", + "get-func-name": "^2.0.2", + "loupe": "^2.3.6", + "pathval": "^1.1.1", + "type-detect": "^4.0.8" } }, "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - } - }, - "chownr": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", - "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" - }, - "class-utils": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", - "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, "requires": { - "arr-union": "^3.1.0", - "define-property": "^0.2.5", - "isobject": "^3.0.0", - "static-extend": "^0.1.1" + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" }, "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, "requires": { - "is-descriptor": "^0.1.0" + "has-flag": "^3.0.0" } - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" } } }, + "check-error": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.3.tgz", + "integrity": "sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==", + "dev": true, + "requires": { + "get-func-name": "^2.0.2" + } + }, + "chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "devOptional": true + }, + "clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "devOptional": true + }, "cli-color": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/cli-color/-/cli-color-0.3.3.tgz", - "integrity": "sha1-EtW90Vj/igsNtAEZiRPAPfBp9vU=", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/cli-color/-/cli-color-1.4.0.tgz", + "integrity": "sha512-xu6RvQqqrWEo6MPR1eixqGPywhYBHRs653F9jfXB2Hx4jdM/3WxiNE1vppRmxtMIfl16SFYTpYlrnqH/HsK/2w==", "requires": { - "d": "~0.1.1", - "es5-ext": "~0.10.6", - "memoizee": "~0.3.8", - "timers-ext": "0.1" + "ansi-regex": "^2.1.1", + "d": "1", + "es5-ext": "^0.10.46", + "es6-iterator": "^2.0.3", + "memoizee": "^0.4.14", + "timers-ext": "^0.1.5" } }, "cliui": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", - "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", + "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", + "dev": true, "requires": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wrap-ansi": "^2.0.0" + "string-width": "^3.1.0", + "strip-ansi": "^5.2.0", + "wrap-ansi": "^5.1.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", + "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", + "dev": true + }, + "emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "dev": true + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + } } }, - "clone": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", - "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=" - }, - "clone-stats": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz", - "integrity": "sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE=" + "cls-bluebird": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cls-bluebird/-/cls-bluebird-2.1.0.tgz", + "integrity": "sha512-XVb0RPmHQyy35Tz9z34gvtUcBKUK8A/1xkGCyeFc9B0C7Zr5SysgFaswRVdwI5NEMcO+3JKlIDGIOgERSn9NdA==", + "requires": { + "is-bluebird": "^1.0.2", + "shimmer": "^1.1.0" + } }, "code-point-at": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" - }, - "collection-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", - "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", - "requires": { - "map-visit": "^1.0.0", - "object-visit": "^1.0.0" - } + "integrity": "sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA==" }, "color-convert": { "version": "1.9.3", @@ -674,71 +10375,107 @@ "color-name": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", "dev": true }, "color-support": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", - "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==" - }, - "colorette": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.2.1.tgz", - "integrity": "sha512-puCDz0CzydiSYOrnXpz/PKd69zRrribezjtE9yd4zvytoRc8+RY/KJPvtPFKZS3E3wP6neGyMe0vOTlHO5L3Pw==" + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", + "devOptional": true }, "combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dev": true, "requires": { "delayed-stream": "~1.0.0" } }, "commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" - }, - "component-emitter": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", - "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==" + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", + "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==" }, "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" + }, + "readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + } + } }, "config-chain": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.12.tgz", - "integrity": "sha512-a1eOIcu8+7lUInge4Rpf/n4Krkf3Dd9lqhljRzII1/Zno/kRtUWnznPO3jOKBmTEktkt3fkxisUcivoj0ebzoA==", + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.13.tgz", + "integrity": "sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==", "requires": { "ini": "^1.3.4", "proto-list": "~1.2.1" } }, "connect-redis": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/connect-redis/-/connect-redis-6.0.0.tgz", - "integrity": "sha512-6eGEAAPHYvcfbRNCMmPzBIjrqRWLw7at9lCUH4G6NQ8gwWDJelaUmFNOqPIhehbw941euVmIuqWsaWiKXfb+5g==" + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/connect-redis/-/connect-redis-6.1.3.tgz", + "integrity": "sha512-aaNluLlAn/3JPxRwdzw7lhvEoU6Enb+d83xnokUNhC9dktqBoawKWL+WuxinxvBLTz6q9vReTnUDnUslaz74aw==" }, "connect-session-sequelize": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/connect-session-sequelize/-/connect-session-sequelize-3.0.0.tgz", - "integrity": "sha1-qaaPTU2QzCG7jqB1OuRHUeouf2o=", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/connect-session-sequelize/-/connect-session-sequelize-6.0.0.tgz", + "integrity": "sha512-XC71xJd5rqObdL7700S/qFD+gSRA4o6WVJAyFY0Vjah73id5bBElM0SHQR1ME5Bxrt4JL8alvggseNDVTlKyxA==", "requires": { - "debug": "^2.1.1" + "debug": "^3.1.0", + "deep-equal": "^1.0.1" }, "dependencies": { "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "requires": { - "ms": "2.0.0" + "ms": "^2.1.1" } } } @@ -746,291 +10483,270 @@ "console-control-strings": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", - "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=" + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==", + "devOptional": true }, "content-disposition": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", - "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", "requires": { - "safe-buffer": "5.1.2" + "safe-buffer": "5.2.1" } }, "content-type": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", - "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==" }, "cookie": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", - "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==" + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz", + "integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==" }, "cookie-parser": { - "version": "1.4.5", - "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.5.tgz", - "integrity": "sha512-f13bPUj/gG/5mDr+xLmSxxDsB9DQiTIfhJS/sqjrmfAWiAN+x2O4i/XguTL9yDZ+/IFDanJ+5x7hC4CXT9Tdzw==", + "version": "1.4.6", + "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.6.tgz", + "integrity": "sha512-z3IzaNjdwUC2olLIB5/ITd0/setiaFMLYiZJle7xg5Fe9KWAceil7xszYfHHBtDFYLSgJduS2Ty0P1uJdPDJeA==", "requires": { - "cookie": "0.4.0", + "cookie": "0.4.1", "cookie-signature": "1.0.6" } }, "cookie-signature": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" - }, - "copy-descriptor": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", - "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=" - }, - "core-js": { - "version": "3.8.3", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.8.3.tgz", - "integrity": "sha512-KPYXeVZYemC2TkNEkX/01I+7yd+nX3KddKwZ1Ww7SKWdI2wQprSgLmrTddT8nw92AjEklTsPBoSdQBhbI1bQ6Q==" + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" }, "core-util-is": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==" }, "cross-spawn": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-3.0.1.tgz", - "integrity": "sha1-ElYDfsufDF9549bvE14wdwGEuYI=", + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", "dev": true, "requires": { - "lru-cache": "^4.0.1", - "which": "^1.2.9" + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" }, "dependencies": { - "lru-cache": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", - "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", "dev": true, "requires": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" + "isexe": "^2.0.0" } - }, - "yallist": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", - "dev": true } } }, "csv": { - "version": "0.4.6", - "resolved": "https://registry.npmjs.org/csv/-/csv-0.4.6.tgz", - "integrity": "sha1-jbrn3f26rmLB6ph8Pg+Kmsc3tz0=", + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/csv/-/csv-5.1.3.tgz", + "integrity": "sha512-uHPF5nxxFgcBQ/Mkicjh+IcQJeooIcN8gS/5mnvIdIccLh3Qf792jXE00ovdYDmABhE0yTMNCZgx3ZsBrR2GoQ==", "requires": { - "csv-generate": "^0.0.6", - "csv-parse": "^1.0.0", - "csv-stringify": "^0.0.8", - "stream-transform": "^0.1.0" + "csv-generate": "^3.2.3", + "csv-parse": "^4.4.6", + "csv-stringify": "^5.3.3", + "stream-transform": "^2.0.1" } }, "csv-generate": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/csv-generate/-/csv-generate-0.0.6.tgz", - "integrity": "sha1-l+TmOuRrIZEs2UdbwxRp0m9a3mY=" + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/csv-generate/-/csv-generate-3.4.3.tgz", + "integrity": "sha512-w/T+rqR0vwvHqWs/1ZyMDWtHHSJaN06klRqJXBEpDJaM/+dZkso0OKh1VcuuYvK3XM53KysVNq8Ko/epCK8wOw==" }, "csv-parse": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/csv-parse/-/csv-parse-1.3.3.tgz", - "integrity": "sha1-0c/YdDwvhJoKuy/VRNtWaV0ZpJA=" + "version": "4.16.3", + "resolved": "https://registry.npmjs.org/csv-parse/-/csv-parse-4.16.3.tgz", + "integrity": "sha512-cO1I/zmz4w2dcKHVvpCr7JVRu8/FymG5OEpmvsZYlccYolPBLoVGKUHgNoc4ZGkFeFlWGEDmMyBM+TTqRdW/wg==" }, "csv-stringify": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/csv-stringify/-/csv-stringify-0.0.8.tgz", - "integrity": "sha1-Usw7PfwZd1jFWtMlqVvoUHH55Rs=" - }, - "currently-unhandled": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", - "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=", - "dev": true, - "requires": { - "array-find-index": "^1.0.1" - } + "version": "5.6.5", + "resolved": "https://registry.npmjs.org/csv-stringify/-/csv-stringify-5.6.5.tgz", + "integrity": "sha512-PjiQ659aQ+fUTQqSrd1XEDnOr52jh30RBurfzkscaE2tPaFsDH5wOAHJiw8XAHphRknCwMUE9KRayc4K/NbO8A==" }, "d": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/d/-/d-0.1.1.tgz", - "integrity": "sha1-2hhMU10Y2O57oqoim5FACfrhEwk=", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", + "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", "requires": { - "es5-ext": "~0.10.2" + "es5-ext": "^0.10.50", + "type": "^1.0.1" } }, "dashdash": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", - "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==", "requires": { "assert-plus": "^1.0.0" } }, - "dateformat": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-2.2.0.tgz", - "integrity": "sha1-QGXiATz5+5Ft39gu+1Bq1MZ2kGI=" - }, "debug": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.0.tgz", - "integrity": "sha512-heNPJUJIqC+xB6ayLAMHaIrmN9HKa7aQO8MGqKpvCA+uJYVcvR6l5kgdrhRuwPFHU7P5/A1w0BjByPHwpfTDKg==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", "requires": { "ms": "^2.1.1" - }, - "dependencies": { - "ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" - } } }, "decamelize": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" + "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==" }, - "decode-uri-component": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", - "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=" - }, - "deep-eql": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-0.1.3.tgz", - "integrity": "sha1-71WKyrjeJSBs1xOQbXTlaTDrafI=", + "decamelize-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.1.tgz", + "integrity": "sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==", "dev": true, "requires": { - "type-detect": "0.1.1" - } - }, - "deep-extend": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", - "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==" - }, - "defaults": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", - "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", - "requires": { - "clone": "^1.0.2" + "decamelize": "^1.1.0", + "map-obj": "^1.0.0" + }, + "dependencies": { + "map-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", + "integrity": "sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==", + "dev": true + } } }, - "define-properties": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", - "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "deep-eql": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.3.tgz", + "integrity": "sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==", + "dev": true, "requires": { - "object-keys": "^1.0.12" + "type-detect": "^4.0.0" } }, - "define-property": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", - "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", - "requires": { - "is-descriptor": "^1.0.2", - "isobject": "^3.0.1" - }, - "dependencies": { - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" - }, - "kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==" - } + "deep-equal": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.1.tgz", + "integrity": "sha512-yd9c5AdiqVcR+JjcwUQb9DkhJc8ngNr0MahEBGvDiJw8puWab2yZlh+nkasOnZP+EGTAP6rRp2JzJhJZzvNF8g==", + "requires": { + "is-arguments": "^1.0.4", + "is-date-object": "^1.0.1", + "is-regex": "^1.0.4", + "object-is": "^1.0.1", + "object-keys": "^1.1.1", + "regexp.prototype.flags": "^1.2.0" + } + }, + "deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, + "define-data-property": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.1.tgz", + "integrity": "sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ==", + "requires": { + "get-intrinsic": "^1.2.1", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.0" + } + }, + "define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "requires": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" } }, "delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", - "dev": true + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==" }, "delegates": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", - "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=" + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==", + "devOptional": true }, "denque": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/denque/-/denque-1.5.1.tgz", - "integrity": "sha512-XwE+iZ4D6ZUB7mfYRMb5wByE8L74HCn30FBN7sWnXksWc1LO1bPDl67pBR9o/kC4z/xSNAwkMYcGgqDV3BE3Hw==" + "integrity": "sha512-XwE+iZ4D6ZUB7mfYRMb5wByE8L74HCn30FBN7sWnXksWc1LO1bPDl67pBR9o/kC4z/xSNAwkMYcGgqDV3BE3Hw==", + "optional": true }, "depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" - }, - "deprecated": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/deprecated/-/deprecated-0.0.1.tgz", - "integrity": "sha1-+cmvVGSvoeepcUWKi97yqpTVuxk=" + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" }, "destroy": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", - "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==" }, - "detect-file": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-0.1.0.tgz", - "integrity": "sha1-STXe39lIhkjgBrASlWbpOGcR6mM=", + "detect-libc": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.2.tgz", + "integrity": "sha512-UX6sGumvvqSaXgdKGUsgZWqcUyIXZ/vZTrlRT/iobiKhGL0zL4d3osHj3uqllWJK+i+sixDS/3COVEOFbupFyw==", + "optional": true + }, + "dicer": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/dicer/-/dicer-0.2.5.tgz", + "integrity": "sha512-FDvbtnq7dzlPz0wyYlOExifDEZcu8h+rErEXgfxqmLfRfC/kJidEFh4+effJRO3P0xmfqyPbSMG0LveNRfTKVg==", "requires": { - "fs-exists-sync": "^0.1.0" + "readable-stream": "1.1.x", + "streamsearch": "0.1.2" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==" + }, + "readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha512-+MeVjFf4L44XUkhM1eYbD8fyEsxcV81pqMSR5gblfcLCHfZvbrqy4/qYHE+/R5HoBUT11WV5O08Cr1n3YXkWVQ==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ==" + } } }, - "detect-libc": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", - "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=" - }, "diff": { "version": "3.5.0", "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", "dev": true }, + "doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "requires": { + "esutils": "^2.0.2" + } + }, "dom-serializer": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.2.tgz", @@ -1041,9 +10757,9 @@ }, "dependencies": { "domelementtype": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.1.0.tgz", - "integrity": "sha512-LsTgx/L5VpD+Q8lmsXSHW2WpA+eBlZ9HPf3erD1IoPF00/3JKHZ3BknUVA2QGDNu69ZNmyFmCWBSO45XjYKC5w==" + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==" }, "entities": { "version": "2.2.0", @@ -1075,9 +10791,9 @@ } }, "dottie": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/dottie/-/dottie-1.1.1.tgz", - "integrity": "sha1-RcKj9IvWUo7u0memmoSOqspvqmo=" + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/dottie/-/dottie-2.0.6.tgz", + "integrity": "sha512-iGCHkfUc5kFekGiqhe8B/mdaurD+lakO9txNnTvKtA6PISrw86LgqHvRzWYPyoE2Ph5aMIrCw9/uko6XHTKCwA==" }, "dtrace-provider": { "version": "0.8.8", @@ -1088,275 +10804,664 @@ "nan": "^2.14.0" } }, - "duplexer2": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.0.2.tgz", - "integrity": "sha1-xhTc9n4vsUmVqRcR5aYX6KYKMds=", + "ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==", + "dev": true, + "peer": true, + "requires": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, + "editorconfig": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/editorconfig/-/editorconfig-1.0.4.tgz", + "integrity": "sha512-L9Qe08KWTlqYMVvMcTIvMAdl1cDUubzRNYL+WfA4bLDMHe4nemKkpmYzkznE1FwLKu0EEmy6obgQKzMJrg4x9Q==", "requires": { - "readable-stream": "~1.1.9" + "@one-ini/wasm": "0.1.1", + "commander": "^10.0.0", + "minimatch": "9.0.1", + "semver": "^7.5.3" }, "dependencies": { - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + "brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "requires": { + "balanced-match": "^1.0.0" + } + }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "requires": { + "yallist": "^4.0.0" + } + }, + "minimatch": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.1.tgz", + "integrity": "sha512-0jWhJpD/MdhPXwPuiRkCbfYfSKp2qnn2eOc279qI7f+osl/l+prKSrvhg157zSYvx/1nmgn2NqdT6k2Z7zSH9w==", + "requires": { + "brace-expansion": "^2.0.1" + } + }, + "semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "requires": { + "lru-cache": "^6.0.0" + } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + } + } + }, + "ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==" + }, + "encoding": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", + "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", + "optional": true, + "requires": { + "iconv-lite": "^0.6.2" + }, + "dependencies": { + "iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "optional": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + } + } + } + }, + "end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "requires": { + "once": "^1.4.0" + } + }, + "entities": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz", + "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==" + }, + "env-paths": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", + "devOptional": true + }, + "err-code": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", + "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==", + "devOptional": true + }, + "error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "requires": { + "is-arrayish": "^0.2.1" + } + }, + "es-abstract": { + "version": "1.22.2", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.2.tgz", + "integrity": "sha512-YoxfFcDmhjOgWPWsV13+2RNjq1F6UQnfs+8TftwNqtzlmFzEXvlUwdrNrYeaizfjQzRMxkZ6ElWMOJIFKdVqwA==", + "requires": { + "array-buffer-byte-length": "^1.0.0", + "arraybuffer.prototype.slice": "^1.0.2", + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "es-set-tostringtag": "^2.0.1", + "es-to-primitive": "^1.2.1", + "function.prototype.name": "^1.1.6", + "get-intrinsic": "^1.2.1", + "get-symbol-description": "^1.0.0", + "globalthis": "^1.0.3", + "gopd": "^1.0.1", + "has": "^1.0.3", + "has-property-descriptors": "^1.0.0", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.5", + "is-array-buffer": "^3.0.2", + "is-callable": "^1.2.7", + "is-negative-zero": "^2.0.2", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.2", + "is-string": "^1.0.7", + "is-typed-array": "^1.1.12", + "is-weakref": "^1.0.2", + "object-inspect": "^1.12.3", + "object-keys": "^1.1.1", + "object.assign": "^4.1.4", + "regexp.prototype.flags": "^1.5.1", + "safe-array-concat": "^1.0.1", + "safe-regex-test": "^1.0.0", + "string.prototype.trim": "^1.2.8", + "string.prototype.trimend": "^1.0.7", + "string.prototype.trimstart": "^1.0.7", + "typed-array-buffer": "^1.0.0", + "typed-array-byte-length": "^1.0.0", + "typed-array-byte-offset": "^1.0.0", + "typed-array-length": "^1.0.4", + "unbox-primitive": "^1.0.2", + "which-typed-array": "^1.1.11" + } + }, + "es-array-method-boxes-properly": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz", + "integrity": "sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA==" + }, + "es-set-tostringtag": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz", + "integrity": "sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==", + "requires": { + "get-intrinsic": "^1.1.3", + "has": "^1.0.3", + "has-tostringtag": "^1.0.0" + } + }, + "es-shim-unscopables": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz", + "integrity": "sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==", + "dev": true, + "requires": { + "has": "^1.0.3" + } + }, + "es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "requires": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + } + }, + "es5-ext": { + "version": "0.10.62", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.62.tgz", + "integrity": "sha512-BHLqn0klhEpnOKSrzn/Xsz2UIW8j+cGmo9JLzr8BiUapV8hPL9+FliFqjwr9ngW7jWdnxv6eO+/LqyhJVqgrjA==", + "requires": { + "es6-iterator": "^2.0.3", + "es6-symbol": "^3.1.3", + "next-tick": "^1.1.0" + } + }, + "es6-iterator": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", + "integrity": "sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==", + "requires": { + "d": "1", + "es5-ext": "^0.10.35", + "es6-symbol": "^3.1.1" + } + }, + "es6-symbol": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", + "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", + "requires": { + "d": "^1.0.1", + "ext": "^1.1.2" + } + }, + "es6-weak-map": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.3.tgz", + "integrity": "sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==", + "requires": { + "d": "1", + "es5-ext": "^0.10.46", + "es6-iterator": "^2.0.3", + "es6-symbol": "^3.1.1" + } + }, + "escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true + }, + "escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true + }, + "eslint": { + "version": "8.51.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.51.0.tgz", + "integrity": "sha512-2WuxRZBrlwnXi+/vFSJyjMqrNjtJqiasMzehF0shoLaW7DzS3/9Yvrmq5JiT66+pNjiX4UBnLDiKHcWAr/OInA==", + "dev": true, + "requires": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.2", + "@eslint/js": "8.51.0", + "@humanwhocodes/config-array": "^0.11.11", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true + }, + "find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "requires": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "requires": { + "argparse": "^2.0.1" + } + }, + "locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "requires": { + "p-locate": "^5.0.0" + } }, - "readable-stream": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" + "yocto-queue": "^0.1.0" } }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" - } - } - }, - "ecc-jsbn": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", - "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", - "dev": true, - "requires": { - "jsbn": "~0.1.0", - "safer-buffer": "^2.1.0" - } - }, - "editorconfig": { - "version": "0.15.3", - "resolved": "https://registry.npmjs.org/editorconfig/-/editorconfig-0.15.3.tgz", - "integrity": "sha512-M9wIMFx96vq0R4F+gRpY3o2exzb8hEj/n9S8unZtHSvYjibBp/iMufSzvmOcV/laG0ZtuTVGtiJggPOSW2r93g==", - "requires": { - "commander": "^2.19.0", - "lru-cache": "^4.1.5", - "semver": "^5.6.0", - "sigmund": "^1.0.1" - }, - "dependencies": { - "lru-cache": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", - "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", + "p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, "requires": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" + "p-limit": "^3.0.2" } }, - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true }, - "yallist": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=" + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } } } }, - "ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" - }, - "electron-to-chromium": { - "version": "1.3.659", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.659.tgz", - "integrity": "sha512-VPc1LcvuQYGjam6k7JcB6uJFTMo2YNlJ6rSbwbxApZQdow7X81kh/vDB6LB5B8DNmvkbKnpZkLmpKmnvoKA+Gw==" - }, - "emoji-regex": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "eslint-config-prettier": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.0.0.tgz", + "integrity": "sha512-IcJsTkJae2S35pRsRAwoCE+925rJJStOdkKnLVgtE+tEpqU0EVVM7OqrwxqgptKdX29NUwC82I5pXsGFIgSevw==", "dev": true }, - "encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" + "eslint-config-standard": { + "version": "17.1.0", + "resolved": "https://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-17.1.0.tgz", + "integrity": "sha512-IwHwmaBNtDK4zDHQukFDW5u/aTb8+meQWZvNFWkiGmbWjD6bqyuSSBxxXKkCftCUzc1zwCH2m/baCNDLGmuO5Q==", + "dev": true }, - "end-of-stream": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-0.1.5.tgz", - "integrity": "sha1-jhdyBsPICDfYVjLouTWd/osvbq8=", + "eslint-import-resolver-node": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", + "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==", + "dev": true, "requires": { - "once": "~1.3.0" + "debug": "^3.2.7", + "is-core-module": "^2.13.0", + "resolve": "^1.22.4" }, "dependencies": { - "once": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/once/-/once-1.3.3.tgz", - "integrity": "sha1-suJhVXzkwxTsgwTz+oJmPkKXyiA=", + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, "requires": { - "wrappy": "1" + "ms": "^2.1.1" } } } }, - "entities": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz", - "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==" - }, - "error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "requires": { - "is-arrayish": "^0.2.1" - } - }, - "es-abstract": { - "version": "1.18.0-next.2", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0-next.2.tgz", - "integrity": "sha512-Ih4ZMFHEtZupnUh6497zEL4y2+w8+1ljnCyaTa+adcoafI1GOvMwFlDjBLfWR7y9VLfrjRJe9ocuHY1PSR9jjw==", + "eslint-module-utils": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.0.tgz", + "integrity": "sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==", "dev": true, "requires": { - "call-bind": "^1.0.2", - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2", - "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.2.2", - "is-negative-zero": "^2.0.1", - "is-regex": "^1.1.1", - "object-inspect": "^1.9.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.2", - "string.prototype.trimend": "^1.0.3", - "string.prototype.trimstart": "^1.0.3" + "debug": "^3.2.7" + }, + "dependencies": { + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + } } }, - "es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "eslint-plugin-es-x": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-es-x/-/eslint-plugin-es-x-7.2.0.tgz", + "integrity": "sha512-9dvv5CcvNjSJPqnS5uZkqb3xmbeqRLnvXKK7iI5+oK/yTusyc46zbBZKENGsOfojm/mKfszyZb+wNqNPAPeGXA==", "dev": true, "requires": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - } - }, - "es5-ext": { - "version": "0.10.53", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.53.tgz", - "integrity": "sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q==", - "requires": { - "es6-iterator": "~2.0.3", - "es6-symbol": "~3.1.3", - "next-tick": "~1.0.0" + "@eslint-community/eslint-utils": "^4.1.2", + "@eslint-community/regexpp": "^4.6.0" } }, - "es6-iterator": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", - "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", + "eslint-plugin-import": { + "version": "2.28.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.28.1.tgz", + "integrity": "sha512-9I9hFlITvOV55alzoKBI+K9q74kv0iKMeY6av5+umsNwayt59fz692daGyjR+oStBQgx6nwR9rXldDev3Clw+A==", + "dev": true, "requires": { - "d": "1", - "es5-ext": "^0.10.35", - "es6-symbol": "^3.1.1" + "array-includes": "^3.1.6", + "array.prototype.findlastindex": "^1.2.2", + "array.prototype.flat": "^1.3.1", + "array.prototype.flatmap": "^1.3.1", + "debug": "^3.2.7", + "doctrine": "^2.1.0", + "eslint-import-resolver-node": "^0.3.7", + "eslint-module-utils": "^2.8.0", + "has": "^1.0.3", + "is-core-module": "^2.13.0", + "is-glob": "^4.0.3", + "minimatch": "^3.1.2", + "object.fromentries": "^2.0.6", + "object.groupby": "^1.0.0", + "object.values": "^1.1.6", + "semver": "^6.3.1", + "tsconfig-paths": "^3.14.2" }, "dependencies": { - "d": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", - "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, "requires": { - "es5-ext": "^0.10.50", - "type": "^1.0.1" + "esutils": "^2.0.2" } + }, + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true } } }, - "es6-symbol": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", - "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", + "eslint-plugin-mocha": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-mocha/-/eslint-plugin-mocha-10.2.0.tgz", + "integrity": "sha512-ZhdxzSZnd1P9LqDPF0DBcFLpRIGdh1zkF2JHnQklKQOvrQtT73kdP5K9V2mzvbLR+cCAO9OI48NXK/Ax9/ciCQ==", + "dev": true, "requires": { - "d": "^1.0.1", - "ext": "^1.1.2" - }, - "dependencies": { - "d": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", - "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", - "requires": { - "es5-ext": "^0.10.50", - "type": "^1.0.1" - } - } + "eslint-utils": "^3.0.0", + "rambda": "^7.4.0" } }, - "es6-weak-map": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-0.1.4.tgz", - "integrity": "sha1-cGzvnpmqI2undmwjnIueKG6n0ig=", + "eslint-plugin-n": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-n/-/eslint-plugin-n-16.2.0.tgz", + "integrity": "sha512-AQER2jEyQOt1LG6JkGJCCIFotzmlcCZFur2wdKrp1JX2cNotC7Ae0BcD/4lLv3lUAArM9uNS8z/fsvXTd0L71g==", + "dev": true, "requires": { - "d": "~0.1.1", - "es5-ext": "~0.10.6", - "es6-iterator": "~0.1.3", - "es6-symbol": "~2.0.1" + "@eslint-community/eslint-utils": "^4.4.0", + "builtins": "^5.0.1", + "eslint-plugin-es-x": "^7.1.0", + "get-tsconfig": "^4.7.0", + "ignore": "^5.2.4", + "is-core-module": "^2.12.1", + "minimatch": "^3.1.2", + "resolve": "^1.22.2", + "semver": "^7.5.3" }, "dependencies": { - "es6-iterator": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-0.1.3.tgz", - "integrity": "sha1-1vWLjE/EE8JJtLqhl2j45NfIlE4=", + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, "requires": { - "d": "~0.1.1", - "es5-ext": "~0.10.5", - "es6-symbol": "~2.0.1" + "yallist": "^4.0.0" } }, - "es6-symbol": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-2.0.1.tgz", - "integrity": "sha1-dhtcZ8/U8dGK+yNPaR1nhoLLO/M=", + "semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, "requires": { - "d": "~0.1.1", - "es5-ext": "~0.10.5" + "lru-cache": "^6.0.0" } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true } } }, - "escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==" + "eslint-plugin-promise": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-6.1.1.tgz", + "integrity": "sha512-tjqWDwVZQo7UIPMeDReOpUgHCmCiH+ePnVT+5zVapL0uuHnegBUs2smM13CzOs2Xb5+MHMRFTs9v24yjba4Oig==", + "dev": true }, - "escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" + "eslint-scope": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "dev": true, + "requires": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + } }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" - }, - "eslint-plugin-compat": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-compat/-/eslint-plugin-compat-3.9.0.tgz", - "integrity": "sha512-lt3l5PHFHVEYSZ5zijcoYvtQJPsBifRiH5N0Et57KwVu7l/yxmHhSG6VJiLMa/lXrg93Qu8049RNQOMn0+yJBg==", - "requires": { - "@mdn/browser-compat-data": "^2.0.7", - "ast-metadata-inferer": "^0.4.0", - "browserslist": "^4.12.2", - "caniuse-lite": "^1.0.30001166", - "core-js": "^3.6.5", - "find-up": "^4.1.0", - "lodash.memoize": "4.1.2", - "semver": "7.3.2" + "eslint-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", + "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^2.0.0" + }, + "dependencies": { + "eslint-visitor-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", + "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", + "dev": true + } + } + }, + "eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true + }, + "espree": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "dev": true, + "requires": { + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" } }, "esprima": { @@ -1365,92 +11470,158 @@ "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", "dev": true }, + "esquery": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", + "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", + "dev": true, + "requires": { + "estraverse": "^5.1.0" + } + }, + "esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "requires": { + "estraverse": "^5.2.0" + } + }, + "estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true + }, + "esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true + }, "etag": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==" }, "event-emitter": { "version": "0.3.5", "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", - "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=", + "integrity": "sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA==", "requires": { "d": "1", "es5-ext": "~0.10.14" + } + }, + "eventemitter3": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-3.1.2.tgz", + "integrity": "sha512-tvtQIeLVHjDkJYnzf2dgVMxfuSGJeM/7UCG17TT4EumTfNtF+0nebF/4zWOIkCreAbtNqhGEboB6BWrwqNaw4Q==" + }, + "execa": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", + "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", + "requires": { + "cross-spawn": "^6.0.0", + "get-stream": "^4.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" }, "dependencies": { - "d": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", - "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==" + }, + "shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==", "requires": { - "es5-ext": "^0.10.50", - "type": "^1.0.1" + "shebang-regex": "^1.0.0" } } } }, - "expand-brackets": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", - "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", - "requires": { - "is-posix-bracket": "^0.1.0" - } - }, - "expand-range": { - "version": "1.8.2", - "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz", - "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=", - "requires": { - "fill-range": "^2.1.0" - } - }, - "expand-tilde": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-1.2.2.tgz", - "integrity": "sha1-C4HrqJflo9MdHD0QL48BRB5VlEk=", - "requires": { - "os-homedir": "^1.0.1" - } - }, "express": { - "version": "4.17.1", - "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", - "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", + "version": "4.18.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", + "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==", "requires": { - "accepts": "~1.3.7", + "accepts": "~1.3.8", "array-flatten": "1.1.1", - "body-parser": "1.19.0", - "content-disposition": "0.5.3", + "body-parser": "1.20.1", + "content-disposition": "0.5.4", "content-type": "~1.0.4", - "cookie": "0.4.0", + "cookie": "0.5.0", "cookie-signature": "1.0.6", "debug": "2.6.9", - "depd": "~1.1.2", + "depd": "2.0.0", "encodeurl": "~1.0.2", "escape-html": "~1.0.3", "etag": "~1.8.1", - "finalhandler": "~1.1.2", + "finalhandler": "1.2.0", "fresh": "0.5.2", + "http-errors": "2.0.0", "merge-descriptors": "1.0.1", "methods": "~1.1.2", - "on-finished": "~2.3.0", + "on-finished": "2.4.1", "parseurl": "~1.3.3", "path-to-regexp": "0.1.7", - "proxy-addr": "~2.0.5", - "qs": "6.7.0", + "proxy-addr": "~2.0.7", + "qs": "6.11.0", "range-parser": "~1.2.1", - "safe-buffer": "5.1.2", - "send": "0.17.1", - "serve-static": "1.14.1", - "setprototypeof": "1.1.1", - "statuses": "~1.5.0", + "safe-buffer": "5.2.1", + "send": "0.18.0", + "serve-static": "1.15.0", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", "type-is": "~1.6.18", "utils-merge": "1.0.1", "vary": "~1.1.2" }, "dependencies": { + "body-parser": { + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", + "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", + "requires": { + "bytes": "3.1.2", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.11.0", + "raw-body": "2.5.1", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + } + }, + "cookie": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", + "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==" + }, "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", @@ -1467,34 +11638,39 @@ "integrity": "sha512-7QlaXnSREMmN5P2o4gmpUZDfJlLtfBka9d6r7/ccXaU7rPp76odw9YYtwZYdIiha2JqwiaG6o2Wu6NZJQ0u7Fg==", "requires": { "glob": "^7.1.3", - "graceful-fs": "^4.1.2", + "graceful-fs": "4.2.11", "handlebars": "^4.1.2", "object.assign": "^4.1.0", "promise": "^8.0.2" }, "dependencies": { "graceful-fs": { - "version": "4.2.8", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz", - "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==" + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" } } }, "express-session": { - "version": "1.17.1", - "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.17.1.tgz", - "integrity": "sha512-UbHwgqjxQZJiWRTMyhvWGvjBQduGCSBDhhZXYenziMFjxst5rMV+aJZ6hKPHZnPyHGsrqRICxtX8jtEbm/z36Q==", + "version": "1.17.3", + "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.17.3.tgz", + "integrity": "sha512-4+otWXlShYlG1Ma+2Jnn+xgKUZTMJ5QD3YvfilX3AcocOAbIkVylSWEklzALe/+Pu4qV6TYBj5GwOBFfdKqLBw==", "requires": { - "cookie": "0.4.0", + "cookie": "0.4.2", "cookie-signature": "1.0.6", "debug": "2.6.9", "depd": "~2.0.0", "on-headers": "~1.0.2", "parseurl": "~1.3.3", - "safe-buffer": "5.2.0", + "safe-buffer": "5.2.1", "uid-safe": "~2.1.5" }, "dependencies": { + "cookie": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", + "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==" + }, "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", @@ -1502,81 +11678,35 @@ "requires": { "ms": "2.0.0" } - }, - "depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" - }, - "safe-buffer": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz", - "integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==" } } }, "ext": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/ext/-/ext-1.4.0.tgz", - "integrity": "sha512-Key5NIsUxdqKg3vIsdw9dSuXpPCQ297y6wBjL30edxwPgt2E44WcWBZey/ZvUc6sERLTxKdyCu4gZFmUbk1Q7A==", - "requires": { - "type": "^2.0.0" - }, - "dependencies": { - "type": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/type/-/type-2.1.0.tgz", - "integrity": "sha512-G9absDWvhAWCV2gmF1zKud3OyC61nZDwWvBL2DApaVFogI07CprggiQAOOjvp2NRjYWFzPyu7vwtDrQFq8jeSA==" - } - } - }, - "extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" - }, - "extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/ext/-/ext-1.7.0.tgz", + "integrity": "sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw==", "requires": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" + "type": "^2.7.2" }, - "dependencies": { - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "requires": { - "is-plain-object": "^2.0.4" - } + "dependencies": { + "type": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/type/-/type-2.7.2.tgz", + "integrity": "sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw==" } } }, - "extglob": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", - "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", - "requires": { - "is-extglob": "^1.0.0" - } + "extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "dev": true, + "peer": true }, "extsprintf": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.2.0.tgz", - "integrity": "sha1-WtlGwi9bMrp/jNdCZxHG6KP8JSk=" - }, - "fancy-log": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.3.tgz", - "integrity": "sha512-k9oEhlyc0FrVh25qYuSELjr8oxsCoc4/LEZfg2iJJrfEk/tZL9bCoJE47gqAvI2m/AUjluCS4+3I0eTx8n3AEw==", - "requires": { - "ansi-gray": "^0.1.1", - "color-support": "^1.1.3", - "parse-node-version": "^1.0.0", - "time-stamp": "^1.0.0" - } + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==" }, "fast-deep-equal": { "version": "3.1.3", @@ -1590,34 +11720,41 @@ "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", "dev": true }, - "filename-regex": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", - "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=" + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true + }, + "fastq": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", + "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", + "dev": true, + "requires": { + "reusify": "^1.0.4" + } }, - "fill-range": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.4.tgz", - "integrity": "sha512-cnrcCbj01+j2gTG921VZPnHbjmdAf8oQV/iGeV2kZxGSyfYjjTyY79ErsK1WJWMpw6DaApEX72binqJE+/d+5Q==", + "file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, "requires": { - "is-number": "^2.1.0", - "isobject": "^2.0.0", - "randomatic": "^3.0.0", - "repeat-element": "^1.1.2", - "repeat-string": "^1.5.2" + "flat-cache": "^3.0.4" } }, "finalhandler": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", - "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", + "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", "requires": { "debug": "2.6.9", "encodeurl": "~1.0.2", "escape-html": "~1.0.3", - "on-finished": "~2.3.0", + "on-finished": "2.4.1", "parseurl": "~1.3.3", - "statuses": "~1.5.0", + "statuses": "2.0.1", "unpipe": "~1.0.0" }, "dependencies": { @@ -1628,107 +11765,101 @@ "requires": { "ms": "2.0.0" } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" } } }, - "find-index": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/find-index/-/find-index-0.1.1.tgz", - "integrity": "sha1-Z101iyyjiS15Whq0cjL4tuLg3eQ=" - }, "find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", "requires": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" + "locate-path": "^3.0.0" } }, - "findup-sync": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-0.4.3.tgz", - "integrity": "sha1-QAQ5Kee8YK3wt/SCfExudaDeyhI=", + "finity": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/finity/-/finity-0.5.4.tgz", + "integrity": "sha512-3l+5/1tuw616Lgb0QBimxfdd2TqaDGpfCBpfX6EqtFmqUV3FtQnVEX4Aa62DagYEqnsTIjZcTfbq9msDbXYgyA==" + }, + "flat": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/flat/-/flat-4.1.1.tgz", + "integrity": "sha512-FmTtBsHskrU6FJ2VxCnsDb84wu9zhmO3cUX2kGFb5tuwhfXxGciiT0oRY+cck35QmG+NmGh5eLz6lLCpWTqwpA==", + "dev": true, "requires": { - "detect-file": "^0.1.0", - "is-glob": "^2.0.1", - "micromatch": "^2.3.7", - "resolve-dir": "^0.1.0" + "is-buffer": "~2.0.3" } }, - "fined": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/fined/-/fined-1.2.0.tgz", - "integrity": "sha512-ZYDqPLGxDkDhDZBjZBb+oD1+j0rA4E0pXY50eplAAOPg2N/gUBSSk5IM1/QhPfyVo19lJ+CvXpqfvk+b2p/8Ng==", + "flat-cache": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.1.1.tgz", + "integrity": "sha512-/qM2b3LUIaIgviBQovTLvijfyOQXPtSRnRK26ksj2J7rzPIecePUIpJsZ4T02Qg+xiAEKIs5K8dsHEd+VaKa/Q==", + "dev": true, "requires": { - "expand-tilde": "^2.0.2", - "is-plain-object": "^2.0.3", - "object.defaults": "^1.1.0", - "object.pick": "^1.2.0", - "parse-filepath": "^1.0.1" + "flatted": "^3.2.9", + "keyv": "^4.5.3", + "rimraf": "^3.0.2" }, "dependencies": { - "expand-tilde": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", - "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, "requires": { - "homedir-polyfill": "^1.0.1" + "glob": "^7.1.3" } } } }, - "first-chunk-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/first-chunk-stream/-/first-chunk-stream-1.0.0.tgz", - "integrity": "sha1-Wb+1DNkF9g18OUzT2ayqtOatk04=" - }, - "flagged-respawn": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-1.0.1.tgz", - "integrity": "sha512-lNaHNVymajmk0OJMBn8fVUAU1BtDeKIqKoVhk4xAALB57aALg6b4W0MfJ/cUE0g9YBXy5XhSlPIpYIJ7HaY/3Q==" + "flatted": { + "version": "3.2.9", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.9.tgz", + "integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==", + "dev": true }, - "flat": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/flat/-/flat-4.1.1.tgz", - "integrity": "sha512-FmTtBsHskrU6FJ2VxCnsDb84wu9zhmO3cUX2kGFb5tuwhfXxGciiT0oRY+cck35QmG+NmGh5eLz6lLCpWTqwpA==", - "dev": true, + "follow-redirects": { + "version": "1.5.10", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.10.tgz", + "integrity": "sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ==", "requires": { - "is-buffer": "~2.0.3" + "debug": "=3.1.0" }, "dependencies": { - "is-buffer": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz", - "integrity": "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==", - "dev": true + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "requires": { + "ms": "2.0.0" + } } } }, - "for-in": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", - "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=" - }, - "for-own": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", - "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", + "for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", "requires": { - "for-in": "^1.0.1" + "is-callable": "^1.1.3" } }, "forever-agent": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", - "dev": true + "integrity": "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==", + "dev": true, + "peer": true }, "form-data": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", - "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", - "dev": true, + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.1.tgz", + "integrity": "sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA==", "requires": { "asynckit": "^0.4.0", "combined-stream": "^1.0.6", @@ -1736,361 +11867,283 @@ } }, "formidable": { - "version": "1.0.17", - "resolved": "https://registry.npmjs.org/formidable/-/formidable-1.0.17.tgz", - "integrity": "sha1-71SRSQ+UM7cF+qdyScmQKa40hVk=" + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/formidable/-/formidable-1.2.6.tgz", + "integrity": "sha512-KcpbcpuLNOwrEjnbpMC0gS+X8ciDoZE1kkqzat4a8vrprf+s9pKNQ/QIwWfbfs4ltgmFl3MD177SNTkve3BwGQ==" }, "forwarded": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", - "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=" - }, - "fragment-cache": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", - "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", - "requires": { - "map-cache": "^0.2.2" - } + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==" }, "fresh": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" - }, - "fs-exists-sync": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/fs-exists-sync/-/fs-exists-sync-0.1.0.tgz", - "integrity": "sha1-mC1ok6+RjnLQjeyehnP/K1qNat0=" + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==" }, "fs-extra": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-1.0.0.tgz", - "integrity": "sha1-zTzl9+fLYUWIP8rjGR6Yd/hYeVA=", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", + "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", "requires": { - "graceful-fs": "^4.1.2", - "jsonfile": "^2.1.0", - "klaw": "^1.0.0" + "graceful-fs": "4.2.11", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" }, "dependencies": { "graceful-fs": { - "version": "4.2.8", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz", - "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==" + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" } } }, "fs-minipass": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.7.tgz", - "integrity": "sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "devOptional": true, "requires": { - "minipass": "^2.6.0" + "minipass": "^3.0.0" } }, "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" }, - "fstream": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.12.tgz", - "integrity": "sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==", - "dev": true, + "function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==" + }, + "function.prototype.name": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz", + "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==", "requires": { - "graceful-fs": "^4.1.2", - "inherits": "~2.0.0", - "mkdirp": ">=0.5 0", - "rimraf": "2" - }, - "dependencies": { - "graceful-fs": { - "version": "4.2.8", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz", - "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==", - "dev": true - } + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "functions-have-names": "^1.2.3" } }, - "function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + "functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==" }, "gauge": { - "version": "2.7.4", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", - "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-4.0.4.tgz", + "integrity": "sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==", + "devOptional": true, "requires": { - "aproba": "^1.0.3", - "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.0", - "object-assign": "^4.1.0", - "signal-exit": "^3.0.0", - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wide-align": "^1.1.0" + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.3", + "console-control-strings": "^1.1.0", + "has-unicode": "^2.0.1", + "signal-exit": "^3.0.7", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.5" }, "dependencies": { - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" + "wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "devOptional": true, + "requires": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } } } }, "gaze": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/gaze/-/gaze-0.5.2.tgz", - "integrity": "sha1-QLcJU30k0dRXZ9takIaJ3+aaxE8=", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/gaze/-/gaze-1.1.3.tgz", + "integrity": "sha512-BRdNm8hbWzFzWHERTrejLqwHDfS4GibPoq5wjTPIoJHoBtKGPg3xAFfxmM+9ztbXelxcf2hwQcaz1PtmFeue8g==", + "dev": true, "requires": { - "globule": "~0.1.0" + "globule": "^1.0.0" } }, - "generic-pool": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/generic-pool/-/generic-pool-2.4.2.tgz", - "integrity": "sha1-iGvFvwvrfblugby7oHiBjeWmJoM=" + "generate-function": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.3.1.tgz", + "integrity": "sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==", + "optional": true, + "requires": { + "is-property": "^1.0.2" + } }, "get-caller-file": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", - "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==" + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true + }, + "get-func-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz", + "integrity": "sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==", + "dev": true }, "get-intrinsic": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", - "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz", + "integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==", "requires": { "function-bind": "^1.1.1", "has": "^1.0.3", - "has-symbols": "^1.0.1" + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3" } }, "get-stdin": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", - "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=", + "integrity": "sha512-F5aQMywwJ2n85s4hJPTT9RPxGmubonuB10MNYo17/xph174n2MIR33HRguhzVag10O/npM7SPk73LMZNP+FaWw==", "dev": true }, - "get-value": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", - "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=" + "get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "requires": { + "pump": "^3.0.0" + } + }, + "get-symbol-description": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", + "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", + "requires": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.1" + } + }, + "get-tsconfig": { + "version": "4.7.2", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.7.2.tgz", + "integrity": "sha512-wuMsz4leaj5hbGgg4IvDU0bqJagpftG5l5cXIAvo8uZrqn0NJqwtfupTN00VnkQJPcIRrxYrm1Ue24btpCha2A==", + "dev": true, + "requires": { + "resolve-pkg-maps": "^1.0.0" + } }, "getpass": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", - "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==", "dev": true, + "peer": true, "requires": { "assert-plus": "^1.0.0" } }, "glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", "requires": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", - "minimatch": "^3.0.4", + "minimatch": "^3.1.1", "once": "^1.3.0", "path-is-absolute": "^1.0.0" } }, - "glob-base": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz", - "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=", - "requires": { - "glob-parent": "^2.0.0", - "is-glob": "^2.0.0" - } - }, "glob-parent": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", - "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, "requires": { - "is-glob": "^2.0.0" + "is-glob": "^4.0.3" } }, - "glob-stream": { - "version": "3.1.18", - "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-3.1.18.tgz", - "integrity": "sha1-kXCl8St5Awb9/lmPMT+PeVT9FDs=", + "globals": { + "version": "13.23.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.23.0.tgz", + "integrity": "sha512-XAmF0RjlrjY23MA51q3HltdlGxUpXPvg0GioKiD9X6HD28iMjo2dKC8Vqwm7lne4GNr78+RHTfliktR6ZH09wA==", + "dev": true, "requires": { - "glob": "^4.3.1", - "glob2base": "^0.0.12", - "minimatch": "^2.0.1", - "ordered-read-streams": "^0.1.0", - "through2": "^0.6.1", - "unique-stream": "^1.0.0" + "type-fest": "^0.20.2" }, "dependencies": { - "glob": { - "version": "4.5.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-4.5.3.tgz", - "integrity": "sha1-xstz0yJsHv7wTePFbQEvAzd+4V8=", - "requires": { - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^2.0.1", - "once": "^1.3.0" - } - }, - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" - }, - "minimatch": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-2.0.10.tgz", - "integrity": "sha1-jQh8OcazjAAbl/ynzm0OHoCvusc=", - "requires": { - "brace-expansion": "^1.0.0" - } - }, - "readable-stream": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" - }, - "through2": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", - "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", - "requires": { - "readable-stream": ">=1.0.33-1 <1.1.0-0", - "xtend": ">=4.0.0 <4.1.0-0" - } + "type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true } } }, - "glob-watcher": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-0.0.6.tgz", - "integrity": "sha1-uVtKjfdLOcgymLDAXJeLTZo7cQs=", - "requires": { - "gaze": "^0.5.1" - } - }, - "glob2base": { - "version": "0.0.12", - "resolved": "https://registry.npmjs.org/glob2base/-/glob2base-0.0.12.tgz", - "integrity": "sha1-nUGbPijxLoOjYhZKJ3BVkiycDVY=", - "requires": { - "find-index": "^0.1.1" - } - }, - "global-modules": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-0.2.3.tgz", - "integrity": "sha1-6lo77ULG1s6ZWk+KEmm12uIjgo0=", - "requires": { - "global-prefix": "^0.1.4", - "is-windows": "^0.2.0" - } - }, - "global-prefix": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-0.1.5.tgz", - "integrity": "sha1-jTvGuNo8qBEqFg2NSW/wRiv+948=", + "globalthis": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", + "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", "requires": { - "homedir-polyfill": "^1.0.0", - "ini": "^1.3.4", - "is-windows": "^0.2.0", - "which": "^1.2.12" + "define-properties": "^1.1.3" } }, "globule": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/globule/-/globule-0.1.0.tgz", - "integrity": "sha1-2cjt3h2nnRJaFRt5UzuXhnY0auU=", + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/globule/-/globule-1.3.4.tgz", + "integrity": "sha512-OPTIfhMBh7JbBYDpa5b+Q5ptmMWKwcNcFSR/0c6t8V4f3ZAVBEsKNY37QdVqmLRYSMhOUGYrY0QhSoEpzGr/Eg==", + "dev": true, "requires": { - "glob": "~3.1.21", - "lodash": "~1.0.1", - "minimatch": "~0.2.11" + "glob": "~7.1.1", + "lodash": "^4.17.21", + "minimatch": "~3.0.2" }, "dependencies": { "glob": { - "version": "3.1.21", - "resolved": "https://registry.npmjs.org/glob/-/glob-3.1.21.tgz", - "integrity": "sha1-0p4KBV3qUTj00H7UDomC6DwgZs0=", + "version": "7.1.7", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", + "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", + "dev": true, "requires": { - "graceful-fs": "~1.2.0", - "inherits": "1", - "minimatch": "~0.2.11" - }, - "dependencies": { - "graceful-fs": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-1.2.3.tgz", - "integrity": "sha1-FaSAaldUfLLS2/J/QuiajDRRs2Q=" - } + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" } }, - "graceful-fs": { - "version": "4.2.8", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz", - "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==" - }, - "inherits": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-1.0.2.tgz", - "integrity": "sha1-ykMJ2t7mtUzAuNJH6NfHoJdb3Js=" - }, - "lodash": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-1.0.2.tgz", - "integrity": "sha1-j1dWDIO1n8JwvT1WG2kAQ0MOJVE=" - }, - "lru-cache": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz", - "integrity": "sha1-bUUk6LlV+V1PW1iFHOId1y+06VI=" - }, "minimatch": { - "version": "0.2.14", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz", - "integrity": "sha1-x054BXT2PG+aCQ6Q775u9TpqdWo=", + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.8.tgz", + "integrity": "sha512-6FsRAQsxQ61mw+qP1ZzbL9Bc78x2p5OqNgNpnoAFLTrX8n5Kxph0CsnhmKKNXTWjXqU5L0pGPR7hYk+XWZr60Q==", + "dev": true, "requires": { - "lru-cache": "2", - "sigmund": "~1.0.0" + "brace-expansion": "^1.1.7" } } } }, - "glogg": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/glogg/-/glogg-1.0.2.tgz", - "integrity": "sha512-5mwUoSuBk44Y4EshyiqcH95ZntbDdTQqA3QYSrxmzj28Ai0vXBGMH1ApSANH14j2sIRtqCEyg6PfsuP7ElOEDA==", + "gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", "requires": { - "sparkles": "^1.0.0" + "get-intrinsic": "^1.1.3" } }, "graceful-fs": { - "version": "3.0.12", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.12.tgz", - "integrity": "sha512-J55gaCS4iTTJfTXIxSVw3EMQckcqkpdRv3IR7gu6sq0+tbC363Zx6KH/SEwXASK9JRbhyZmVjJEVJIOxYsB3Qg==", - "requires": { - "natives": "^1.1.3" - } + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" + }, + "graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true }, "growl": { "version": "1.10.5", @@ -2098,208 +12151,89 @@ "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", "dev": true }, - "gulp": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/gulp/-/gulp-3.9.1.tgz", - "integrity": "sha1-VxzkWSjdQK9lFPxAEYZgFsE4RbQ=", - "requires": { - "archy": "^1.0.0", - "chalk": "^1.0.0", - "deprecated": "^0.0.1", - "gulp-util": "^3.0.0", - "interpret": "^1.0.0", - "liftoff": "^2.1.0", - "minimist": "^1.1.0", - "orchestrator": "^0.3.0", - "pretty-hrtime": "^1.0.0", - "semver": "^4.1.0", - "tildify": "^1.0.0", - "v8flags": "^2.0.2", - "vinyl-fs": "^0.3.0" - }, - "dependencies": { - "minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" - }, - "semver": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/semver/-/semver-4.3.6.tgz", - "integrity": "sha1-MAvG4OhjdPe6YQaLWx7NV/xlMto=" - } - } - }, - "gulp-help": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/gulp-help/-/gulp-help-1.6.1.tgz", - "integrity": "sha1-Jh2xhuGDl/7z9qLCLpwxW/qIrgw=", - "requires": { - "chalk": "^1.0.0", - "object-assign": "^3.0.0" - } - }, - "gulp-util": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/gulp-util/-/gulp-util-3.0.8.tgz", - "integrity": "sha1-AFTh50RQLifATBh8PsxQXdVLu08=", - "requires": { - "array-differ": "^1.0.0", - "array-uniq": "^1.0.2", - "beeper": "^1.0.0", - "chalk": "^1.0.0", - "dateformat": "^2.0.0", - "fancy-log": "^1.1.0", - "gulplog": "^1.0.0", - "has-gulplog": "^0.1.0", - "lodash._reescape": "^3.0.0", - "lodash._reevaluate": "^3.0.0", - "lodash._reinterpolate": "^3.0.0", - "lodash.template": "^3.0.0", - "minimist": "^1.1.0", - "multipipe": "^0.1.2", - "object-assign": "^3.0.0", - "replace-ext": "0.0.1", - "through2": "^2.0.0", - "vinyl": "^0.5.0" - }, - "dependencies": { - "minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" - } - } - }, - "gulplog": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/gulplog/-/gulplog-1.0.0.tgz", - "integrity": "sha1-4oxNRdBey77YGDY86PnFkmIp/+U=", - "requires": { - "glogg": "^1.0.0" - } - }, "handlebars": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.5.0.tgz", - "integrity": "sha512-yss1ZbupTpRfe86dpM1abxnnSfxa6eIRn3laqBPIgRYy87qgYtX6xinSOeybjYo/4AVzdTTWK5Kr06A6AllxJg==", + "version": "4.7.8", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz", + "integrity": "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==", "requires": { - "eslint-plugin-compat": "^3.3.0", - "neo-async": "^2.6.0", - "optimist": "^0.6.1", + "minimist": "^1.2.5", + "neo-async": "^2.6.2", "source-map": "^0.6.1", - "uglify-js": "^3.1.4" + "uglify-js": "^3.1.4", + "wordwrap": "^1.0.0" } }, "har-schema": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", - "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", - "dev": true + "integrity": "sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q==", + "dev": true, + "peer": true }, "har-validator": { "version": "5.1.5", "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", "dev": true, + "peer": true, "requires": { "ajv": "^6.12.3", "har-schema": "^2.0.0" } }, + "hard-rejection": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/hard-rejection/-/hard-rejection-2.1.0.tgz", + "integrity": "sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==", + "dev": true + }, "has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "requires": { - "function-bind": "^1.1.1" - } + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.4.tgz", + "integrity": "sha512-qdSAmqLF6209RFj4VVItywPMbm3vWylknmB3nvNiUIs72xAimcM8nVYxYr7ncvZq5qzk9MKIZR8ijqD/1QuYjQ==" }, - "has-ansi": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", - "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", - "requires": { - "ansi-regex": "^2.0.0" - } + "has-bigints": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", + "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==" }, "has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", "dev": true }, - "has-gulplog": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/has-gulplog/-/has-gulplog-0.1.0.tgz", - "integrity": "sha1-ZBTIKRNpfaUVkDl9r7EvIpZ4Ec4=", + "has-property-descriptors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", + "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", "requires": { - "sparkles": "^1.0.0" + "get-intrinsic": "^1.1.1" } }, - "has-symbols": { + "has-proto": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", - "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==" + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", + "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==" }, - "has-unicode": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", - "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=" + "has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==" }, - "has-value": { + "has-tostringtag": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", - "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", + "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", "requires": { - "get-value": "^2.0.6", - "has-values": "^1.0.0", - "isobject": "^3.0.0" - }, - "dependencies": { - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" - } + "has-symbols": "^1.0.2" } }, - "has-values": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", - "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", - "requires": { - "is-number": "^3.0.0", - "kind-of": "^4.0.0" - }, - "dependencies": { - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "kind-of": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", - "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", - "requires": { - "is-buffer": "^1.1.5" - } - } - } + "has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==", + "devOptional": true }, "he": { "version": "1.2.0", @@ -2307,33 +12241,45 @@ "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==" }, "hoek": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.1.tgz", - "integrity": "sha512-QLg82fGkfnJ/4iy1xZ81/9SIJiq1NGFUMGs6ParyjBZr6jW2Ufj/snDqTHixNlHdPNwN2RLVD0Pi3igeK9+JfA==" + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-6.1.3.tgz", + "integrity": "sha512-YXXAAhmF9zpQbC7LEcREFtXfGq5K1fmd+4PHkBq8NUqmzW3G+Dq10bI/i0KucLRwss3YYFQ0fSfoxBZYiGUqtQ==" }, - "homedir-polyfill": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", - "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", + "hosted-git-info": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", + "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==", + "dev": true, "requires": { - "parse-passwd": "^1.0.0" + "lru-cache": "^6.0.0" + }, + "dependencies": { + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + } } }, - "hosted-git-info": { - "version": "2.8.8", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz", - "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==" - }, "html-to-text": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/html-to-text/-/html-to-text-3.3.0.tgz", - "integrity": "sha1-aptjxpm4hbt7qEsURr/mh2u/z7c=", + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/html-to-text/-/html-to-text-5.1.1.tgz", + "integrity": "sha512-Bci6bD/JIfZSvG4s0gW/9mMKwBRoe/1RWLxUME/d6WUSZCdY7T60bssf/jFf7EYXRyqU4P5xdClVqiYU0/ypdA==", "requires": { - "he": "^1.0.0", - "htmlparser2": "^3.9.2", - "optimist": "^0.6.1", - "underscore": "^1.8.3", - "underscore.string": "^3.2.3" + "he": "^1.2.0", + "htmlparser2": "^3.10.1", + "lodash": "^4.17.11", + "minimist": "^1.2.0" } }, "htmlparser2": { @@ -2349,33 +12295,94 @@ "readable-stream": "^3.1.1" } }, + "http-cache-semantics": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", + "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==", + "devOptional": true + }, "http-errors": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", - "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "requires": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + } + }, + "http-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", + "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", + "dev": true, "requires": { - "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.1", - "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.0" + "@tootallnate/once": "2", + "agent-base": "6", + "debug": "4" } }, "http-signature": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", - "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "integrity": "sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ==", "dev": true, + "peer": true, "requires": { "assert-plus": "^1.0.0", "jsprim": "^1.2.2", "sshpk": "^1.7.0" } }, + "httpntlm": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/httpntlm/-/httpntlm-1.6.1.tgz", + "integrity": "sha512-Tcz3Ct9efvNqw3QdTl3h6IgRRlIQxwKkJELN/aAIGnzi2xvb3pDHdnMs8BrxWLV6OoT4DlVyhzSVhFt/tk0lIw==", + "requires": { + "httpreq": ">=0.4.22", + "underscore": "~1.7.0" + }, + "dependencies": { + "underscore": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.7.0.tgz", + "integrity": "sha512-cp0oQQyZhUM1kpJDLdGO1jPZHgS/MpzoWYfe9+CM2h/QGDZlqwT2T3YGukuBdaNJ/CAPoeyAZRRHz8JFo176vA==" + } + } + }, + "httpreq": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/httpreq/-/httpreq-1.1.1.tgz", + "integrity": "sha512-uhSZLPPD2VXXOSN8Cni3kIsoFHaU2pT/nySEU/fHr/ePbqHYr0jeiQRmUKLEirC09SFPsdMoA7LU7UXMd/w0Kw==" + }, + "https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "devOptional": true, + "requires": { + "agent-base": "6", + "debug": "4" + } + }, + "humanize-ms": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", + "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==", + "devOptional": true, + "requires": { + "ms": "^2.0.0" + } + }, "ical-generator": { - "version": "0.2.10", - "resolved": "https://registry.npmjs.org/ical-generator/-/ical-generator-0.2.10.tgz", - "integrity": "sha512-q4TRRGIaG8McNeZRx9sF120vxVuZbPSAMiwn9GgI9+iRrrtUsLZnVUAO7dPP7XSXt+yrrrxP2LbQ+KEnUC6+JQ==" + "version": "1.15.4", + "resolved": "https://registry.npmjs.org/ical-generator/-/ical-generator-1.15.4.tgz", + "integrity": "sha512-drXe4RLkfNlvDvdy/E6BUI9p+01L3ySK1ufNEYI9TxNKG9ZA3G60QWoZvD1dtmH4scwDxYu6/sZBPJvYVNrj8A==", + "requires": { + "moment-timezone": "^0.5.32" + } }, "iconv-lite": { "version": "0.4.24", @@ -2385,286 +12392,296 @@ "safer-buffer": ">= 2.1.2 < 3" } }, - "ignore-walk": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.3.tgz", - "integrity": "sha512-m7o6xuOaT1aqheYHKf8W6J5pYH85ZI9w077erOzLje3JsB1gkafkAhHHY19dqjulgIZHFm32Cp5uNZgcQqdJKw==", - "requires": { - "minimatch": "^3.0.4" - } + "ignore": { + "version": "5.2.4", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", + "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", + "dev": true }, - "in-publish": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/in-publish/-/in-publish-2.0.1.tgz", - "integrity": "sha512-oDM0kUSNFC31ShNxHKUyfZKy8ZeXZBWMjMdZHKLOk13uvT27VTL/QzRGfRUcevJhpkZAvlhPYuXkF7eNWrtyxQ==", + "immediate": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", + "integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==", "dev": true }, - "indent-string": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", - "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=", + "import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", "dev": true, "requires": { - "repeating": "^2.0.0" + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" } }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "devOptional": true + }, + "indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "devOptional": true + }, + "infer-owner": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", + "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", + "devOptional": true + }, "inflection": { "version": "1.12.0", "resolved": "https://registry.npmjs.org/inflection/-/inflection-1.12.0.tgz", - "integrity": "sha1-ogCTVlbW9fa8TcdQLhrstwMihBY=" + "integrity": "sha512-lRy4DxuIFWXlJU7ed8UiTJOSTqStqYdEb4CEbtXfNbkdj3nH1L+reUWiE10VWcJS2yR7tge8Z74pJjtBjNwj0w==" }, "inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", "requires": { "once": "^1.3.0", "wrappy": "1" } }, "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, "ini": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" }, - "interpret": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", - "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==" + "internal-slot": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.5.tgz", + "integrity": "sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==", + "requires": { + "get-intrinsic": "^1.2.0", + "has": "^1.0.3", + "side-channel": "^1.0.4" + } }, "invert-kv": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", - "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=" + "integrity": "sha512-xgs2NH9AE66ucSq4cNG1nhSFghr5l6tdL15Pk+jl46bmmBapgoaY/AacXyaDznAqmGL99TiLSQgO/XazFSKYeQ==" + }, + "ip": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz", + "integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==", + "devOptional": true }, "ipaddr.js": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==" }, - "is-absolute": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-1.0.0.tgz", - "integrity": "sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==", + "is-arguments": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", + "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", "requires": { - "is-relative": "^1.0.0", - "is-windows": "^1.0.1" - }, - "dependencies": { - "is-windows": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", - "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==" - } + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" } }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "is-array-buffer": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz", + "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==", "requires": { - "kind-of": "^3.0.2" + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.0", + "is-typed-array": "^1.1.10" } }, "is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=" - }, - "is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" - }, - "is-callable": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.3.tgz", - "integrity": "sha512-J1DcMe8UYTBSrKezuIUTUwjXsho29693unXM2YhJUTR2txK/eG47bvNa/wipPFmZFgr/N6f1GA66dv0mEyTIyQ==", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", "dev": true }, - "is-core-module": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.2.0.tgz", - "integrity": "sha512-XRAfAdyyY5F5cOXn7hYQDqh2Xmii+DEfIcQGxK/uNwMHhIkPWO0g8msXcbzLe+MpGoR951MlqM/2iIlU4vKDdQ==", - "requires": { - "has": "^1.0.3" - } - }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "is-bigint": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", + "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", "requires": { - "kind-of": "^3.0.2" + "has-bigints": "^1.0.1" } }, - "is-date-object": { + "is-bluebird": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", - "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==", - "dev": true + "resolved": "https://registry.npmjs.org/is-bluebird/-/is-bluebird-1.0.2.tgz", + "integrity": "sha512-PDRu1vVip5dGQg5tfn2qVCCyxbBYu5MhYUJwSfL/RoGBI97n1fxvilVazxzptZW0gcmsMH17H4EVZZI5E/RSeA==" }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "is-boolean-object": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", + "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", "requires": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - }, - "dependencies": { - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==" - } + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" } }, - "is-dotfile": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz", - "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=" + "is-buffer": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz", + "integrity": "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==" }, - "is-equal-shallow": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz", - "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=", + "is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==" + }, + "is-core-module": { + "version": "2.13.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.0.tgz", + "integrity": "sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ==", "requires": { - "is-primitive": "^2.0.0" + "has": "^1.0.3" } }, - "is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=" + "is-date-object": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", + "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "requires": { + "has-tostringtag": "^1.0.0" + } }, "is-extglob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", - "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=" - }, - "is-finite": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.1.0.tgz", - "integrity": "sha512-cdyMtqX/BOqqNBBiKlIVkytNHm49MtMlYyn1zxzvJKWmFMlGzm+ry5BBfYyeY9YmNKbRSo/o7OX9w9ale0wg3w==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", "dev": true }, "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "requires": { - "number-is-nan": "^1.0.0" - } + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" }, "is-glob": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", - "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, "requires": { - "is-extglob": "^1.0.0" + "is-extglob": "^2.1.1" } }, + "is-lambda": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz", + "integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==", + "devOptional": true + }, "is-negative-zero": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.1.tgz", - "integrity": "sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w==", - "dev": true + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", + "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==" }, - "is-number": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", - "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", + "is-number-object": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", + "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", "requires": { - "kind-of": "^3.0.2" + "has-tostringtag": "^1.0.0" } }, - "is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "requires": { - "isobject": "^3.0.1" - }, - "dependencies": { - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" - } - } + "is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true }, - "is-posix-bracket": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz", - "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=" + "is-plain-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", + "integrity": "sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==", + "dev": true }, - "is-primitive": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz", - "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=" + "is-promise": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz", + "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==" + }, + "is-property": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", + "integrity": "sha512-Ks/IoX00TtClbGQr4TWXemAnktAQvYB7HzcCxDGqEZU6oCmb2INHuOoKxbtR+HFkmYWBKv/dOZtGRiAjDhj92g==", + "optional": true }, "is-regex": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.2.tgz", - "integrity": "sha512-axvdhb5pdhEVThqJzYXwMlVuZwC+FF2DpcOhTS+y/8jVq4trxyPgfcwIxIKiyeuLlSQYKkmUaPQJ8ZE4yNKXDg==", - "dev": true, + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", "requires": { "call-bind": "^1.0.2", - "has-symbols": "^1.0.1" + "has-tostringtag": "^1.0.0" } }, - "is-relative": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz", - "integrity": "sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==", + "is-shared-array-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", + "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", + "requires": { + "call-bind": "^1.0.2" + } + }, + "is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==" + }, + "is-string": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", + "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", "requires": { - "is-unc-path": "^1.0.0" + "has-tostringtag": "^1.0.0" } }, "is-symbol": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", - "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", - "dev": true, + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", + "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "requires": { + "has-symbols": "^1.0.2" + } + }, + "is-typed-array": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.12.tgz", + "integrity": "sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==", "requires": { - "has-symbols": "^1.0.1" + "which-typed-array": "^1.1.11" } }, "is-typedarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", - "dev": true + "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==", + "dev": true, + "peer": true }, - "is-unc-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz", - "integrity": "sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==", + "is-weakref": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", + "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", "requires": { - "unc-path-regex": "^0.1.2" + "call-bind": "^1.0.2" } }, - "is-utf8": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", - "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=" - }, - "is-windows": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-0.2.0.tgz", - "integrity": "sha1-3hqm1j6indJIc3tp8f+LgALSEIw=" - }, "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==" }, "isemail": { "version": "3.2.0", @@ -2677,57 +12694,86 @@ "isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" - }, - "isobject": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", - "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", - "requires": { - "isarray": "1.0.0" - } + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" }, "isstream": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", - "dev": true + "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==", + "dev": true, + "peer": true }, "joi": { - "version": "12.0.0", - "resolved": "https://registry.npmjs.org/joi/-/joi-12.0.0.tgz", - "integrity": "sha512-z0FNlV4NGgjQN1fdtHYXf5kmgludM65fG/JlXzU6+rwkt9U5UWuXVYnXa2FpK0u6+qBuCmrm5byPNuiiddAHvQ==", + "version": "14.3.1", + "resolved": "https://registry.npmjs.org/joi/-/joi-14.3.1.tgz", + "integrity": "sha512-LQDdM+pkOrpAn4Lp+neNIFV3axv1Vna3j38bisbQhETPMANYRbFJFUyOZcOClYvM/hppMhGWuKSFEK9vjrB+bQ==", "requires": { - "hoek": "4.x.x", + "hoek": "6.x.x", "isemail": "3.x.x", - "topo": "2.x.x" + "topo": "3.x.x" + } + }, + "js-base64": { + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.6.4.tgz", + "integrity": "sha512-pZe//GGmwJndub7ZghVHz7vjb2LgC1m8B07Au3eYqeqv9emhESByMXxaEgkUkEqJe87oBbSniGYoQNIBklc7IQ==", + "dev": true + }, + "js-beautify": { + "version": "1.14.9", + "resolved": "https://registry.npmjs.org/js-beautify/-/js-beautify-1.14.9.tgz", + "integrity": "sha512-coM7xq1syLcMyuVGyToxcj2AlzhkDjmfklL8r0JgJ7A76wyGMpJ1oA35mr4APdYNO/o/4YY8H54NQIJzhMbhBg==", + "requires": { + "config-chain": "^1.1.13", + "editorconfig": "^1.0.3", + "glob": "^8.1.0", + "nopt": "^6.0.0" + }, + "dependencies": { + "brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "requires": { + "balanced-match": "^1.0.0" + } + }, + "glob": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" + } + }, + "minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "requires": { + "brace-expansion": "^2.0.1" + } + }, + "nopt": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-6.0.0.tgz", + "integrity": "sha512-ZwLpbTgdhuZUnZzjd7nb1ZV+4DoiC6/sfiVKok72ym/4Tlf+DFdlHYmT2JPmcNNWV6Pi3SDf1kT+A4r9RTuT9g==", + "requires": { + "abbrev": "^1.0.0" + } + } } }, - "js-base64": { - "version": "2.6.4", - "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.6.4.tgz", - "integrity": "sha512-pZe//GGmwJndub7ZghVHz7vjb2LgC1m8B07Au3eYqeqv9emhESByMXxaEgkUkEqJe87oBbSniGYoQNIBklc7IQ==", + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", "dev": true }, - "js-beautify": { - "version": "1.13.5", - "resolved": "https://registry.npmjs.org/js-beautify/-/js-beautify-1.13.5.tgz", - "integrity": "sha512-MsXlH6Z/BiRYSkSRW3clNDqDjSpiSNOiG8xYVUBXt4k0LnGvDhlTGOlHX1VFtAdoLmtwjxMG5qiWKy/g+Ipv5w==", - "requires": { - "config-chain": "^1.1.12", - "editorconfig": "^0.15.3", - "glob": "^7.1.3", - "mkdirp": "^1.0.4", - "nopt": "^5.0.0" - }, - "dependencies": { - "mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==" - } - } - }, "js-yaml": { "version": "3.13.1", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", @@ -2741,91 +12787,159 @@ "jsbn": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", + "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==", + "dev": true, + "peer": true + }, + "json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", "dev": true }, - "json-schema": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", - "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", + "json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", "dev": true }, + "json-schema": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", + "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==", + "dev": true, + "peer": true + }, "json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", "dev": true }, + "json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true + }, "json-stringify-safe": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", - "dev": true + "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", + "dev": true, + "peer": true + }, + "json5": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "dev": true, + "requires": { + "minimist": "^1.2.0" + } }, "jsonfile": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz", - "integrity": "sha1-NzaitCi4e72gzIO1P6PWM6NcKug=", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", "requires": { - "graceful-fs": "^4.1.6" + "graceful-fs": "4.2.11" }, "dependencies": { "graceful-fs": { - "version": "4.2.8", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz", - "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==", - "optional": true + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" } } }, "jsprim": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", - "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz", + "integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==", "dev": true, + "peer": true, "requires": { "assert-plus": "1.0.0", "extsprintf": "1.3.0", - "json-schema": "0.2.3", + "json-schema": "0.4.0", "verror": "1.10.0" }, "dependencies": { - "extsprintf": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", - "dev": true + "verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==", + "dev": true, + "peer": true, + "requires": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } } } }, - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "requires": { - "is-buffer": "^1.1.5" - } - }, - "klaw": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/klaw/-/klaw-1.3.1.tgz", - "integrity": "sha1-QIhDO0azsbolnXh4XY6W9zugJDk=", + "jszip": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.10.1.tgz", + "integrity": "sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==", + "dev": true, "requires": { - "graceful-fs": "^4.1.9" + "lie": "~3.3.0", + "pako": "~1.0.2", + "readable-stream": "~2.3.6", + "setimmediate": "^1.0.5" }, "dependencies": { - "graceful-fs": { - "version": "4.2.8", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz", - "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==", - "optional": true + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true + }, + "readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true } } }, + "keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "requires": { + "json-buffer": "3.0.1" + } + }, + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true + }, "lcid": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", - "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", + "integrity": "sha512-YiGkH6EnGrDGqLMITnGjXtGmNtjoXw9SVUzcaos8RBi7Ps0VBylkq+vOcY9QE5poLasPCR849ucFUkl0UzUyOw==", "requires": { "invert-kv": "^1.0.0" } @@ -2833,7 +12947,7 @@ "ldap-filter": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/ldap-filter/-/ldap-filter-0.2.2.tgz", - "integrity": "sha1-8rhCvguG2jNSeYUFsx68rlkNd9A=", + "integrity": "sha512-HDnDRNY/z0E3qljSjDWtu7xXCUdiXzwadz7m1jIwl3XHhPMrqUyurOd32YWH5IZ3zZMP4PrG7gKdRIB2uZHKGA==", "requires": { "assert-plus": "0.1.5" }, @@ -2841,7 +12955,7 @@ "assert-plus": { "version": "0.1.5", "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.1.5.tgz", - "integrity": "sha1-7nQAlBMALYTOxyGcasgRgS5yMWA=" + "integrity": "sha512-brU24g7ryhRwGCI2y+1dGQmQXiZF7TtIj583S96y0jjdajIe6wn8BuXyELYhvD22dtIxDQVFk04YTJwwdwOYJw==" } } }, @@ -2860,7 +12974,7 @@ "ldapjs": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/ldapjs/-/ldapjs-1.0.2.tgz", - "integrity": "sha1-VE/3Ayt7g8aPBwEyjZKXqmlDQPk=", + "integrity": "sha512-Y8fRYFXOWWKBs9I2QRNXb0FncDcG0Gjc7YU6XI3kIV9hLMRaFKH5QHi2TZeB7FrpgXuabOgL0GdYALbssHxH5Q==", "requires": { "asn1": "0.2.3", "assert-plus": "^1.0.0", @@ -2869,524 +12983,55 @@ "dashdash": "^1.14.0", "dtrace-provider": "~0.8", "ldap-filter": "0.2.2", - "once": "^1.4.0", - "vasync": "^1.6.4", - "verror": "^1.8.1" - } - }, - "libbase64": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/libbase64/-/libbase64-0.1.0.tgz", - "integrity": "sha1-YjUag5VjrF/1vSbxL2Dpgwu3UeY=" - }, - "libmime": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/libmime/-/libmime-1.2.0.tgz", - "integrity": "sha1-jYS087Ils3BEECNu9JSQZDa6dCs=", - "requires": { - "iconv-lite": "^0.4.13", - "libbase64": "^0.1.0", - "libqp": "^1.1.0" - } - }, - "libqp": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/libqp/-/libqp-1.1.0.tgz", - "integrity": "sha1-9ebgatdLeU+1tbZpiL9yjvHe2+g=" - }, - "liftoff": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-2.5.0.tgz", - "integrity": "sha1-IAkpG7Mc6oYbvxCnwVooyvdcMew=", - "requires": { - "extend": "^3.0.0", - "findup-sync": "^2.0.0", - "fined": "^1.0.1", - "flagged-respawn": "^1.0.0", - "is-plain-object": "^2.0.4", - "object.map": "^1.0.0", - "rechoir": "^0.6.2", - "resolve": "^1.1.7" - }, - "dependencies": { - "arr-diff": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=" - }, - "array-unique": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=" - }, - "braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "requires": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - } - }, - "detect-file": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", - "integrity": "sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=" - }, - "expand-brackets": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", - "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", - "requires": { - "debug": "^2.3.3", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "posix-character-classes": "^0.1.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "requires": { - "is-extendable": "^0.1.0" - } - }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "requires": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - } - }, - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==" - } - } - }, - "expand-tilde": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", - "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", - "requires": { - "homedir-polyfill": "^1.0.1" - } - }, - "extglob": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", - "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", - "requires": { - "array-unique": "^0.3.2", - "define-property": "^1.0.0", - "expand-brackets": "^2.1.4", - "extend-shallow": "^2.0.1", - "fragment-cache": "^0.2.1", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", - "requires": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "findup-sync": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-2.0.0.tgz", - "integrity": "sha1-kyaxSIwi0aYIhlCoaQGy2akKLLw=", - "requires": { - "detect-file": "^1.0.0", - "is-glob": "^3.1.0", - "micromatch": "^3.0.4", - "resolve-dir": "^1.0.1" - } - }, - "global-modules": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", - "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", - "requires": { - "global-prefix": "^1.0.1", - "is-windows": "^1.0.1", - "resolve-dir": "^1.0.0" - } - }, - "global-prefix": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", - "integrity": "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=", - "requires": { - "expand-tilde": "^2.0.2", - "homedir-polyfill": "^1.0.1", - "ini": "^1.3.4", - "is-windows": "^1.0.1", - "which": "^1.2.14" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=" - }, - "is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "requires": { - "is-extglob": "^2.1.0" - } - }, - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-windows": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", - "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==" - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" - }, - "kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==" - }, - "micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" - } - }, - "resolve-dir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", - "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=", - "requires": { - "expand-tilde": "^2.0.0", - "global-modules": "^1.0.0" - } - } - } - }, - "load-json-file": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", - "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", - "requires": { - "graceful-fs": "^4.1.2", - "parse-json": "^2.2.0", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0", - "strip-bom": "^2.0.0" - }, - "dependencies": { - "graceful-fs": { - "version": "4.2.8", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz", - "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==" - }, - "strip-bom": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", - "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", - "requires": { - "is-utf8": "^0.2.0" - } - } - } - }, - "locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "requires": { - "p-locate": "^4.1.0" - } - }, - "lodash": { - "version": "4.17.20", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", - "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==" - }, - "lodash._basecopy": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz", - "integrity": "sha1-jaDmqHbPNEwK2KVIghEd08XHyjY=" - }, - "lodash._basetostring": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/lodash._basetostring/-/lodash._basetostring-3.0.1.tgz", - "integrity": "sha1-0YYdh3+CSlL2aYMtyvPuFVZqB9U=" - }, - "lodash._basevalues": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lodash._basevalues/-/lodash._basevalues-3.0.0.tgz", - "integrity": "sha1-W3dXYoAr3j0yl1A+JjAIIP32Ybc=" - }, - "lodash._getnative": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz", - "integrity": "sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U=" - }, - "lodash._isiterateecall": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz", - "integrity": "sha1-UgOte6Ql+uhCRg5pbbnPPmqsBXw=" - }, - "lodash._reescape": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lodash._reescape/-/lodash._reescape-3.0.0.tgz", - "integrity": "sha1-Kx1vXf4HyKNVdT5fJ/rH8c3hYWo=" - }, - "lodash._reevaluate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lodash._reevaluate/-/lodash._reevaluate-3.0.0.tgz", - "integrity": "sha1-WLx0xAZklTrgsSTYBpltrKQx4u0=" - }, - "lodash._reinterpolate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", - "integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=" - }, - "lodash._root": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/lodash._root/-/lodash._root-3.0.1.tgz", - "integrity": "sha1-+6HEUkwZ7ppfgTa0YJ8BfPTe1pI=" + "once": "^1.4.0", + "vasync": "^1.6.4", + "verror": "^1.8.1" + } }, - "lodash.escape": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-3.2.0.tgz", - "integrity": "sha1-mV7g3BjBtIzJLv+ucaEKq1tIdpg=", + "levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, "requires": { - "lodash._root": "^3.0.0" + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" } }, - "lodash.isarguments": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", - "integrity": "sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo=" - }, - "lodash.isarray": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz", - "integrity": "sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U=" - }, - "lodash.keys": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz", - "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=", + "lie": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz", + "integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==", + "dev": true, "requires": { - "lodash._getnative": "^3.0.0", - "lodash.isarguments": "^3.0.0", - "lodash.isarray": "^3.0.0" + "immediate": "~3.0.5" } }, - "lodash.memoize": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", - "integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=" - }, - "lodash.restparam": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/lodash.restparam/-/lodash.restparam-3.6.1.tgz", - "integrity": "sha1-k2pOMJ7zMKdkXtQUWYbIWuWyCAU=" + "lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true }, - "lodash.template": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-3.6.2.tgz", - "integrity": "sha1-+M3sxhaaJVvpCYrosMU9N4kx0U8=", + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", "requires": { - "lodash._basecopy": "^3.0.0", - "lodash._basetostring": "^3.0.0", - "lodash._basevalues": "^3.0.0", - "lodash._isiterateecall": "^3.0.0", - "lodash._reinterpolate": "^3.0.0", - "lodash.escape": "^3.0.0", - "lodash.keys": "^3.0.0", - "lodash.restparam": "^3.0.0", - "lodash.templatesettings": "^3.0.0" + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" } }, - "lodash.templatesettings": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-3.1.1.tgz", - "integrity": "sha1-+zB4RHU7Zrnxr6VOJix0UwfbqOU=", - "requires": { - "lodash._reinterpolate": "^3.0.0", - "lodash.escape": "^3.0.0" - } + "lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true }, "log-symbols": { "version": "2.2.0", @@ -3395,47 +13040,21 @@ "dev": true, "requires": { "chalk": "^2.0.1" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } } }, - "loud-rejection": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", - "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=", + "long": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", + "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==", + "optional": true + }, + "loupe": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.7.tgz", + "integrity": "sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==", "dev": true, "requires": { - "currently-unhandled": "^0.4.1", - "signal-exit": "^3.0.0" + "get-func-name": "^2.0.1" } }, "lru-cache": { @@ -3449,113 +13068,128 @@ "lru-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/lru-queue/-/lru-queue-0.1.0.tgz", - "integrity": "sha1-Jzi9nw089PhEkMVzbEhpmsYyzaM=", + "integrity": "sha512-BpdYkt9EvGl8OfWHDQPISVpcl5xZthb+XPsbELj5AQXxIC8IriDZIQYjBJPEm5rS420sjZ0TLEzRcq5KdBhYrQ==", "requires": { "es5-ext": "~0.10.2" } }, - "mailcomposer": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mailcomposer/-/mailcomposer-2.1.0.tgz", - "integrity": "sha1-plMYIomWFP7omckiJtgeK5y7GD0=", + "make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "optional": true, "requires": { - "buildmail": "^2.0.0", - "libmime": "^1.2.0" + "semver": "^6.0.0" + }, + "dependencies": { + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "optional": true + } } }, - "make-iterator": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/make-iterator/-/make-iterator-1.0.1.tgz", - "integrity": "sha512-pxiuXh0iVEq7VM7KMIhs5gxsfxCux2URptUQaXo4iZZJxBAzTPOLE2BumO5dbfVYq/hBJFBR/a1mFDmOx5AGmw==", + "make-fetch-happen": { + "version": "10.2.1", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-10.2.1.tgz", + "integrity": "sha512-NgOPbRiaQM10DYXvN3/hhGVI2M5MtITFryzBGxHM5p4wnFxsVCbxkrBrDsk+EZ5OB4jEOT7AjDxtdF+KVEFT7w==", + "dev": true, "requires": { - "kind-of": "^6.0.2" + "agentkeepalive": "^4.2.1", + "cacache": "^16.1.0", + "http-cache-semantics": "^4.1.0", + "http-proxy-agent": "^5.0.0", + "https-proxy-agent": "^5.0.0", + "is-lambda": "^1.0.1", + "lru-cache": "^7.7.1", + "minipass": "^3.1.6", + "minipass-collect": "^1.0.2", + "minipass-fetch": "^2.0.3", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "negotiator": "^0.6.3", + "promise-retry": "^2.0.1", + "socks-proxy-agent": "^7.0.0", + "ssri": "^9.0.0" }, "dependencies": { - "kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==" + "lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "dev": true } } }, - "map-cache": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", - "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=" - }, - "map-obj": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", - "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=", - "dev": true - }, - "map-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", - "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", + "map-age-cleaner": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz", + "integrity": "sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==", "requires": { - "object-visit": "^1.0.0" + "p-defer": "^1.0.0" } }, - "math-random": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/math-random/-/math-random-1.0.4.tgz", - "integrity": "sha512-rUxjysqif/BZQH2yhd5Aaq7vXMSx9NdEsQcyA07uEzIvxgI7zIr33gGsh+RU0/XjmQpCW7RsVof1vlkvQVCK5A==" + "map-obj": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.3.0.tgz", + "integrity": "sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==", + "dev": true }, "media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==" + }, + "mem": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/mem/-/mem-4.3.0.tgz", + "integrity": "sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w==", + "requires": { + "map-age-cleaner": "^0.1.1", + "mimic-fn": "^2.0.0", + "p-is-promise": "^2.0.0" + } }, "memoizee": { - "version": "0.3.10", - "resolved": "https://registry.npmjs.org/memoizee/-/memoizee-0.3.10.tgz", - "integrity": "sha1-TsoNiu057J0Bf0xcLy9kMvQuXI8=", - "requires": { - "d": "~0.1.1", - "es5-ext": "~0.10.11", - "es6-weak-map": "~0.1.4", - "event-emitter": "~0.3.4", - "lru-queue": "0.1", - "next-tick": "~0.2.2", - "timers-ext": "0.1" - }, - "dependencies": { - "next-tick": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-0.2.2.tgz", - "integrity": "sha1-ddpKkn7liH45BliABltzNkE7MQ0=" - } + "version": "0.4.15", + "resolved": "https://registry.npmjs.org/memoizee/-/memoizee-0.4.15.tgz", + "integrity": "sha512-UBWmJpLZd5STPm7PMUlOw/TSy972M+z8gcyQ5veOnSDRREz/0bmpyTfKt3/51DhEBqCZQn1udM/5flcSPYhkdQ==", + "requires": { + "d": "^1.0.1", + "es5-ext": "^0.10.53", + "es6-weak-map": "^2.0.3", + "event-emitter": "^0.3.5", + "is-promise": "^2.2.2", + "lru-queue": "^0.1.0", + "next-tick": "^1.1.0", + "timers-ext": "^0.1.7" } }, "meow": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz", - "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=", + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/meow/-/meow-9.0.0.tgz", + "integrity": "sha512-+obSblOQmRhcyBt62furQqRAQpNyWXo8BuQ5bN7dG8wmwQ+vwHKp/rCFD4CrTP8CsDQD1sjoZ94K417XEUk8IQ==", "dev": true, "requires": { - "camelcase-keys": "^2.0.0", - "decamelize": "^1.1.2", - "loud-rejection": "^1.0.0", - "map-obj": "^1.0.1", - "minimist": "^1.1.3", - "normalize-package-data": "^2.3.4", - "object-assign": "^4.0.1", - "read-pkg-up": "^1.0.1", - "redent": "^1.0.0", - "trim-newlines": "^1.0.0" + "@types/minimist": "^1.2.0", + "camelcase-keys": "^6.2.2", + "decamelize": "^1.2.0", + "decamelize-keys": "^1.1.0", + "hard-rejection": "^2.1.0", + "minimist-options": "4.1.0", + "normalize-package-data": "^3.0.0", + "read-pkg-up": "^7.0.1", + "redent": "^3.0.0", + "trim-newlines": "^3.0.0", + "type-fest": "^0.18.0", + "yargs-parser": "^20.2.3" }, "dependencies": { - "minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", - "dev": true - }, - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", "dev": true } } @@ -3563,32 +13197,12 @@ "merge-descriptors": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" + "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" }, "methods": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" - }, - "micromatch": { - "version": "2.3.11", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", - "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", - "requires": { - "arr-diff": "^2.0.0", - "array-unique": "^0.2.1", - "braces": "^1.8.2", - "expand-brackets": "^0.1.4", - "extglob": "^0.3.1", - "filename-regex": "^2.0.0", - "is-extglob": "^1.0.0", - "is-glob": "^2.0.1", - "kind-of": "^3.0.2", - "normalize-path": "^2.0.1", - "object.omit": "^2.0.0", - "parse-glob": "^3.0.4", - "regex-cache": "^0.4.2" - } + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==" }, "mime": { "version": "1.6.0", @@ -3596,80 +13210,147 @@ "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" }, "mime-db": { - "version": "1.45.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.45.0.tgz", - "integrity": "sha512-CkqLUxUk15hofLoLyljJSrukZi8mAtgd+yE5uO4tqRZsdsAJKv0O+rFMhVDRJgozy+yG6md5KwuXhD4ocIoP+w==" + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" }, "mime-types": { - "version": "2.1.28", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.28.tgz", - "integrity": "sha512-0TO2yJ5YHYr7M2zzT7gDU1tbwHxEUWBCLt0lscSNpcdAfFyJOVEpRYNS7EXVcTLNj/25QO8gulHC5JtTzSE2UQ==", + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", "requires": { - "mime-db": "1.45.0" + "mime-db": "1.52.0" } }, + "mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==" + }, + "min-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", + "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", + "dev": true + }, "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "requires": { "brace-expansion": "^1.1.7" } }, "minimist": { - "version": "0.0.10", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", - "integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=" + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==" + }, + "minimist-options": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-4.1.0.tgz", + "integrity": "sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==", + "dev": true, + "requires": { + "arrify": "^1.0.1", + "is-plain-obj": "^1.1.0", + "kind-of": "^6.0.3" + } }, "minipass": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz", - "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==", + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "devOptional": true, "requires": { - "safe-buffer": "^5.1.2", - "yallist": "^3.0.0" + "yallist": "^4.0.0" + }, + "dependencies": { + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "devOptional": true + } } }, - "minizlib": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.3.3.tgz", - "integrity": "sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==", + "minipass-collect": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz", + "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", + "devOptional": true, "requires": { - "minipass": "^2.9.0" + "minipass": "^3.0.0" } }, - "mixin-deep": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", - "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", + "minipass-fetch": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-2.1.2.tgz", + "integrity": "sha512-LT49Zi2/WMROHYoqGgdlQIZh8mLPZmOrN2NdJjMXxYe4nkN6FUyuPuOAOedNJDrx0IRGg9+4guZewtp8hE6TxA==", + "dev": true, + "requires": { + "encoding": "^0.1.13", + "minipass": "^3.1.6", + "minipass-sized": "^1.0.3", + "minizlib": "^2.1.2" + } + }, + "minipass-flush": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", + "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", + "devOptional": true, + "requires": { + "minipass": "^3.0.0" + } + }, + "minipass-pipeline": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", + "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", + "devOptional": true, + "requires": { + "minipass": "^3.0.0" + } + }, + "minipass-sized": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz", + "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==", + "devOptional": true, "requires": { - "for-in": "^1.0.2", - "is-extendable": "^1.0.1" + "minipass": "^3.0.0" + } + }, + "minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "devOptional": true, + "requires": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" }, "dependencies": { - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "requires": { - "is-plain-object": "^2.0.4" - } + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "devOptional": true } } }, + "mixme": { + "version": "0.5.9", + "resolved": "https://registry.npmjs.org/mixme/-/mixme-0.5.9.tgz", + "integrity": "sha512-VC5fg6ySUscaWUpI4gxCBTQMH2RdUpNrk+MsbpCYtIvf9SBJdiUey4qE7BXviJsJR4nDQxCZ+3yaYNW3guz/Pw==" + }, "mkdirp": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.4.tgz", + "integrity": "sha512-iG9AK/dJLtJ0XNgTuDbSyNS3zECqDlAhnQW4CsNxBG3LQJBbHmRX1egw39DmtOdCAqY+dKXV+sgPgilNWUKMVw==", "requires": { "minimist": "^1.2.5" - }, - "dependencies": { - "minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" - } } }, "mocha": { @@ -3703,38 +13384,6 @@ "yargs-unparser": "1.6.0" }, "dependencies": { - "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true - }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true - }, - "cliui": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", - "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", - "dev": true, - "requires": { - "string-width": "^3.1.0", - "strip-ansi": "^5.2.0", - "wrap-ansi": "^5.1.0" - } - }, "debug": { "version": "3.2.6", "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", @@ -3744,21 +13393,6 @@ "ms": "^2.1.1" } }, - "find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, - "requires": { - "locate-path": "^3.0.0" - } - }, - "get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true - }, "glob": { "version": "7.1.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", @@ -3773,35 +13407,13 @@ "path-is-absolute": "^1.0.0" } }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true - }, - "locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dev": true, - "requires": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - } - }, - "minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", - "dev": true - }, - "mkdirp": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.4.tgz", - "integrity": "sha512-iG9AK/dJLtJ0XNgTuDbSyNS3zECqDlAhnQW4CsNxBG3LQJBbHmRX1egw39DmtOdCAqY+dKXV+sgPgilNWUKMVw==", + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", "dev": true, "requires": { - "minimist": "^1.2.5" + "brace-expansion": "^1.1.7" } }, "ms": { @@ -3810,132 +13422,31 @@ "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", "dev": true }, - "object.assign": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", - "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", - "dev": true, - "requires": { - "define-properties": "^1.1.2", - "function-bind": "^1.1.1", - "has-symbols": "^1.0.0", - "object-keys": "^1.0.11" - } - }, - "p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "dev": true, - "requires": { - "p-limit": "^2.0.0" - } - }, - "path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", - "dev": true - }, - "require-main-filename": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", - "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", - "dev": true - }, - "string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dev": true, - "requires": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - } - }, - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "requires": { - "ansi-regex": "^4.1.0" - } - }, - "supports-color": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.0.0.tgz", - "integrity": "sha512-on9Kwidc1IUQo+bQdhi8+Tijpo0e1SS6RoGo2guUwn5vdaxw8RXOF9Vb2ws+ihWOmh4JnCJOvaziZWP1VABaLg==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - }, - "which-module": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", - "dev": true - }, - "wrap-ansi": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", - "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.0", - "string-width": "^3.0.0", - "strip-ansi": "^5.0.0" - } - }, - "y18n": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.1.tgz", - "integrity": "sha512-wNcy4NvjMYL8gogWWYAO7ZFWFfHcbdbE57tZO8e4cbpj8tfUcwrwqSl3ad8HxpYWCdXcJUCeKKZS62Av1affwQ==", - "dev": true - }, - "yargs": { - "version": "13.3.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", - "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", - "dev": true, - "requires": { - "cliui": "^5.0.0", - "find-up": "^3.0.0", - "get-caller-file": "^2.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^3.0.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^13.1.2" - } - }, - "yargs-parser": { - "version": "13.1.2", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", - "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", + "object.assign": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", + "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", "dev": true, "requires": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" + "define-properties": "^1.1.2", + "function-bind": "^1.1.1", + "has-symbols": "^1.0.0", + "object-keys": "^1.0.11" } } } }, "moment": { - "version": "2.29.1", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.1.tgz", - "integrity": "sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ==" + "version": "2.29.4", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz", + "integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==" }, "moment-timezone": { - "version": "0.5.33", - "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.33.tgz", - "integrity": "sha512-PTc2vcT8K9J5/9rDEPe5czSIKgLoGsH8UNpA4qZTVw0Vd/Uz19geE9abbIOQKaAQFcnQ3v5YEXrbSc5BpshH+w==", + "version": "0.5.43", + "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.43.tgz", + "integrity": "sha512-72j3aNyuIsDxdF1i7CEgV2FfxM1r6aaqJyLB2vwb33mXYyoyLly+F1zbWqhA3/bVIoJ4szlUoMbUnVdid32NUQ==", "requires": { - "moment": ">= 2.9.0" + "moment": "^2.29.4" } }, "morgan": { @@ -3958,30 +13469,45 @@ "ms": "2.0.0" } }, - "depd": { + "ms": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==", + "requires": { + "ee-first": "1.1.1" + } } } }, "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" }, - "multipipe": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/multipipe/-/multipipe-0.1.2.tgz", - "integrity": "sha1-Ko8t33Du1WTf8tV/HhoTfZ8FB4s=", + "multer": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/multer/-/multer-1.4.4.tgz", + "integrity": "sha512-2wY2+xD4udX612aMqMcB8Ws2Voq6NIUPEtD1be6m411T4uDH/VtL9i//xvcyFlTVfRdaBsk7hV5tgrGQqhuBiw==", "requires": { - "duplexer2": "0.0.2" + "append-field": "^1.0.0", + "busboy": "^0.2.11", + "concat-stream": "^1.5.2", + "mkdirp": "^0.5.4", + "object-assign": "^4.1.1", + "on-finished": "^2.3.0", + "type-is": "^1.6.4", + "xtend": "^4.0.0" } }, "mv": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/mv/-/mv-2.1.1.tgz", - "integrity": "sha1-rmzg1vbV4KT32JN5jQPB6pVZtqI=", + "integrity": "sha512-at/ZndSy3xEGJ8i0ygALh8ru9qy7gWW1cmkaqBN29JmMlIvM//MEO9y1sk/avxuwnPcfhkejkLsuPxH81BrkSg==", "optional": true, "requires": { "mkdirp": "~0.5.1", @@ -3989,96 +13515,154 @@ "rimraf": "~2.4.0" } }, - "nan": { - "version": "2.14.2", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.2.tgz", - "integrity": "sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ==" - }, - "nanomatch": { - "version": "1.2.13", - "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", - "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "fragment-cache": "^0.2.1", - "is-windows": "^1.0.2", - "kind-of": "^6.0.2", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "arr-diff": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=" - }, - "array-unique": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=" - }, - "is-windows": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", - "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==" - }, - "kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==" + "mysql2": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/mysql2/-/mysql2-1.7.0.tgz", + "integrity": "sha512-xTWWQPjP5rcrceZQ7CSTKR/4XIDeH/cRkNH/uzvVGQ7W5c7EJ0dXeJUusk7OKhIoHj7uFKUxDVSCfLIl+jluog==", + "optional": true, + "requires": { + "denque": "^1.4.1", + "generate-function": "^2.3.1", + "iconv-lite": "^0.5.0", + "long": "^4.0.0", + "lru-cache": "^5.1.1", + "named-placeholders": "^1.1.2", + "seq-queue": "^0.0.5", + "sqlstring": "^2.3.1" + }, + "dependencies": { + "iconv-lite": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.5.2.tgz", + "integrity": "sha512-kERHXvpSaB4aU3eANwidg79K8FlrN77m8G9V+0vOR3HYaRifrlwMEpT7ZBJqLSEIHnEgJTHcWK82wwLwwKwtag==", + "optional": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } } } }, - "natives": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/natives/-/natives-1.1.6.tgz", - "integrity": "sha512-6+TDFewD4yxY14ptjKaS63GVdtKiES1pTPyxn9Jb0rBqPMZ7VcCiooEhPNsr+mqHtMGxa/5c/HhcC4uPEUw/nA==" + "named-placeholders": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/named-placeholders/-/named-placeholders-1.1.3.tgz", + "integrity": "sha512-eLoBxg6wE/rZkJPhU/xRX1WTpkFEwDJEN96oxFrTsqBdbT5ec295Q+CoHrL9IT0DipqKhmGcaZmwOt8OON5x1w==", + "optional": true, + "requires": { + "lru-cache": "^7.14.1" + }, + "dependencies": { + "lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "optional": true + } + } + }, + "nan": { + "version": "2.18.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.18.0.tgz", + "integrity": "sha512-W7tfG7vMOGtD30sHoZSSc/JVYiyDPEyQVso/Zz+/uQd0B0L46gtC+pHha5FFMRpil6fm/AoEcRWyOVi4+E/f8w==", + "devOptional": true + }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true }, "nconf": { - "version": "0.8.5", - "resolved": "https://registry.npmjs.org/nconf/-/nconf-0.8.5.tgz", - "integrity": "sha1-8pQeFWGVL6kGu7MjKM+I1MY155Q=", + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/nconf/-/nconf-0.10.0.tgz", + "integrity": "sha512-fKiXMQrpP7CYWJQzKkPPx9hPgmq+YLDyxcG9N8RpiE9FoCkCbzD0NyW0YhE3xn3Aupe7nnDeIx4PFzYehpHT9Q==", "requires": { "async": "^1.4.0", "ini": "^1.3.0", "secure-keys": "^1.0.0", "yargs": "^3.19.0" - } - }, - "ncp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ncp/-/ncp-2.0.0.tgz", - "integrity": "sha1-GVoh1sRuNh0vsSgbo4uR6d9727M=", - "optional": true - }, - "needle": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/needle/-/needle-0.11.0.tgz", - "integrity": "sha1-AqcbAI6vfVWuifuf12hbe4jXvCk=", - "requires": { - "debug": "^2.1.2", - "iconv-lite": "^0.4.4" }, "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "camelcase": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", + "integrity": "sha512-DLIsRzJVBQu72meAKPkWQOLcujdXT32hwdfnkI1frSiSRMK1MofjKHf+MEx0SB6fjEFXL8fBDv1dKymBlOp4Qw==" + }, + "cliui": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", + "integrity": "sha512-0yayqDxWQbqk3ojkYqUKqaAQ6AfNKeKWRNA8kR0WXzAsdHpP4BIaOmMAG87JGuO6qcobyW4GjxHd9PmhEd+T9w==", "requires": { - "ms": "2.0.0" + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wrap-ansi": "^2.0.0" + } + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==", + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha512-0XsVpQLnVCXHJfyEs8tC0zpTVIr5PKKsQtkT29IwupnPTjtPmQ3xT/4yCREF9hYkV/3M3kzcUTSAZT6a6h81tw==", + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==", + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "wrap-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "integrity": "sha512-vAaEaDM946gbNpH5pLVNR+vX2ht6n0Bt3GXwVB1AuAqZosOvHNF3P7wDnh8KLkSqgUh0uh77le7Owgoz+Z9XBw==", + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1" + } + }, + "y18n": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.2.tgz", + "integrity": "sha512-uGZHXkHnhF0XeeAPgnKfPv1bgKAYyVvmNL1xlKsPYZPaIHxGti2hHqvOCQv71XMsLxu1QjergkqogUnms5D3YQ==" + }, + "yargs": { + "version": "3.32.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.32.0.tgz", + "integrity": "sha512-ONJZiimStfZzhKamYvR/xvmgW3uEkAUFSP91y2caTEPhzF6uP2JfPiVZcq66b/YR0C3uitxSV7+T1x8p5bkmMg==", + "requires": { + "camelcase": "^2.0.1", + "cliui": "^3.0.3", + "decamelize": "^1.1.1", + "os-locale": "^1.4.0", + "string-width": "^1.0.1", + "window-size": "^0.1.4", + "y18n": "^3.2.0" } } } }, + "ncp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ncp/-/ncp-2.0.0.tgz", + "integrity": "sha512-zIdGUrPRFTUELUvr3Gmc7KZ2Sw/h1PiVM0Af/oHB6zgnV1ikqSfRk+TOufi79aHYCW3NiOXmr1BP5nWbzojLaA==", + "optional": true + }, "negotiator": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", - "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==" + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==" }, "neo-async": { "version": "2.6.2", @@ -4086,9 +13670,20 @@ "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==" }, "next-tick": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", - "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=" + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz", + "integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==" + }, + "nice-try": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==" + }, + "node-addon-api": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-4.3.0.tgz", + "integrity": "sha512-73sE9+3UaLYYFmDsFZnqCInzPyh3MqIwZO9cw58yIqAZhONrrabrYyYe3TuIqtIiOuTXVhsGau8hcrhhwSsDIQ==", + "optional": true }, "node-environment-flags": { "version": "1.0.5", @@ -4098,182 +13693,311 @@ "requires": { "object.getownpropertydescriptors": "^2.0.3", "semver": "^5.7.0" - }, - "dependencies": { - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - } } }, - "node-gyp": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-3.8.0.tgz", - "integrity": "sha512-3g8lYefrRRzvGeSowdJKAKyks8oUpLEd/DyPV4eMhVlhJ0aNaZqIrNUIPuEWWTAoPqyFkfGrM67MC69baqn6vA==", - "dev": true, + "node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "optional": true, "requires": { - "fstream": "^1.0.0", - "glob": "^7.0.3", - "graceful-fs": "^4.1.2", - "mkdirp": "^0.5.0", - "nopt": "2 || 3", - "npmlog": "0 || 1 || 2 || 3 || 4", - "osenv": "0", - "request": "^2.87.0", - "rimraf": "2", - "semver": "~5.3.0", - "tar": "^2.0.0", - "which": "1" + "whatwg-url": "^5.0.0" + } + }, + "node-gyp": { + "version": "8.4.1", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-8.4.1.tgz", + "integrity": "sha512-olTJRgUtAb/hOXG0E93wZDs5YiJlgbXxTwQAFHyNlRsXQnYzUaF2aGgujZbw+hR8aF4ZG/rST57bWMWD16jr9w==", + "devOptional": true, + "requires": { + "env-paths": "^2.2.0", + "glob": "^7.1.4", + "graceful-fs": "4.2.11", + "make-fetch-happen": "^9.1.0", + "nopt": "^5.0.0", + "npmlog": "^6.0.0", + "rimraf": "^3.0.2", + "semver": "^7.3.5", + "tar": "^6.1.2", + "which": "^2.0.2" }, "dependencies": { + "@npmcli/fs": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-1.1.1.tgz", + "integrity": "sha512-8KG5RD0GVP4ydEzRn/I4BNDuxDtqVbOdm8675T49OIG/NGhaK0pjPX7ZcDlvKYbA+ulvVK3ztfcF4uBdOxuJbQ==", + "devOptional": true, + "requires": { + "@gar/promisify": "^1.0.1", + "semver": "^7.3.5" + } + }, + "@npmcli/move-file": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-1.1.2.tgz", + "integrity": "sha512-1SUf/Cg2GzGDyaf15aR9St9TWlb+XvbZXWpDx8YKs7MLzMH/BCeopv+y9vzrzgkfykCGuWOlSu3mZhj2+FQcrg==", + "devOptional": true, + "requires": { + "mkdirp": "^1.0.4", + "rimraf": "^3.0.2" + } + }, + "@tootallnate/once": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", + "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", + "devOptional": true + }, + "cacache": { + "version": "15.3.0", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-15.3.0.tgz", + "integrity": "sha512-VVdYzXEn+cnbXpFgWs5hTT7OScegHVmLhJIR8Ufqk3iFD6A6j5iSX1KuBTfNEv4tdJWE2PzA6IVFtcLC7fN9wQ==", + "devOptional": true, + "requires": { + "@npmcli/fs": "^1.0.0", + "@npmcli/move-file": "^1.0.1", + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "glob": "^7.1.4", + "infer-owner": "^1.0.4", + "lru-cache": "^6.0.0", + "minipass": "^3.1.1", + "minipass-collect": "^1.0.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.2", + "mkdirp": "^1.0.3", + "p-map": "^4.0.0", + "promise-inflight": "^1.0.1", + "rimraf": "^3.0.2", + "ssri": "^8.0.1", + "tar": "^6.0.2", + "unique-filename": "^1.1.1" + } + }, + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "devOptional": true, + "requires": { + "ms": "2.1.2" + } + }, "graceful-fs": { - "version": "4.2.8", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz", - "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==", - "dev": true + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" }, - "nopt": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", - "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", - "dev": true, + "http-proxy-agent": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", + "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", + "devOptional": true, + "requires": { + "@tootallnate/once": "1", + "agent-base": "6", + "debug": "4" + } + }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "devOptional": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "make-fetch-happen": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-9.1.0.tgz", + "integrity": "sha512-+zopwDy7DNknmwPQplem5lAZX/eCOzSvSNNcSKm5eVwTkOBzoktEfXsa9L23J/GIRhxRsaxzkPEhrJEpE2F4Gg==", + "devOptional": true, + "requires": { + "agentkeepalive": "^4.1.3", + "cacache": "^15.2.0", + "http-cache-semantics": "^4.1.0", + "http-proxy-agent": "^4.0.1", + "https-proxy-agent": "^5.0.0", + "is-lambda": "^1.0.1", + "lru-cache": "^6.0.0", + "minipass": "^3.1.3", + "minipass-collect": "^1.0.2", + "minipass-fetch": "^1.3.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "negotiator": "^0.6.2", + "promise-retry": "^2.0.1", + "socks-proxy-agent": "^6.0.0", + "ssri": "^8.0.0" + } + }, + "minipass-fetch": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-1.4.1.tgz", + "integrity": "sha512-CGH1eblLq26Y15+Azk7ey4xh0J/XfJfrCox5LDJiKqI2Q2iwOLOKrlmIaODiSQS8d18jalF6y2K2ePUm0CmShw==", + "devOptional": true, + "requires": { + "encoding": "^0.1.12", + "minipass": "^3.1.0", + "minipass-sized": "^1.0.3", + "minizlib": "^2.0.0" + } + }, + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "devOptional": true + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "devOptional": true + }, + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "devOptional": true, "requires": { - "abbrev": "1" + "glob": "^7.1.3" } }, "semver": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", - "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=", - "dev": true + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "devOptional": true, + "requires": { + "lru-cache": "^6.0.0" + } }, - "tar": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.2.tgz", - "integrity": "sha512-FCEhQ/4rE1zYv9rYXJw/msRqsnmlje5jHP6huWeBZ704jUTy02c5AZyWujpMR1ax6mVw9NyJMfuK2CMDWVIfgA==", - "dev": true, + "socks-proxy-agent": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-6.2.1.tgz", + "integrity": "sha512-a6KW9G+6B3nWZ1yB8G7pJwL3ggLy1uTzKAgCb7ttblwqdz9fMGJUuTy3uFzEP48FAs9FLILlmzDlE2JJhVQaXQ==", + "devOptional": true, "requires": { - "block-stream": "*", - "fstream": "^1.0.12", - "inherits": "2" + "agent-base": "^6.0.2", + "debug": "^4.3.3", + "socks": "^2.6.2" } - } - } - }, - "node-pre-gyp": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.11.0.tgz", - "integrity": "sha512-TwWAOZb0j7e9eGaf9esRx3ZcLaE5tQ2lvYy1pb5IAaG1a2e2Kv5Lms1Y4hpj+ciXJRofIxxlt5haeQ/2ANeE0Q==", - "requires": { - "detect-libc": "^1.0.2", - "mkdirp": "^0.5.1", - "needle": "^2.2.1", - "nopt": "^4.0.1", - "npm-packlist": "^1.1.6", - "npmlog": "^4.0.2", - "rc": "^1.2.7", - "rimraf": "^2.6.1", - "semver": "^5.3.0", - "tar": "^4" - }, - "dependencies": { - "debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + }, + "ssri": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.1.tgz", + "integrity": "sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ==", + "devOptional": true, "requires": { - "ms": "^2.1.1" + "minipass": "^3.1.1" } }, - "ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" - }, - "needle": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/needle/-/needle-2.6.0.tgz", - "integrity": "sha512-KKYdza4heMsEfSWD7VPUIz3zX2XDwOyX2d+geb4vrERZMT5RMU6ujjaD+I5Yr54uZxQ2w6XRTAhHBbSCyovZBg==", + "unique-filename": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", + "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", + "devOptional": true, "requires": { - "debug": "^3.2.6", - "iconv-lite": "^0.4.4", - "sax": "^1.2.4" + "unique-slug": "^2.0.0" } }, - "nopt": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.3.tgz", - "integrity": "sha512-CvaGwVMztSMJLOeXPrez7fyfObdZqNUK1cPAEzLHrTybIua9pMdmmPR5YwtfNftIOMv3DPUhFaxsZMNTQO20Kg==", + "unique-slug": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz", + "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==", + "devOptional": true, "requires": { - "abbrev": "1", - "osenv": "^0.1.4" + "imurmurhash": "^0.1.4" } }, - "rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "devOptional": true, "requires": { - "glob": "^7.1.3" + "isexe": "^2.0.0" } }, - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "devOptional": true } } }, - "node-releases": { - "version": "1.1.70", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.70.tgz", - "integrity": "sha512-Slf2s69+2/uAD79pVVQo8uSiC34+g8GWY8UH2Qtqv34ZfhYrxpYpfzs9Js9d6O0mbDmALuxaTlplnBTnSELcrw==" - }, "node-sass": { - "version": "4.14.1", - "resolved": "https://registry.npmjs.org/node-sass/-/node-sass-4.14.1.tgz", - "integrity": "sha512-sjCuOlvGyCJS40R8BscF5vhVlQjNN069NtQ1gSxyK1u9iqvn6tf7O1R4GNowVZfiZUCRt5MmMs1xd+4V/7Yr0g==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/node-sass/-/node-sass-8.0.0.tgz", + "integrity": "sha512-jPzqCF2/e6JXw6r3VxfIqYc8tKQdkj5Z/BDATYyG6FL6b/LuYBNFGFVhus0mthcWifHm/JzBpKAd+3eXsWeK/A==", "dev": true, "requires": { "async-foreach": "^0.1.3", - "chalk": "^1.1.1", - "cross-spawn": "^3.0.0", + "chalk": "^4.1.2", + "cross-spawn": "^7.0.3", "gaze": "^1.0.0", "get-stdin": "^4.0.1", "glob": "^7.0.3", - "in-publish": "^2.0.0", "lodash": "^4.17.15", - "meow": "^3.7.0", - "mkdirp": "^0.5.1", - "nan": "^2.13.2", - "node-gyp": "^3.8.0", - "npmlog": "^4.0.0", - "request": "^2.88.0", - "sass-graph": "2.2.5", + "make-fetch-happen": "^10.0.4", + "meow": "^9.0.0", + "nan": "^2.17.0", + "node-gyp": "^8.4.1", + "sass-graph": "^4.0.1", "stdout-stream": "^1.4.0", - "true-case-path": "^1.0.2" + "true-case-path": "^2.2.1" }, "dependencies": { - "gaze": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/gaze/-/gaze-1.1.3.tgz", - "integrity": "sha512-BRdNm8hbWzFzWHERTrejLqwHDfS4GibPoq5wjTPIoJHoBtKGPg3xAFfxmM+9ztbXelxcf2hwQcaz1PtmFeue8g==", + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, "requires": { - "globule": "^1.0.0" + "color-name": "~1.1.4" } }, - "globule": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/globule/-/globule-1.3.2.tgz", - "integrity": "sha512-7IDTQTIu2xzXkT+6mlluidnWo+BypnbSoEVVQCGfzqnl5Ik8d3e1d4wycb8Rj9tWW+Z39uPWsdlquqiqPCd/pA==", + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "requires": { - "glob": "~7.1.1", - "lodash": "~4.17.10", - "minimatch": "~3.0.2" + "has-flag": "^4.0.0" } } } @@ -4281,268 +14005,220 @@ "node-uuid": { "version": "1.4.8", "resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.8.tgz", - "integrity": "sha1-sEDrCSOWivq/jTL7HxfxFn/auQc=" + "integrity": "sha512-TkCET/3rr9mUuRp+CpO7qfgT++aAxfDRaalQhwPFzI9BY/2rCDn6OfpZOVggi1AXfTPpfkTrg5f5WQx5G1uLxA==" }, "nodemailer": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-1.11.0.tgz", - "integrity": "sha1-TmnLObAwFbHR7wx4qBVBK56Xb3k=", - "requires": { - "libmime": "^1.2.0", - "mailcomposer": "^2.1.0", - "needle": "^0.11.0", - "nodemailer-direct-transport": "^1.1.0", - "nodemailer-smtp-transport": "^1.1.0" - } + "version": "6.9.6", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.6.tgz", + "integrity": "sha512-s7pDtWwe5fLMkQUhw8TkWB/wnZ7SRdd9HRZslq/s24hlZvBP3j32N/ETLmnqTpmj4xoBZL9fOWyCIZ7r2HORHg==" + }, + "nodemailer-fetch": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/nodemailer-fetch/-/nodemailer-fetch-1.6.0.tgz", + "integrity": "sha512-P7S5CEVGAmDrrpn351aXOLYs1R/7fD5NamfMCHyi6WIkbjS2eeZUB/TkuvpOQr0bvRZicVqo59+8wbhR3yrJbQ==" }, - "nodemailer-direct-transport": { + "nodemailer-shared": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/nodemailer-direct-transport/-/nodemailer-direct-transport-1.1.0.tgz", - "integrity": "sha1-oveHCO5vFuoFc/yClJ0Tj/Fy9iQ=", + "resolved": "https://registry.npmjs.org/nodemailer-shared/-/nodemailer-shared-1.1.0.tgz", + "integrity": "sha512-68xW5LSyPWv8R0GLm6veAvm7E+XFXkVgvE3FW0FGxNMMZqMkPFeGDVALfR1DPdSfcoO36PnW7q5AAOgFImEZGg==", "requires": { - "smtp-connection": "^1.3.1" + "nodemailer-fetch": "1.6.0" } }, "nodemailer-smtp-transport": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/nodemailer-smtp-transport/-/nodemailer-smtp-transport-1.1.0.tgz", - "integrity": "sha1-5sN/MYhaswgOfe089SjErX5pE5g=", + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/nodemailer-smtp-transport/-/nodemailer-smtp-transport-2.7.4.tgz", + "integrity": "sha512-1e86YhJ633OZWk3OHWS5TpuoYXG/LtY2/RzNiB5+EkFifDdqHCNHBnExd5cobx0ZSHJLNGM8EKnDuHRFIjFi6Q==", "requires": { - "clone": "^1.0.2", - "nodemailer-wellknown": "^0.1.7", - "smtp-connection": "^1.3.7" + "nodemailer-shared": "1.1.0", + "nodemailer-wellknown": "0.1.10", + "smtp-connection": "2.12.0" } }, "nodemailer-wellknown": { "version": "0.1.10", "resolved": "https://registry.npmjs.org/nodemailer-wellknown/-/nodemailer-wellknown-0.1.10.tgz", - "integrity": "sha1-WG24EB2zDLRDjrVGc3pBqtDPE9U=" + "integrity": "sha512-/VV4mjAEjfm2fn0loUvrpjvugw5rgurNjPO4WU24CuVSoeumsyLOTgaEWG8WoGdPxh1biOAp5JxDoy1hlA2zsw==" }, "nopt": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", + "devOptional": true, "requires": { "abbrev": "1" } }, "normalize-package-data": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.3.tgz", + "integrity": "sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==", + "dev": true, "requires": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", + "hosted-git-info": "^4.0.1", + "is-core-module": "^2.5.0", + "semver": "^7.3.4", "validate-npm-package-license": "^3.0.1" }, "dependencies": { + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } } } }, - "normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", - "requires": { - "remove-trailing-separator": "^1.0.1" - } - }, - "npm-bundled": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.1.1.tgz", - "integrity": "sha512-gqkfgGePhTpAEgUsGEgcq1rqPXA+tv/aVBlgEzfXwA1yiUJF7xtEt3CtVwOjNYQOVknDk0F20w58Fnm3EtG0fA==", - "requires": { - "npm-normalize-package-bin": "^1.0.1" - } - }, - "npm-normalize-package-bin": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz", - "integrity": "sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA==" - }, - "npm-packlist": { - "version": "1.4.8", - "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-1.4.8.tgz", - "integrity": "sha512-5+AZgwru5IevF5ZdnFglB5wNlHG1AOOuw28WhUq8/8emhBmLv6jX5by4WJCh7lW0uSYZYS6DXqIsyZVIXRZU9A==", + "npm-run-path": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", + "integrity": "sha512-lJxZYlT4DW/bRUtFh1MQIWqmLwQfAxnqWG4HhEdjMlkrJYnJn0Jrr2u3mgxqaWsdiBc76TYkTG/mhrnYTuzfHw==", "requires": { - "ignore-walk": "^3.0.1", - "npm-bundled": "^1.0.1", - "npm-normalize-package-bin": "^1.0.1" + "path-key": "^2.0.0" + }, + "dependencies": { + "path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==" + } } }, "npmlog": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", - "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-6.0.2.tgz", + "integrity": "sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==", + "devOptional": true, "requires": { - "are-we-there-yet": "~1.1.2", - "console-control-strings": "~1.1.0", - "gauge": "~2.7.3", - "set-blocking": "~2.0.0" + "are-we-there-yet": "^3.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^4.0.3", + "set-blocking": "^2.0.0" } }, "number-is-nan": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" + "integrity": "sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ==" + }, + "oauth": { + "version": "0.9.15", + "resolved": "https://registry.npmjs.org/oauth/-/oauth-0.9.15.tgz", + "integrity": "sha512-a5ERWK1kh38ExDEfoO6qUHJb32rd7aYmPHuyCu3Fta/cnICvYmgd2uhuKXvPD+PXB+gCEYYEaQdIRAjCOwAKNA==" }, "oauth-sign": { "version": "0.9.0", "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", - "dev": true + "dev": true, + "peer": true }, "object-assign": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-3.0.0.tgz", - "integrity": "sha1-m+3VygiXlJvKR+f/QIBi1Un1h/I=" - }, - "object-copy": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", - "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", - "requires": { - "copy-descriptor": "^0.1.0", - "define-property": "^0.2.5", - "kind-of": "^3.0.3" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "requires": { - "is-descriptor": "^0.1.0" - } - } - } + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==" }, "object-inspect": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.9.0.tgz", - "integrity": "sha512-i3Bp9iTqwhaLZBxGkRfo5ZbE07BQRT7MGu8+nNgwW9ItGp1TzCTw2DLEoWwjClxBjOFI/hWljTAmYGCEwmtnOw==", - "dev": true + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.0.tgz", + "integrity": "sha512-HQ4J+ic8hKrgIt3mqk6cVOVrW2ozL4KdvHlqpBv9vDYWx9ysAgENAdvy4FoGF+KFdhR7nQTNm5J0ctAeOwn+3g==" + }, + "object-is": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.5.tgz", + "integrity": "sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==", + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" + } }, "object-keys": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==" }, - "object-visit": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", - "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", - "requires": { - "isobject": "^3.0.0" - }, - "dependencies": { - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" - } - } - }, "object.assign": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", - "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", + "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", "requires": { - "call-bind": "^1.0.0", - "define-properties": "^1.1.3", - "has-symbols": "^1.0.1", + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "has-symbols": "^1.0.3", "object-keys": "^1.1.1" } }, - "object.defaults": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/object.defaults/-/object.defaults-1.1.0.tgz", - "integrity": "sha1-On+GgzS0B96gbaFtiNXNKeQ1/s8=", + "object.entries": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.7.tgz", + "integrity": "sha512-jCBs/0plmPsOnrKAfFQXRG2NFjlhZgjjcBLSmTnEhU8U6vVTsVe8ANeQJCHTl3gSsI4J+0emOoCgoKlmQPMgmA==", "requires": { - "array-each": "^1.0.1", - "array-slice": "^1.0.0", - "for-own": "^1.0.0", - "isobject": "^3.0.0" - }, - "dependencies": { - "for-own": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", - "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", - "requires": { - "for-in": "^1.0.1" - } - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" - } + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" } }, - "object.getownpropertydescriptors": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.1.tgz", - "integrity": "sha512-6DtXgZ/lIZ9hqx4GtZETobXLR/ZLaa0aqV0kzbn80Rf8Z2e/XFnhA0I7p07N2wH8bBBltr2xQPi6sbKWAY2Eng==", + "object.fromentries": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.7.tgz", + "integrity": "sha512-UPbPHML6sL8PI/mOqPwsH4G6iyXcCGzLin8KvEPenOZN5lpCNBZZQ+V62vdjB1mQHrmqGQt5/OJzemUA+KJmEA==", "dev": true, "requires": { - "call-bind": "^1.0.0", - "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.1" + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" } }, - "object.map": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object.map/-/object.map-1.0.1.tgz", - "integrity": "sha1-z4Plncj8wK1fQlDh94s7gb2AHTc=", + "object.getownpropertydescriptors": { + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.7.tgz", + "integrity": "sha512-PrJz0C2xJ58FNn11XV2lr4Jt5Gzl94qpy9Lu0JlfEj14z88sqbSBJCBEzdlNUCzY2gburhbrwOZ5BHCmuNUy0g==", "requires": { - "for-own": "^1.0.0", - "make-iterator": "^1.0.0" - }, - "dependencies": { - "for-own": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", - "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", - "requires": { - "for-in": "^1.0.1" - } - } + "array.prototype.reduce": "^1.0.6", + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "safe-array-concat": "^1.0.0" } }, - "object.omit": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", - "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=", + "object.groupby": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.1.tgz", + "integrity": "sha512-HqaQtqLnp/8Bn4GL16cj+CUYbnpe1bh0TtEaWvybszDG4tgxCJuRpV8VGuvNaI1fAnI4lUJzDG55MXcOH4JZcQ==", + "dev": true, "requires": { - "for-own": "^0.1.4", - "is-extendable": "^0.1.1" + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "get-intrinsic": "^1.2.1" } }, - "object.pick": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", - "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", + "object.values": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.7.tgz", + "integrity": "sha512-aU6xnDFYT3x17e/f0IiiwlGPTy2jzMySGfUB4fq6z7CV8l85CWHDk5ErhyhpfDHhrOMwGFhSQkhMGHaIotA6Ng==", "requires": { - "isobject": "^3.0.1" - }, - "dependencies": { - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" - } + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" } }, "on-finished": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", - "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", "requires": { "ee-first": "1.1.1" } @@ -4555,7 +14231,7 @@ "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", "requires": { "wrappy": "1" } @@ -4563,42 +14239,42 @@ "optimist": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", - "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", + "integrity": "sha512-snN4O4TkigujZphWLN0E//nQmm7790RYaE53DdL7ZYwee2D8DDo9/EyYiKUfN3rneWUjhJnueija3G9I2i0h3g==", "requires": { "minimist": "~0.0.1", "wordwrap": "~0.0.2" + }, + "dependencies": { + "minimist": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", + "integrity": "sha512-iotkTvxc+TwOm5Ieim8VnSNvCDjCK9S8G3scJ50ZthspSxa7jx50jkhYduuAtAjvfDUwSgOwf8+If99AlOEhyw==" + }, + "wordwrap": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", + "integrity": "sha512-1tMA907+V4QmxV7dbRvb4/8MaRALK6q9Abid3ndMYnbyo8piisCmeONVqVSXqQA3KaP4SLt5b7ud6E2sqP8TFw==" + } } }, - "options": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/options/-/options-0.0.6.tgz", - "integrity": "sha1-7CLTEoBrtT5zF3Pnza788cZDEo8=", - "dev": true - }, - "orchestrator": { - "version": "0.3.8", - "resolved": "https://registry.npmjs.org/orchestrator/-/orchestrator-0.3.8.tgz", - "integrity": "sha1-FOfp4nZPcxX7rBhOUGx6pt+UrX4=", + "optionator": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", + "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", + "dev": true, "requires": { - "end-of-stream": "~0.1.5", - "sequencify": "~0.0.7", - "stream-consume": "~0.1.0" + "@aashutoshrathi/word-wrap": "^1.2.3", + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0" } }, - "ordered-read-streams": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-0.1.0.tgz", - "integrity": "sha1-/VZamvjrRHO6abbtijQ1LLVS8SY=" - }, - "os-homedir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", - "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=" - }, "os-locale": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", - "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", + "integrity": "sha512-PRT7ZORmwu2MEFt4/fv3Q+mEfN4zetKxufQrkShY2oGvUms9r8otu5HfdyIFHkYXjO7laNsoVGmM2MANfuTA8g==", "requires": { "lcid": "^1.0.0" } @@ -4606,16 +14282,28 @@ "os-tmpdir": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" + "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==", + "dev": true }, - "osenv": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", - "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", - "requires": { - "os-homedir": "^1.0.0", - "os-tmpdir": "^1.0.0" - } + "p-cancelable": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.0.0.tgz", + "integrity": "sha512-USgPoaC6tkTGlS831CxsVdmZmyb8tR1D+hStI84MyckLOzfJlYQUweomrwE3D8T7u5u5GVuW064LT501wHTYYA==" + }, + "p-defer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz", + "integrity": "sha512-wB3wfAxZpk2AzOfUMJNL+d36xothRSyj8EXOa4f6GMqYDN9BJaaSISbsk+wS9abmnebVw95C2Kb5t85UmpCxuw==" + }, + "p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==" + }, + "p-is-promise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-2.1.0.tgz", + "integrity": "sha512-Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg==" }, "p-limit": { "version": "2.3.0", @@ -4626,11 +14314,33 @@ } }, "p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", "requires": { - "p-limit": "^2.2.0" + "p-limit": "^2.0.0" + } + }, + "p-map": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", + "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "devOptional": true, + "requires": { + "aggregate-error": "^3.0.0" + } + }, + "p-queue": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/p-queue/-/p-queue-2.4.2.tgz", + "integrity": "sha512-n8/y+yDJwBjoLQe1GSJbbaYQLTI7QHNZI2+rpmCDbe++WLf9HC3gf6iqj5yfPAV71W4UF3ql5W1+UBPXoXTxng==" + }, + "p-retry": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-3.0.1.tgz", + "integrity": "sha512-XE6G4+YTTkT2a0UWb2kjZe8xNwf8bIbnqpc/IS/idOBVhyves0mK5OJgeocjx7q5pvX/6m23xuzVPYT1uGM73w==", + "requires": { + "retry": "^0.12.0" } }, "p-try": { @@ -4638,68 +14348,59 @@ "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==" }, - "parse-filepath": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.2.tgz", - "integrity": "sha1-pjISf1Oq89FYdvWHLz/6x2PWyJE=", - "requires": { - "is-absolute": "^1.0.0", - "map-cache": "^0.2.0", - "path-root": "^0.1.1" - } + "pako": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", + "dev": true }, - "parse-glob": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", - "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=", + "parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, "requires": { - "glob-base": "^0.3.0", - "is-dotfile": "^1.0.0", - "is-extglob": "^1.0.0", - "is-glob": "^2.0.0" + "callsites": "^3.0.0" } }, "parse-json": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", - "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, "requires": { - "error-ex": "^1.2.0" + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" } }, - "parse-node-version": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parse-node-version/-/parse-node-version-1.0.1.tgz", - "integrity": "sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==" - }, - "parse-passwd": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", - "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=" - }, "parseurl": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" }, - "pascalcase": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", - "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=" - }, "passport": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/passport/-/passport-0.3.2.tgz", - "integrity": "sha1-ndAJ+RXo/glbASSgG4+C2gdRAQI=", + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/passport/-/passport-0.4.1.tgz", + "integrity": "sha512-IxXgZZs8d7uFSt3eqNjM9NQ3g3uQCW5avD8mRNoXV99Yig50vjuaez6dQK2qC0kVWPRTujxY0dWgGfT09adjYg==", "requires": { "passport-strategy": "1.x.x", "pause": "0.0.1" } }, + "passport-google-oauth20": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/passport-google-oauth20/-/passport-google-oauth20-1.0.0.tgz", + "integrity": "sha512-asv9bVBYf0F6OBP/17dBbHq74KpKVrIQLKPpPmUoR2Wwxv9ZlmNv6QpIX2m0VPkAilLtQeWewWESsqZeh7ZSWQ==", + "requires": { + "passport-oauth2": "1.x.x" + } + }, "passport-http-bearer": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/passport-http-bearer/-/passport-http-bearer-1.0.1.tgz", - "integrity": "sha1-FHRp6jZp4qhMYWfvmdu3fh8AmKg=", + "integrity": "sha512-SELQM+dOTuMigr9yu8Wo4Fm3ciFfkMq5h/ZQ8ffi4ELgZrX1xh9PlglqZdcUZ1upzJD/whVyt+YWF62s3U6Ipw==", "requires": { "passport-strategy": "1.x.x" } @@ -4707,114 +14408,88 @@ "passport-local": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/passport-local/-/passport-local-1.0.0.tgz", - "integrity": "sha1-H+YyaMkudWBmJkN+O5BmYsFbpu4=", + "integrity": "sha512-9wCE6qKznvf9mQYYbgJ3sVOHmCWoUNMVFoZzNoznmISbhnNNPhN9xfY3sLmScHMetEJeoY7CXwfhCe7argfQow==", "requires": { "passport-strategy": "1.x.x" } }, + "passport-oauth2": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/passport-oauth2/-/passport-oauth2-1.7.0.tgz", + "integrity": "sha512-j2gf34szdTF2Onw3+76alNnaAExlUmHvkc7cL+cmaS5NzHzDP/BvFHJruueQ9XAeNOdpI+CH+PWid8RA7KCwAQ==", + "requires": { + "base64url": "3.x.x", + "oauth": "0.9.x", + "passport-strategy": "1.x.x", + "uid2": "0.0.x", + "utils-merge": "1.x.x" + } + }, "passport-strategy": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/passport-strategy/-/passport-strategy-1.0.0.tgz", - "integrity": "sha1-tVOaqPwiWj0a0XlHbd8ja0QPUuQ=" + "integrity": "sha512-CB97UUvDKJde2V0KDWWB3lyf6PC3FaZP7YxZ2G8OAtn9p4HI9j9JLP9qjOGZFvyl8uwNT8qM+hGnz/n16NI7oA==" }, "path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==" + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==" }, "path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" - }, - "path-parse": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", - "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==" + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==" }, - "path-root": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/path-root/-/path-root-0.1.1.tgz", - "integrity": "sha1-mkpoFMrBwM1zNgqV8yCDyOpHRbc=", - "requires": { - "path-root-regex": "^0.1.0" - } + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true }, - "path-root-regex": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/path-root-regex/-/path-root-regex-0.1.2.tgz", - "integrity": "sha1-v8zcjfWxLcUsi0PsONGNcsBLqW0=" + "path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" }, "path-to-regexp": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" + "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" }, - "path-type": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", - "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", - "requires": { - "graceful-fs": "^4.1.2", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" - }, - "dependencies": { - "graceful-fs": { - "version": "4.2.8", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz", - "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==" - } - } + "pathval": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", + "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", + "dev": true }, "pause": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz", - "integrity": "sha1-HUCLP9t2kjuVQ9lvtMnf1TXZy10=" + "integrity": "sha512-KG8UEiEVkR3wGEb4m5yZkVCzigAD+cVEJck2CzYZO37ZGJfctvVptVO192MwrtPhzONn6go8ylnOdMhKqi4nfg==" }, "performance-now": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", - "dev": true - }, - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" - }, - "pinkie": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", - "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=" - }, - "pinkie-promise": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", - "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", - "requires": { - "pinkie": "^2.0.0" - } - }, - "posix-character-classes": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", - "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=" + "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==", + "dev": true, + "peer": true }, "precond": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/precond/-/precond-0.2.3.tgz", - "integrity": "sha1-qpWRvKokkj8eD0hJ0kD0fvwQdaw=" + "integrity": "sha512-QCYG84SgGyGzqJ/vlMsxeXd/pgL/I94ixdNFyh1PusWmTCyVfPJjZ1K1jvHtsbfnXQs2TSkEP2fR7QiMZAnKFQ==" }, - "preserve": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", - "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=" + "prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true }, - "pretty-hrtime": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", - "integrity": "sha1-t+PqQkNaTJsnWdmeDyAesZWALuE=" + "prettier": { + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-1.17.0.tgz", + "integrity": "sha512-sXe5lSt2WQlCbydGETgfm1YBShgOX4HxQkFPvbxkcwgDvGDeqVau8h+12+lmSVlP3rHPz0oavfddSZg/q+Szjw==", + "dev": true }, "process-nextick-args": { "version": "2.0.1", @@ -4822,74 +14497,93 @@ "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" }, "promise": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/promise/-/promise-8.1.0.tgz", - "integrity": "sha512-W04AqnILOL/sPRXziNicCjSNRruLAuIHEOVBazepu0545DDNGYHz7ar9ZgZ1fMU8/MA4mVxp5rkBWRi6OXIy3Q==", + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/promise/-/promise-8.3.0.tgz", + "integrity": "sha512-rZPNPKTOYVNEEKFaq1HqTgOwZD+4/YHS5ukLzQCypkj+OkYx7iv0mA91lJlpPPZ8vMau3IIGj5Qlwrx+8iiSmg==", "requires": { "asap": "~2.0.6" } }, + "promise-inflight": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", + "integrity": "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==", + "devOptional": true + }, + "promise-retry": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", + "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", + "devOptional": true, + "requires": { + "err-code": "^2.0.2", + "retry": "^0.12.0" + } + }, "proto-list": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", - "integrity": "sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk=" + "integrity": "sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==" }, "proxy-addr": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz", - "integrity": "sha512-dh/frvCBVmSsDYzw6n926jv974gddhkFPfiN8hPOi30Wax25QZyZEGveluCgliBnqmuM+UJmBErbAUFIoDbjOw==", + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", "requires": { - "forwarded": "~0.1.2", + "forwarded": "0.2.0", "ipaddr.js": "1.9.1" } }, - "pseudomap": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", - "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=" - }, "psl": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", - "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", + "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==", "dev": true }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, "punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", + "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==" }, "qs": { - "version": "6.7.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", - "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==" + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", + "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "requires": { + "side-channel": "^1.0.4" + } + }, + "queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true + }, + "quick-lru": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-4.0.1.tgz", + "integrity": "sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==", + "dev": true + }, + "rambda": { + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/rambda/-/rambda-7.5.0.tgz", + "integrity": "sha512-y/M9weqWAH4iopRd7EHDEQQvpFPHj1AA3oHozE9tfITHUtTR7Z9PSlIRRG2l1GuW7sefC1cXFfIcF+cgnShdBA==", + "dev": true }, "random-bytes": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz", - "integrity": "sha1-T2ih3Arli9P7lYSMMDJNt11kNgs=" - }, - "randomatic": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-3.1.1.tgz", - "integrity": "sha512-TuDE5KxZ0J461RVjrJZCJc+J+zCkTb1MbH9AQUq68sMhOMcy9jLcb3BrZKgp9q9Ncltdg4QVqWrH02W2EFFVYw==", - "requires": { - "is-number": "^4.0.0", - "kind-of": "^6.0.0", - "math-random": "^1.0.1" - }, - "dependencies": { - "is-number": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", - "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==" - }, - "kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==" - } - } + "integrity": "sha512-iv7LhNVO047HzYR3InF6pUcUsPQiHTM1Qal51DcGSuZFBil1aBBWG5eHPNek7bvILMaYJ/8RU1e8w1AMdHmLQQ==" }, "range-parser": { "version": "1.2.1", @@ -4897,109 +14591,120 @@ "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" }, "raw-body": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", - "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", + "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", "requires": { - "bytes": "3.1.0", - "http-errors": "1.7.2", + "bytes": "3.1.2", + "http-errors": "2.0.0", "iconv-lite": "0.4.24", "unpipe": "1.0.0" } }, - "rc": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", - "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "read-pkg": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", + "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", + "dev": true, "requires": { - "deep-extend": "^0.6.0", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" + "@types/normalize-package-data": "^2.4.0", + "normalize-package-data": "^2.5.0", + "parse-json": "^5.0.0", + "type-fest": "^0.6.0" }, "dependencies": { - "minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" + "normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, + "requires": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "type-fest": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", + "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", + "dev": true } } }, - "read-pkg": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", - "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", - "requires": { - "load-json-file": "^1.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^1.0.0" - } - }, "read-pkg-up": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", - "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", + "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", + "dev": true, "requires": { - "find-up": "^1.0.0", - "read-pkg": "^1.0.0" + "find-up": "^4.1.0", + "read-pkg": "^5.2.0", + "type-fest": "^0.8.1" }, "dependencies": { "find-up": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", - "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, "requires": { - "path-exists": "^2.0.0", - "pinkie-promise": "^2.0.0" + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" } }, - "path-exists": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", - "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, "requires": { - "pinkie-promise": "^2.0.0" + "p-limit": "^2.2.0" } + }, + "type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "dev": true } } }, "readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", "requires": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", "util-deprecate": "^1.0.1" } }, - "rechoir": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", - "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", - "requires": { - "resolve": "^1.1.6" - } - }, - "redefine": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/redefine/-/redefine-0.2.1.tgz", - "integrity": "sha1-6J7npvJNGf/2JZBWkzLcYDgKiaM=" - }, "redent": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz", - "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", + "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", "dev": true, "requires": { - "indent-string": "^2.1.0", - "strip-indent": "^1.0.1" + "indent-string": "^4.0.0", + "strip-indent": "^3.0.0" } }, "redis": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/redis/-/redis-3.1.2.tgz", "integrity": "sha512-grn5KoZLr/qrRQVwoSkmzdbw6pwF+/rwODtrOr6vuBRiR/f3rjSTGupbF90Zpqm2oenix8Do6RV7pYEkGwlKkw==", + "optional": true, "requires": { "denque": "^1.5.0", "redis-commands": "^1.7.0", @@ -5010,72 +14715,40 @@ "redis-commands": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/redis-commands/-/redis-commands-1.7.0.tgz", - "integrity": "sha512-nJWqw3bTFy21hX/CPKHth6sfhZbdiHP6bTawSgQBlKOVRG7EZkfHbbHwQJnrE4vsQf0CMNE+3gJ4Fmm16vdVlQ==" + "integrity": "sha512-nJWqw3bTFy21hX/CPKHth6sfhZbdiHP6bTawSgQBlKOVRG7EZkfHbbHwQJnrE4vsQf0CMNE+3gJ4Fmm16vdVlQ==", + "optional": true }, "redis-errors": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/redis-errors/-/redis-errors-1.2.0.tgz", - "integrity": "sha1-62LSrbFeTq9GEMBK/hUpOEJQq60=" + "integrity": "sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w==", + "optional": true }, "redis-parser": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/redis-parser/-/redis-parser-3.0.0.tgz", - "integrity": "sha1-tm2CjNyv5rS4pCin3vTGvKwxyLQ=", + "integrity": "sha512-DJnGAeenTdpMEH6uAJRK/uiyEIH9WVsUmoLwzudwGJUwZPp80PDBWPHXSAGNPwNvIXAbe7MSUB1zQFugFml66A==", + "optional": true, "requires": { "redis-errors": "^1.0.0" } }, - "regex-cache": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz", - "integrity": "sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==", - "requires": { - "is-equal-shallow": "^0.1.3" - } - }, - "regex-not": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", - "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", - "requires": { - "extend-shallow": "^3.0.2", - "safe-regex": "^1.1.0" - } - }, - "remove-trailing-separator": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", - "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=" - }, - "repeat-element": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", - "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==" - }, - "repeat-string": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", - "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=" - }, - "repeating": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", - "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", - "dev": true, + "regexp.prototype.flags": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.1.tgz", + "integrity": "sha512-sy6TXMN+hnP/wMy+ISxg3krXx7BAtWVO4UouuCN/ziM9UEne0euamVNafDfvC83bRNr95y0V5iijeDQFUNpvrg==", "requires": { - "is-finite": "^1.0.0" + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "set-function-name": "^2.0.0" } }, - "replace-ext": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", - "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=" - }, "request": { "version": "2.88.2", "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", "dev": true, + "peer": true, "requires": { "aws-sign2": "~0.7.0", "aws4": "^1.8.0", @@ -5099,11 +14772,24 @@ "uuid": "^3.3.2" }, "dependencies": { + "form-data": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "dev": true, + "peer": true, + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + } + }, "qs": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", - "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", - "dev": true + "version": "6.5.3", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz", + "integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==", + "dev": true, + "peer": true } } }, @@ -5117,14 +14803,6 @@ "request-promise-core": "1.1.4", "stealthy-require": "^1.1.1", "tough-cookie": "^2.3.3" - }, - "dependencies": { - "bluebird": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", - "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", - "dev": true - } } }, "request-promise-core": { @@ -5139,69 +14817,59 @@ "require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=" + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==" }, "require-main-filename": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", - "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=" + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==" }, "resolve": { - "version": "1.19.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.19.0.tgz", - "integrity": "sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg==", + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", "requires": { - "is-core-module": "^2.1.0", - "path-parse": "^1.0.6" + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" } }, - "resolve-dir": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-0.1.1.tgz", - "integrity": "sha1-shklmlYC+sXFxJatiUpujMQwJh4=", - "requires": { - "expand-tilde": "^1.2.2", - "global-modules": "^0.2.3" - } + "resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true }, - "resolve-url": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", - "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=" + "resolve-pkg-maps": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", + "dev": true }, - "ret": { - "version": "0.1.15", - "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", - "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==" + "retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", + "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==" }, "retry-as-promised": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/retry-as-promised/-/retry-as-promised-2.3.2.tgz", - "integrity": "sha1-zZdO5P2bX+A8vzGHHuSCIcB3N7c=", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/retry-as-promised/-/retry-as-promised-3.2.0.tgz", + "integrity": "sha512-CybGs60B7oYU/qSQ6kuaFmRd9sTZ6oXSc0toqePvV74Ac6/IFZSI1ReFQmtCN+uvW1Mtqdwpvt/LGOiCBAY2Mg==", "requires": { - "bluebird": "^3.4.6", - "debug": "^2.6.9" - }, - "dependencies": { - "bluebird": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", - "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" - }, - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - } - } + "any-promise": "^1.3.0" } }, + "reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true + }, "rimraf": { "version": "2.4.5", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.4.5.tgz", - "integrity": "sha1-7nEM5dk6j9uFb7Xqj/Di11k0sto=", + "integrity": "sha512-J5xnxTyqaiw06JjMftq7L9ouA448dw/E7dKghkP9WpKNuwmARNNg+Gk8/u5ryb9N/Yo2+z3MCwuqFK/+qPOPfQ==", + "optional": true, "requires": { "glob": "^6.0.1" }, @@ -5209,7 +14877,8 @@ "glob": { "version": "6.0.4", "resolved": "https://registry.npmjs.org/glob/-/glob-6.0.4.tgz", - "integrity": "sha1-DwiGD2oVUSey+t1PnOJLGqtuTSI=", + "integrity": "sha512-MKZeRNyYZAVVVG1oZeLaWie1uweH40m9AZwIwxyPbTSX4hHrVYSzLg0Ro5Z5R7XKkIX+Cc6oD1rqeDJnwsB8/A==", + "optional": true, "requires": { "inflight": "^1.0.4", "inherits": "2", @@ -5220,10 +14889,30 @@ } } }, + "run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "requires": { + "queue-microtask": "^1.2.2" + } + }, + "safe-array-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.0.1.tgz", + "integrity": "sha512-6XbUAseYE2KtOuGueyeobCySj9L4+66Tn6KQMOPQJrAJEowYKW/YR/MGJZl7FdydUdaFu4LYyDZjxf4/Nmo23Q==", + "requires": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.1", + "has-symbols": "^1.0.3", + "isarray": "^2.0.5" + } + }, "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" }, "safe-json-stringify": { "version": "1.2.0", @@ -5231,12 +14920,14 @@ "integrity": "sha512-gH8eh2nZudPQO6TytOvbxnuhYBOvDBBLW52tz5q6X58lJcd/tkmqFR+5Z9adS8aJtURSXWThWy/xJtJwixErvg==", "optional": true }, - "safe-regex": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", - "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", + "safe-regex-test": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz", + "integrity": "sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==", "requires": { - "ret": "~0.1.10" + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.3", + "is-regex": "^1.1.4" } }, "safer-buffer": { @@ -5245,241 +14936,109 @@ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, "sass-graph": { - "version": "2.2.5", - "resolved": "https://registry.npmjs.org/sass-graph/-/sass-graph-2.2.5.tgz", - "integrity": "sha512-VFWDAHOe6mRuT4mZRd4eKE+d8Uedrk6Xnh7Sh9b4NGufQLQjOrvf/MQoOdx+0s92L89FeyUUNfU597j/3uNpag==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/sass-graph/-/sass-graph-4.0.1.tgz", + "integrity": "sha512-5YCfmGBmxoIRYHnKK2AKzrAkCoQ8ozO+iumT8K4tXJXRVCPf+7s1/9KxTSW3Rbvf+7Y7b4FR3mWyLnQr3PHocA==", "dev": true, "requires": { "glob": "^7.0.0", - "lodash": "^4.0.0", - "scss-tokenizer": "^0.2.3", - "yargs": "^13.3.2" + "lodash": "^4.17.11", + "scss-tokenizer": "^0.4.3", + "yargs": "^17.2.1" }, "dependencies": { - "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true - }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true - }, - "cliui": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", - "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", - "dev": true, - "requires": { - "string-width": "^3.1.0", - "strip-ansi": "^5.2.0", - "wrap-ansi": "^5.1.0" - } - }, - "find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, - "requires": { - "locate-path": "^3.0.0" - } - }, - "get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true - }, - "locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dev": true, - "requires": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - } - }, - "p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "dev": true, - "requires": { - "p-limit": "^2.0.0" - } - }, - "path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", - "dev": true - }, - "require-main-filename": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", - "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", - "dev": true - }, - "string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dev": true, - "requires": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - } - }, - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "requires": { - "ansi-regex": "^4.1.0" - } - }, - "which-module": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", - "dev": true - }, - "wrap-ansi": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", - "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.0", - "string-width": "^3.0.0", - "strip-ansi": "^5.0.0" - } - }, - "y18n": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.1.tgz", - "integrity": "sha512-wNcy4NvjMYL8gogWWYAO7ZFWFfHcbdbE57tZO8e4cbpj8tfUcwrwqSl3ad8HxpYWCdXcJUCeKKZS62Av1affwQ==", - "dev": true - }, "yargs": { - "version": "13.3.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", - "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", "dev": true, "requires": { - "cliui": "^5.0.0", - "find-up": "^3.0.0", - "get-caller-file": "^2.0.1", + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^3.0.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^13.1.2" - } - }, - "yargs-parser": { - "version": "13.1.2", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", - "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", - "dev": true, - "requires": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" } } } }, "sax": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", - "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.3.0.tgz", + "integrity": "sha512-0s+oAmw9zLl1V1cS9BtZN7JAd0cW5e0QH4W3LWEK6a4LaLEA2OTpGYWDY+6XasBLtz6wkm3u1xRw95mRuJ59WA==", + "dev": true }, "scss-tokenizer": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/scss-tokenizer/-/scss-tokenizer-0.2.3.tgz", - "integrity": "sha1-jrBtualyMzOCTT9VMGQRSYR85dE=", + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/scss-tokenizer/-/scss-tokenizer-0.4.3.tgz", + "integrity": "sha512-raKLgf1LI5QMQnG+RxHz6oK0sL3x3I4FN2UDLqgLOGO8hodECNnNh5BXn7fAyBxrA8zVzdQizQ6XjNJQ+uBwMw==", "dev": true, "requires": { - "js-base64": "^2.1.8", - "source-map": "^0.4.2" + "js-base64": "^2.4.9", + "source-map": "^0.7.3" }, "dependencies": { "source-map": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", - "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", - "dev": true, - "requires": { - "amdefine": ">=0.0.4" - } + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", + "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", + "dev": true } } }, "secure-keys": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/secure-keys/-/secure-keys-1.0.0.tgz", - "integrity": "sha1-8MgtmKOxOah3aogIBQuCRDEIf8o=" + "integrity": "sha512-nZi59hW3Sl5P3+wOO89eHBAAGwmCPd2aE1+dLZV5MO+ItQctIvAqihzaAXIQhvtH4KJPxM080HsnqltR2y8cWg==" }, "selenium-webdriver": { - "version": "2.53.3", - "resolved": "https://registry.npmjs.org/selenium-webdriver/-/selenium-webdriver-2.53.3.tgz", - "integrity": "sha1-0p/1qVff8aG0ncRXdW5OS/vc4IU=", + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/selenium-webdriver/-/selenium-webdriver-3.6.0.tgz", + "integrity": "sha512-WH7Aldse+2P5bbFBO4Gle/nuQOdVwpHMTL6raL3uuBj/vPG07k6uzt3aiahu352ONBr5xXh0hDlM3LhtXPOC4Q==", "dev": true, "requires": { - "adm-zip": "0.4.4", - "rimraf": "^2.2.8", - "tmp": "0.0.24", - "ws": "^1.0.1", - "xml2js": "0.4.4" + "jszip": "^3.1.3", + "rimraf": "^2.5.4", + "tmp": "0.0.30", + "xml2js": "^0.4.17" + }, + "dependencies": { + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + } } }, "semver": { - "version": "7.3.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", - "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==" + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==" }, "send": { - "version": "0.17.1", - "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", - "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", + "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", "requires": { "debug": "2.6.9", - "depd": "~1.1.2", - "destroy": "~1.0.4", + "depd": "2.0.0", + "destroy": "1.2.0", "encodeurl": "~1.0.2", "escape-html": "~1.0.3", "etag": "~1.8.1", "fresh": "0.5.2", - "http-errors": "~1.7.2", + "http-errors": "2.0.0", "mime": "1.6.0", - "ms": "2.1.1", - "on-finished": "~2.3.0", + "ms": "2.1.3", + "on-finished": "2.4.1", "range-parser": "~1.2.1", - "statuses": "~1.5.0" + "statuses": "2.0.1" }, "dependencies": { "debug": { @@ -5493,117 +15052,186 @@ "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" } } - }, - "ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" } } }, + "seq-queue": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/seq-queue/-/seq-queue-0.0.5.tgz", + "integrity": "sha512-hr3Wtp/GZIc/6DAGPDcV4/9WoZhjrkXsi5B/07QgX8tsdc6ilr7BFM6PM6rbdAX1kFSDYeZGLipIZZKyQP0O5Q==", + "optional": true + }, "sequelize": { - "version": "3.35.1", - "resolved": "https://registry.npmjs.org/sequelize/-/sequelize-3.35.1.tgz", - "integrity": "sha512-NhUmk4U+fS33/XW8CZsu1fSk8iSseJWF8fKuSa+kDIAK+lmA254QBbDAJiFvdH0P1ZSxyIS1zXl8FqVK5JDq9g==", - "requires": { - "bluebird": "^3.3.4", - "depd": "^1.1.0", - "dottie": "^1.0.0", - "generic-pool": "2.4.2", - "inflection": "^1.6.0", - "lodash": "^4.17.10", - "moment": "^2.13.0", - "moment-timezone": "^0.5.4", - "retry-as-promised": "^2.0.0", - "semver": "^5.0.1", - "shimmer": "1.1.0", - "terraformer-wkt-parser": "^1.1.0", + "version": "5.22.5", + "resolved": "https://registry.npmjs.org/sequelize/-/sequelize-5.22.5.tgz", + "integrity": "sha512-ySIHof18sJbeVG4zjEvsDL490cd9S14/IhkCrZR/g0C/FPlZq1AzEJVeSAo++9/sgJH2eERltAIGqYQNgVqX/A==", + "requires": { + "bluebird": "^3.5.0", + "cls-bluebird": "^2.1.0", + "debug": "^4.1.1", + "dottie": "^2.0.0", + "inflection": "1.12.0", + "lodash": "^4.17.15", + "moment": "^2.24.0", + "moment-timezone": "^0.5.21", + "retry-as-promised": "^3.2.0", + "semver": "^6.3.0", + "sequelize-pool": "^2.3.0", "toposort-class": "^1.0.1", - "uuid": "^3.0.0", - "validator": "^5.2.0", - "wkx": "0.2.0" + "uuid": "^8.3.2", + "validator": "^13.7.0", + "wkx": "^0.4.8" }, "dependencies": { - "bluebird": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", - "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" - }, "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" - }, - "validator": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/validator/-/validator-5.7.0.tgz", - "integrity": "sha1-eoelgUa2laxIYHEUHAxJ1n2gXlw=" + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" + }, + "uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==" } } }, "sequelize-cli": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/sequelize-cli/-/sequelize-cli-2.5.1.tgz", - "integrity": "sha1-zqTHT7vAacO60J/Q/f9/aookwe8=", - "requires": { - "bluebird": "^3.4.5", - "cli-color": "~0.3.2", - "findup-sync": "^0.4.0", - "fs-extra": "^1.0.0", - "gulp": "^3.9.1", - "gulp-help": "~1.6.1", - "js-beautify": "^1.5.4", - "lodash": "^4.12.0", - "moment": "^2.15.1", - "resolve": "^1.0.0", - "umzug": "^1.9.1", - "yargs": "^6.5.0" - }, - "dependencies": { - "bluebird": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", - "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/sequelize-cli/-/sequelize-cli-5.4.0.tgz", + "integrity": "sha512-4Gvl0yH0T3hhSdiiOci3+IKIfVG9x2os0hGWsbfa8QuyGgk9mZOqgTBnSCRtuxsdAyzUix9kfcTnfNolVNtprg==", + "requires": { + "bluebird": "^3.5.3", + "cli-color": "^1.4.0", + "fs-extra": "^7.0.1", + "js-beautify": "^1.8.8", + "lodash": "^4.17.5", + "resolve": "^1.5.0", + "umzug": "^2.1.0", + "yargs": "^12.0.5" + }, + "dependencies": { + "cliui": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz", + "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==", + "requires": { + "string-width": "^2.1.1", + "strip-ansi": "^4.0.0", + "wrap-ansi": "^2.0.0" + } }, - "camelcase": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", - "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=" + "get-caller-file": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", + "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==" + }, + "invert-kv": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz", + "integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==" + }, + "lcid": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz", + "integrity": "sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==", + "requires": { + "invert-kv": "^2.0.0" + } + }, + "os-locale": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.1.0.tgz", + "integrity": "sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==", + "requires": { + "execa": "^1.0.0", + "lcid": "^2.0.0", + "mem": "^4.0.0" + } + }, + "wrap-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "integrity": "sha512-vAaEaDM946gbNpH5pLVNR+vX2ht6n0Bt3GXwVB1AuAqZosOvHNF3P7wDnh8KLkSqgUh0uh77le7Owgoz+Z9XBw==", + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==" + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==", + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha512-0XsVpQLnVCXHJfyEs8tC0zpTVIr5PKKsQtkT29IwupnPTjtPmQ3xT/4yCREF9hYkV/3M3kzcUTSAZT6a6h81tw==", + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==", + "requires": { + "ansi-regex": "^2.0.0" + } + } + } }, "yargs": { - "version": "6.6.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-6.6.0.tgz", - "integrity": "sha1-eC7CHvQDNF+DCoCMo9UTr1YGUgg=", + "version": "12.0.5", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-12.0.5.tgz", + "integrity": "sha512-Lhz8TLaYnxq/2ObqHDql8dX8CJi97oHxrjUcYtzKbbykPtVW9WB+poxI+NM2UIzsMgNCZTIf0AQwsjK5yMAqZw==", "requires": { - "camelcase": "^3.0.0", - "cliui": "^3.2.0", - "decamelize": "^1.1.1", + "cliui": "^4.0.0", + "decamelize": "^1.2.0", + "find-up": "^3.0.0", "get-caller-file": "^1.0.1", - "os-locale": "^1.4.0", - "read-pkg-up": "^1.0.1", + "os-locale": "^3.0.0", "require-directory": "^2.1.1", "require-main-filename": "^1.0.1", "set-blocking": "^2.0.0", - "string-width": "^1.0.2", - "which-module": "^1.0.0", - "y18n": "^3.2.1", - "yargs-parser": "^4.2.0" + "string-width": "^2.0.0", + "which-module": "^2.0.0", + "y18n": "^3.2.1 || ^4.0.0", + "yargs-parser": "^11.1.1" + } + }, + "yargs-parser": { + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-11.1.1.tgz", + "integrity": "sha512-C6kB/WJDiaxONLJQnF8ccx9SEeoTTLek8RVbaOIsrAUS8VrBEXfmeSnCZxygc+XC2sNMBIwOOnfcxiynjHsVSQ==", + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" } } } }, - "sequencify": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/sequencify/-/sequencify-0.0.7.tgz", - "integrity": "sha1-kM/xnQLgcCf9dn9erT57ldHnOAw=" + "sequelize-pool": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/sequelize-pool/-/sequelize-pool-2.3.0.tgz", + "integrity": "sha512-Ibz08vnXvkZ8LJTiUOxRcj1Ckdn7qafNZ2t59jYHMX1VIebTAOYefWdRYFt6z6+hy52WGthAHAoLc9hvk3onqA==" }, "serve-favicon": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/serve-favicon/-/serve-favicon-2.5.0.tgz", - "integrity": "sha1-k10kDN/g9YBTB/3+ln2IlCosvPA=", + "integrity": "sha512-FMW2RvqNr03x+C0WxTyu6sOv21oOjkq5j8tjquWccwa6ScNyGFOGJVpuS1NmTVGBAHS07xnSKotgf2ehQmf9iA==", "requires": { "etag": "~1.8.1", "fresh": "0.5.2", @@ -5625,208 +15253,133 @@ } }, "serve-static": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", - "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", + "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", "requires": { "encodeurl": "~1.0.2", "escape-html": "~1.0.3", "parseurl": "~1.3.3", - "send": "0.17.1" + "send": "0.18.0" } }, "set-blocking": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==" }, - "set-value": { + "set-function-name": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", - "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.1.tgz", + "integrity": "sha512-tMNCiqYVkXIZgc2Hnoy2IvC/f8ezc5koaRFkCjrpWzGpCd3qbZXPzVy9MAZzK1ch/X0jvSkojys3oqJN0qCmdA==", "requires": { - "extend-shallow": "^2.0.1", - "is-extendable": "^0.1.1", - "is-plain-object": "^2.0.3", - "split-string": "^3.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "requires": { - "is-extendable": "^0.1.0" - } - } + "define-data-property": "^1.0.1", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.0" } }, + "setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==", + "dev": true + }, "setprototypeof": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", - "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==" }, "shimmer": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/shimmer/-/shimmer-1.1.0.tgz", - "integrity": "sha1-l9c3cTf/u6tCVSLkKf4KqJpIizU=" + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/shimmer/-/shimmer-1.2.1.tgz", + "integrity": "sha512-sQTKC1Re/rM6XyFM6fIAGHRPVGvyXfgzIDvzoq608vM+jeyVD0Tu1E6Np0Kc2zAIFWIj963V2800iF/9LPieQw==" }, - "sigmund": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz", - "integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=" + "side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "requires": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + } }, "signal-exit": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", - "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==" + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, + "smart-buffer": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", + "devOptional": true }, "smtp-connection": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/smtp-connection/-/smtp-connection-1.3.8.tgz", - "integrity": "sha1-VYMsIWDPswhuHc2H/RwZ+mG39TY=" + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/smtp-connection/-/smtp-connection-2.12.0.tgz", + "integrity": "sha512-UP5jK4s5SGcUcqPN4U9ingqKt9mXYSKa52YhqxPuMecAnUOsVJpOmtgGaOm1urUBJZlzDt1M9WhZZkgbhxQlvg==", + "requires": { + "httpntlm": "1.6.1", + "nodemailer-shared": "1.1.0" + } }, - "snapdragon": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", - "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", + "socks": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.1.tgz", + "integrity": "sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==", + "devOptional": true, "requires": { - "base": "^0.11.1", - "debug": "^2.2.0", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "map-cache": "^0.2.2", - "source-map": "^0.5.6", - "source-map-resolve": "^0.5.0", - "use": "^3.1.0" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - } - }, - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "requires": { - "is-extendable": "^0.1.0" - } - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" - } + "ip": "^2.0.0", + "smart-buffer": "^4.2.0" } }, - "snapdragon-node": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", - "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", + "socks-proxy-agent": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-7.0.0.tgz", + "integrity": "sha512-Fgl0YPZ902wEsAyiQ+idGd1A7rSFx/ayC1CQVMw5P+EQx2V0SgpGtf6OKFhVjPflPUl9YMmEOnmfjCdMUsygww==", + "dev": true, "requires": { - "define-property": "^1.0.0", - "isobject": "^3.0.0", - "snapdragon-util": "^3.0.1" + "agent-base": "^6.0.2", + "debug": "^4.3.3", + "socks": "^2.6.2" }, "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" + "ms": "2.1.2" } - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" - }, - "kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==" } } }, - "snapdragon-util": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", - "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", - "requires": { - "kind-of": "^3.2.0" - } - }, "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" }, - "source-map-resolve": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", - "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==", - "requires": { - "atob": "^2.1.2", - "decode-uri-component": "^0.2.0", - "resolve-url": "^0.2.1", - "source-map-url": "^0.4.0", - "urix": "^0.1.0" - } - }, - "source-map-url": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.1.tgz", - "integrity": "sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw==" - }, - "sparkles": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/sparkles/-/sparkles-1.0.1.tgz", - "integrity": "sha512-dSO0DDYUahUt/0/pD/Is3VIm5TGJjludZ0HVymmhYF6eNA53PVLhnUk0znSYbH8IYBuJdCE+1luR22jNLMaQdw==" - }, "spdx-correct": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", - "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", + "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", + "dev": true, "requires": { "spdx-expression-parse": "^3.0.0", "spdx-license-ids": "^3.0.0" @@ -5835,49 +15388,55 @@ "spdx-exceptions": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", - "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==" + "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", + "dev": true }, "spdx-expression-parse": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dev": true, "requires": { "spdx-exceptions": "^2.1.0", "spdx-license-ids": "^3.0.0" } }, "spdx-license-ids": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.7.tgz", - "integrity": "sha512-U+MTEOO0AiDzxwFvoa4JVnMV6mZlJKk2sBLt90s7G0Gd0Mlknc7kxEn3nuDPNZRta7O2uy8oLcZLVT+4sqNZHQ==" - }, - "split-string": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", - "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", - "requires": { - "extend-shallow": "^3.0.0" - } + "version": "3.0.16", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.16.tgz", + "integrity": "sha512-eWN+LnM3GR6gPu35WxNgbGl8rmY1AEmoMDvL/QD6zYmPWgywxWqJWNdLGT+ke8dKNWrcYgYjPpG5gbTfghP8rw==", + "dev": true }, "sprintf-js": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.2.tgz", - "integrity": "sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug==" + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "dev": true }, "sqlite3": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/sqlite3/-/sqlite3-4.2.0.tgz", - "integrity": "sha512-roEOz41hxui2Q7uYnWsjMOTry6TcNUNmp8audCx18gF10P2NknwdpF+E+HKvz/F2NvPKGGBF4NGc+ZPQ+AABwg==", + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/sqlite3/-/sqlite3-5.1.6.tgz", + "integrity": "sha512-olYkWoKFVNSSSQNvxVUfjiVbz3YtBwTJj+mfV5zpHmqW3sELx2Cf4QCdirMelhM5Zh+KDVaKgQHqCxrqiWHybw==", + "optional": true, "requires": { - "nan": "^2.12.1", - "node-pre-gyp": "^0.11.0" + "@mapbox/node-pre-gyp": "^1.0.0", + "node-addon-api": "^4.2.0", + "node-gyp": "8.x", + "tar": "^6.1.11" } }, + "sqlstring": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.3.tgz", + "integrity": "sha512-qC9iz2FlN7DQl3+wjwn3802RTyjCx7sDvfQEXchwa6CWOx07/WVfh91gBmQ9fahw8snwGEWU3xGzOt4tFyHLxg==", + "optional": true + }, "sshpk": { - "version": "1.16.1", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", - "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.17.0.tgz", + "integrity": "sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ==", "dev": true, + "peer": true, "requires": { "asn1": "~0.2.3", "assert-plus": "^1.0.0", @@ -5890,29 +15449,19 @@ "tweetnacl": "~0.14.0" } }, - "static-extend": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", - "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", + "ssri": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-9.0.1.tgz", + "integrity": "sha512-o57Wcn66jMQvfHG1FlYbWeZWW/dHZhJXjpIcTfXldXEk5nz5lStPo3mK0OJQfGR3RbZUlbISexbljkJzuEj/8Q==", + "dev": true, "requires": { - "define-property": "^0.2.5", - "object-copy": "^0.1.0" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "requires": { - "is-descriptor": "^0.1.0" - } - } + "minipass": "^3.1.1" } }, "statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==" }, "stdout-stream": { "version": "1.4.1", @@ -5923,10 +15472,16 @@ "readable-stream": "^2.0.1" }, "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true + }, "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", "dev": true, "requires": { "core-util-is": "~1.0.0", @@ -5938,61 +15493,71 @@ "util-deprecate": "~1.0.1" } }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true } } }, "stealthy-require": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/stealthy-require/-/stealthy-require-1.1.1.tgz", - "integrity": "sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks=", + "integrity": "sha512-ZnWpYnYugiOVEY5GkcuJK1io5V8QmNYChG62gSit9pQVGErXtrKuPC55ITaVSukmMta5qpMU7vqLt2Lnni4f/g==", "dev": true }, - "stream-consume": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/stream-consume/-/stream-consume-0.1.1.tgz", - "integrity": "sha512-tNa3hzgkjEP7XbCkbRXe1jpg+ievoa0O4SCFlMOYEscGSS4JJsckGL8swUyAa/ApGU3Ae4t6Honor4HhL+tRyg==" - }, "stream-transform": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/stream-transform/-/stream-transform-2.1.3.tgz", + "integrity": "sha512-9GHUiM5hMiCi6Y03jD2ARC1ettBXkQBoQAe7nJsPknnI0ow10aXjTnew8QtYQmLjzn974BnmWEAJgCY6ZP1DeQ==", + "requires": { + "mixme": "^0.5.1" + } + }, + "streamsearch": { "version": "0.1.2", - "resolved": "https://registry.npmjs.org/stream-transform/-/stream-transform-0.1.2.tgz", - "integrity": "sha1-fY5rTgOsR4F3j4x5UXUBv7B2Kp8=" + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-0.1.2.tgz", + "integrity": "sha512-jos8u++JKm0ARcSUTAZXOVC0mSox7Bhn6sBgty73P1f3JGf7yG2clTbBNHUdde/kdvP2FESam+vM6l8jBrNxHA==" }, "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, + "string.prototype.trim": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.8.tgz", + "integrity": "sha512-lfjY4HcixfQXOfaqCvcBuOIapyaroTXhbkfJN3gcB1OtyupngWK4sEET9Knd0cXd28kTUqu/kHoV4HKSJdnjiQ==", + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" } }, "string.prototype.trimend": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.3.tgz", - "integrity": "sha512-ayH0pB+uf0U28CtjlLvL7NaohvR1amUvVZk+y3DYb0Ey2PUV5zPkkKy9+U1ndVEIXO8hNg18eIv9Jntbii+dKw==", - "dev": true, + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.7.tgz", + "integrity": "sha512-Ni79DqeB72ZFq1uH/L6zJ+DKZTkOtPIHovb3YZHQViE+HDouuU4mBrLOLDn5Dde3RF8qw5qVETEjhu9locMLvA==", "requires": { - "call-bind": "^1.0.0", - "define-properties": "^1.1.3" + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" } }, "string.prototype.trimstart": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.3.tgz", - "integrity": "sha512-oBIBUy5lea5tt0ovtOFiEQaBkoBBkyJhZXzJYrSmDo5IUUqbOPvVezuRs/agBIdZ2p2Eo1FD6bD9USyBLfl3xg==", - "dev": true, + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.7.tgz", + "integrity": "sha512-NGhtDFu3jCEm7B4Fy0DpLewdJQOZcQ0rGbwQ/+stjnrp2i+rlKeCvos9hOIeCmqwratM47OBxY7uFZzjxHXmrg==", "requires": { - "call-bind": "^1.0.0", - "define-properties": "^1.1.3" + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" } }, "string_decoder": { @@ -6001,127 +15566,102 @@ "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", "requires": { "safe-buffer": "~5.2.0" - }, - "dependencies": { - "safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" - } } }, "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "requires": { - "ansi-regex": "^2.0.0" + "ansi-regex": "^5.0.1" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" + } } }, "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "dev": true + }, + "strip-eof": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-1.0.0.tgz", - "integrity": "sha1-hbiGLzhEtabV7IRnqTWYFzo295Q=", - "requires": { - "first-chunk-stream": "^1.0.0", - "is-utf8": "^0.2.0" - } + "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", + "integrity": "sha512-7FCwGGmx8mD5xQd3RPUvnSpUXHM3BWuzjtpD4TXsfcZ9EL4azvVVUscFYwD9nx8Kh+uCBC00XBtAykoMHwTh8Q==" }, "strip-indent": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz", - "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", + "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", "dev": true, "requires": { - "get-stdin": "^4.0.1" + "min-indent": "^1.0.0" } }, "strip-json-comments": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" + "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", + "dev": true }, "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" - }, - "tar": { - "version": "4.4.13", - "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.13.tgz", - "integrity": "sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA==", - "requires": { - "chownr": "^1.1.1", - "fs-minipass": "^1.2.5", - "minipass": "^2.8.6", - "minizlib": "^1.2.1", - "mkdirp": "^0.5.0", - "safe-buffer": "^5.1.2", - "yallist": "^3.0.3" - } - }, - "terraformer": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/terraformer/-/terraformer-1.0.12.tgz", - "integrity": "sha512-MokUp0+MFal4CmJDVL6VAO1bKegeXcBM2RnPVfqcFIp2IIv8EbPAjG0j/vEy/vuKB8NVMMSF2vfpVS/QLe4DBg==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.0.0.tgz", + "integrity": "sha512-on9Kwidc1IUQo+bQdhi8+Tijpo0e1SS6RoGo2guUwn5vdaxw8RXOF9Vb2ws+ihWOmh4JnCJOvaziZWP1VABaLg==", + "dev": true, "requires": { - "@types/geojson": "^7946.0.0 || ^1.0.0" + "has-flag": "^3.0.0" } }, - "terraformer-wkt-parser": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/terraformer-wkt-parser/-/terraformer-wkt-parser-1.2.1.tgz", - "integrity": "sha512-+CJyNLWb3lJ9RsZMTM66BY0MT3yIo4l4l22Jd9CrZuwzk54fsu4Sc7zejuS9fCITTuTQy3p06d4MZMVI7v5wSg==", - "requires": { - "@types/geojson": "^1.0.0", - "terraformer": "~1.0.5" - } + "supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==" }, - "through2": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", - "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", - "requires": { - "readable-stream": "~2.3.6", - "xtend": "~4.0.1" + "tar": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.0.tgz", + "integrity": "sha512-/Wo7DcT0u5HUV486xg675HtjNd3BXZ6xDbzsCUZPt5iw8bTQ63bP0Raut3mvro9u+CUyq7YQd8Cx55fsZXxqLQ==", + "devOptional": true, + "requires": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" }, "dependencies": { - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } + "minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "devOptional": true }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - } + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "devOptional": true + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "devOptional": true } } }, - "tildify": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/tildify/-/tildify-1.2.0.tgz", - "integrity": "sha1-3OwD9V3Km3qj5bBPIYF+tW5jWIo=", - "requires": { - "os-homedir": "^1.0.0" - } - }, - "time-stamp": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-1.1.0.tgz", - "integrity": "sha1-dkpaEa9QVhkhsTPztE5hhofg9cM=" + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true }, "timers-ext": { "version": "0.1.7", @@ -6133,66 +15673,31 @@ } }, "tmp": { - "version": "0.0.24", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.24.tgz", - "integrity": "sha1-1qXhmNFKmDXMby18PZ4wJCjIzxI=", - "dev": true - }, - "to-object-path": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", - "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", - "requires": { - "kind-of": "^3.0.2" - } - }, - "to-regex": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", - "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", - "requires": { - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "regex-not": "^1.0.2", - "safe-regex": "^1.1.0" - } - }, - "to-regex-range": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", - "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "version": "0.0.30", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.30.tgz", + "integrity": "sha512-HXdTB7lvMwcb55XFfrTM8CPr/IYREk4hVBFaQ4b/6nInrluSL86hfHm7vu0luYKCfyBZp2trCjpc8caC3vVM3w==", + "dev": true, "requires": { - "is-number": "^3.0.0", - "repeat-string": "^1.6.1" - }, - "dependencies": { - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "requires": { - "kind-of": "^3.0.2" - } - } + "os-tmpdir": "~1.0.1" } }, "toidentifier": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", - "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==" + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==" }, "topo": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/topo/-/topo-2.0.2.tgz", - "integrity": "sha1-zVYVdSU5BXwNwEkaYhw7xvvh0YI=", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/topo/-/topo-3.0.3.tgz", + "integrity": "sha512-IgpPtvD4kjrJ7CRA3ov2FhWQADwv+Tdqbsf1ZnPUSAtCJ9e1Z44MmoSGDXGk4IppoZA7jd/QRkNddlLJWlUZsQ==", "requires": { - "hoek": "4.x.x" + "hoek": "6.x.x" } }, "toposort-class": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/toposort-class/-/toposort-class-1.0.1.tgz", - "integrity": "sha1-f/0feMi+KMO6Rc1OGj9e4ZO9mYg=" + "integrity": "sha512-OsLcGGbYF3rMjPUf8oKktyvCiUxSbqMMS39m33MAjLTC1DVIH6x3WSt63/M77ihI09+Sdfk1AXvfhCEeUmC7mg==" }, "tough-cookie": { "version": "2.5.0", @@ -6204,26 +15709,42 @@ "punycode": "^2.1.1" } }, + "tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "optional": true + }, "trim-newlines": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", - "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-3.0.1.tgz", + "integrity": "sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==", "dev": true }, "true-case-path": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/true-case-path/-/true-case-path-1.0.3.tgz", - "integrity": "sha512-m6s2OdQe5wgpFMC+pAJ+q9djG82O2jcHPOI6RNg1yy9rCYR+WD6Nbpl32fDpfC56nirdRy+opFa/Vk7HYhqaew==", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/true-case-path/-/true-case-path-2.2.1.tgz", + "integrity": "sha512-0z3j8R7MCjy10kc/g+qg7Ln3alJTodw9aDuVWZa3uiWqfuBMKeAeP2ocWcxoyM3D73yz3Jt/Pu4qPr4wHSdB/Q==", + "dev": true + }, + "tsconfig-paths": { + "version": "3.14.2", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.2.tgz", + "integrity": "sha512-o/9iXgCYc5L/JxCHPe3Hvh8Q/2xm5Z+p18PESBU6Ff33695QnCHBEjcytY2q19ua7Mbl/DavtBOLq+oG0RCL+g==", "dev": true, "requires": { - "glob": "^7.1.2" + "@types/json5": "^0.0.29", + "json5": "^1.0.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" } }, "tunnel-agent": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", "dev": true, + "peer": true, "requires": { "safe-buffer": "^5.0.1" } @@ -6231,18 +15752,34 @@ "tweetnacl": { "version": "0.14.5", "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", - "dev": true + "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==", + "dev": true, + "peer": true }, "type": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==" }, + "type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "requires": { + "prelude-ls": "^1.2.1" + } + }, "type-detect": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-0.1.1.tgz", - "integrity": "sha1-C6XsKohWQORw6k6FBZcZANrFiCI=", + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true + }, + "type-fest": { + "version": "0.18.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.18.1.tgz", + "integrity": "sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==", "dev": true }, "type-is": { @@ -6254,10 +15791,58 @@ "mime-types": "~2.1.24" } }, + "typed-array-buffer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.0.tgz", + "integrity": "sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw==", + "requires": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.1", + "is-typed-array": "^1.1.10" + } + }, + "typed-array-byte-length": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.0.tgz", + "integrity": "sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA==", + "requires": { + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "has-proto": "^1.0.1", + "is-typed-array": "^1.1.10" + } + }, + "typed-array-byte-offset": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.0.tgz", + "integrity": "sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg==", + "requires": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "has-proto": "^1.0.1", + "is-typed-array": "^1.1.10" + } + }, + "typed-array-length": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz", + "integrity": "sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==", + "requires": { + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "is-typed-array": "^1.1.9" + } + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==" + }, "uglify-js": { - "version": "3.12.7", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.12.7.tgz", - "integrity": "sha512-SIZhkoh+U/wjW+BHGhVwE9nt8tWJspncloBcFapkpGRwNPqcH8pzX36BXe3TPBjzHWPMUZotpCigak/udWNr1Q==", + "version": "3.17.4", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.17.4.tgz", + "integrity": "sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==", "optional": true }, "uid-safe": { @@ -6268,111 +15853,67 @@ "random-bytes": "~1.0.0" } }, - "ultron": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.0.2.tgz", - "integrity": "sha1-rOEWq1V80Zc4ak6I9GhTeMiy5Po=", - "dev": true + "uid2": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/uid2/-/uid2-0.0.4.tgz", + "integrity": "sha512-IevTus0SbGwQzYh3+fRsAMTVVPOoIVufzacXcHPmdlle1jUpq7BRL+mw3dgeLanvGZdwwbWhRV6XrcFNdBmjWA==" }, "umzug": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/umzug/-/umzug-1.12.0.tgz", - "integrity": "sha1-p5yR8oYu7jEwxsNH8rkK1opm6Lg=", - "requires": { - "bluebird": "^3.4.1", - "lodash": "^4.17.0", - "moment": "^2.16.0", - "redefine": "^0.2.0", - "resolve": "^1.0.0" - }, - "dependencies": { - "bluebird": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", - "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" - } + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/umzug/-/umzug-2.3.0.tgz", + "integrity": "sha512-Z274K+e8goZK8QJxmbRPhl89HPO1K+ORFtm6rySPhFKfKc5GHhqdzD0SGhSWHkzoXasqJuItdhorSvY7/Cgflw==", + "requires": { + "bluebird": "^3.7.2" } }, - "unc-path-regex": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz", - "integrity": "sha1-5z3T17DXxe2G+6xrCufYxqadUPo=" + "unbox-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", + "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", + "requires": { + "call-bind": "^1.0.2", + "has-bigints": "^1.0.2", + "has-symbols": "^1.0.3", + "which-boxed-primitive": "^1.0.2" + } }, "underscore": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.12.0.tgz", - "integrity": "sha512-21rQzss/XPMjolTiIezSu3JAjgagXKROtNrYFEOWK109qY1Uv2tVjPTZ1ci2HgvQDA16gHYSthQIJfB+XId/rQ==" + "version": "1.13.6", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.6.tgz", + "integrity": "sha512-+A5Sja4HP1M08MaXya7p5LvjuM7K6q/2EaC0+iovj/wOcMsTzMvDFbasi/oSapiwOlt252IqsKqPjCl7huKS0A==" + }, + "undici-types": { + "version": "5.25.3", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.25.3.tgz", + "integrity": "sha512-Ga1jfYwRn7+cP9v8auvEXN1rX3sWqlayd4HP7OKk4mZWylEmu3KzXDUGrQUN6Ol7qo1gPvB2e5gX6udnyEPgdA==" }, - "underscore.string": { - "version": "3.3.5", - "resolved": "https://registry.npmjs.org/underscore.string/-/underscore.string-3.3.5.tgz", - "integrity": "sha512-g+dpmgn+XBneLmXXo+sGlW5xQEt4ErkS3mgeN2GFbremYeMBSJKr9Wf2KJplQVaiPY/f7FN6atosWYNm9ovrYg==", + "unique-filename": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-2.0.1.tgz", + "integrity": "sha512-ODWHtkkdx3IAR+veKxFV+VBkUMcN+FaqzUUd7IZzt+0zhDZFPFxhlqwPF3YQvMHx1TD0tdgYl+kuPnJ8E6ql7A==", + "dev": true, "requires": { - "sprintf-js": "^1.0.3", - "util-deprecate": "^1.0.2" + "unique-slug": "^3.0.0" } }, - "union-value": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", - "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", + "unique-slug": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-3.0.0.tgz", + "integrity": "sha512-8EyMynh679x/0gqE9fT9oilG+qEt+ibFyqjuVTsZn1+CMxH+XLlpvr2UZx4nVcCwTpx81nICr2JQFkM+HPLq4w==", + "dev": true, "requires": { - "arr-union": "^3.1.0", - "get-value": "^2.0.6", - "is-extendable": "^0.1.1", - "set-value": "^2.0.1" + "imurmurhash": "^0.1.4" } }, - "unique-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-1.0.0.tgz", - "integrity": "sha1-1ZpKdUJ0R9mqbJHnAmP40mpLEEs=" + "universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==" }, "unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" - }, - "unset-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", - "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", - "requires": { - "has-value": "^0.3.1", - "isobject": "^3.0.0" - }, - "dependencies": { - "has-value": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", - "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", - "requires": { - "get-value": "^2.0.3", - "has-values": "^0.1.4", - "isobject": "^2.0.0" - }, - "dependencies": { - "isobject": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", - "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", - "requires": { - "isarray": "1.0.0" - } - } - } - }, - "has-values": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", - "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=" - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" - } - } + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==" }, "uri-js": { "version": "4.4.1", @@ -6383,75 +15924,58 @@ "punycode": "^2.1.0" } }, - "urix": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", - "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=" - }, - "use": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", - "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==" - }, - "user-home": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/user-home/-/user-home-1.1.1.tgz", - "integrity": "sha1-K1viOjK2Onyd640PKNSFcko98ZA=" - }, "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" }, "utils-merge": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==" }, "uuid": { "version": "3.4.0", "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==" }, - "v8flags": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-2.1.1.tgz", - "integrity": "sha1-qrGh+jDUX4jdMhFIh1rALAtV5bQ=", - "requires": { - "user-home": "^1.1.1" - } - }, "validate-npm-package-license": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, "requires": { "spdx-correct": "^3.0.0", "spdx-expression-parse": "^3.0.0" } }, "validator": { - "version": "3.43.0", - "resolved": "https://registry.npmjs.org/validator/-/validator-3.43.0.tgz", - "integrity": "sha1-lkZLmS1BloM9l6GUv0Cxn/VLrgU=" + "version": "13.11.0", + "resolved": "https://registry.npmjs.org/validator/-/validator-13.11.0.tgz", + "integrity": "sha512-Ii+sehpSfZy+At5nPdnyMhx78fEoPDkR2XW/zimHEL3MyGJQOCQ7WeP20jPYRz7ZCpcKLB21NxuXHF3bxjStBQ==" }, "vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==" }, "vasync": { "version": "1.6.4", "resolved": "https://registry.npmjs.org/vasync/-/vasync-1.6.4.tgz", - "integrity": "sha1-3+k2Fq0OeugBszKp2Iv8XNyOHR8=", + "integrity": "sha512-3oQMomVgQgHzNe5iKuT8PGOhMCQcg1wfh00Nh/Kl39ERdTlw/uNS7kbrhEraDMDKWHdDdc0iBFahPEd/Ft2b+A==", "requires": { "verror": "1.6.0" }, "dependencies": { + "extsprintf": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.2.0.tgz", + "integrity": "sha512-T3PYC6HucmF4OfunfZb5d1nRvTSvWYhsr/Og33HANcCuCtGPUtWVyt/tTs8SU9sR0SGh5Z/xQCuX/D72ph2H+A==" + }, "verror": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/verror/-/verror-1.6.0.tgz", - "integrity": "sha1-fROyex+swuLakEBetepuW90lLqU=", + "integrity": "sha512-bIOaZx4+Bf6a7sIORfmYnyKLDLk/lhVym6rjYlq+vkitYKnhFmUpmPpDTCltWFrUTlGKs6sCeoDWfMA0oOOneA==", "requires": { "extsprintf": "1.2.0" } @@ -6459,84 +15983,29 @@ } }, "verror": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", - "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.1.tgz", + "integrity": "sha512-veufcmxri4e3XSrT0xwfUR7kguIkaxBeosDg00yDWhk49wdwkSUrvvsm7nc75e1PUyvIeZj6nS8VQRYz2/S4Xg==", "requires": { "assert-plus": "^1.0.0", "core-util-is": "1.0.2", "extsprintf": "^1.2.0" } }, - "vinyl": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.5.3.tgz", - "integrity": "sha1-sEVbOPxeDPMNQyUTLkYZcMIJHN4=", - "requires": { - "clone": "^1.0.0", - "clone-stats": "^0.0.1", - "replace-ext": "0.0.1" - } + "webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "optional": true }, - "vinyl-fs": { - "version": "0.3.14", - "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-0.3.14.tgz", - "integrity": "sha1-mmhRzhysHBzqX+hsCTHWIMLPqeY=", + "whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "optional": true, "requires": { - "defaults": "^1.0.0", - "glob-stream": "^3.1.5", - "glob-watcher": "^0.0.6", - "graceful-fs": "^3.0.0", - "mkdirp": "^0.5.0", - "strip-bom": "^1.0.0", - "through2": "^0.6.1", - "vinyl": "^0.4.0" - }, - "dependencies": { - "clone": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz", - "integrity": "sha1-xhJqkK1Pctv1rNskPMN3JP6T/B8=" - }, - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" - }, - "readable-stream": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" - }, - "through2": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", - "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", - "requires": { - "readable-stream": ">=1.0.33-1 <1.1.0-0", - "xtend": ">=4.0.0 <4.1.0-0" - } - }, - "vinyl": { - "version": "0.4.6", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz", - "integrity": "sha1-LzVsh6VQolVGHza76ypbqL94SEc=", - "requires": { - "clone": "^0.2.0", - "clone-stats": "^0.0.1" - } - } + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" } }, "which": { @@ -6547,80 +16016,140 @@ "isexe": "^2.0.0" } }, + "which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "requires": { + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" + } + }, "which-module": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", - "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=" + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.1.tgz", + "integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==" + }, + "which-typed-array": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.11.tgz", + "integrity": "sha512-qe9UWWpkeG5yzZ0tNYxDmd7vo58HDBc39mZ0xWWpolAGADdFOzkfamWLDxkOWcvHQKVmdTyQdLD4NOfjLWTKew==", + "requires": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.0" + } }, "wide-align": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", + "devOptional": true, "requires": { "string-width": "^1.0.2 || 2" + }, + "dependencies": { + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "devOptional": true, + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + } + } } }, "window-size": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.4.tgz", - "integrity": "sha1-+OGqHuWlPsW/FR/6CXQqatdpeHY=" + "integrity": "sha512-2thx4pB0cV3h+Bw7QmMXcEbdmOzv9t0HFplJH/Lz6yu60hXYy5RT8rUu+wlIreVxWsGN20mo+MHeCSfUpQBwPw==" }, "wkx": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/wkx/-/wkx-0.2.0.tgz", - "integrity": "sha1-dsJPFqzQzY+TzTSqMx4PeWElboQ=" + "version": "0.4.8", + "resolved": "https://registry.npmjs.org/wkx/-/wkx-0.4.8.tgz", + "integrity": "sha512-ikPXMM9IR/gy/LwiOSqWlSL3X/J5uk9EO2hHNRXS41eTLXaUFEVw9fn/593jW/tE5tedNg8YjT5HkCa4FqQZyQ==", + "requires": { + "@types/node": "*" + } }, "wordwrap": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", - "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=" + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==" }, "wrap-ansi": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", - "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", + "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", + "dev": true, "requires": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1" + "ansi-styles": "^3.2.0", + "string-width": "^3.0.0", + "strip-ansi": "^5.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", + "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", + "dev": true + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + } } }, "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" }, "ws": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/ws/-/ws-1.1.5.tgz", - "integrity": "sha512-o3KqipXNUdS7wpQzBHSe180lBGO60SoK0yVo3CYJgb2MkobuWuBX6dhkYP5ORCLd55y+SaflMOV5fqAB53ux4w==", - "dev": true, + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-5.2.3.tgz", + "integrity": "sha512-jZArVERrMsKUatIdnLzqvcfydI85dvd/Fp1u/VOpfdDWQ4c9qWXe+VIeAbQ5FrDwciAkr+lzofXLz3Kuf26AOA==", "requires": { - "options": ">=0.0.5", - "ultron": "1.0.x" + "async-limiter": "~1.0.0" } }, "xml2js": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.4.tgz", - "integrity": "sha1-MREBAAMAiuGSQOuhdJe1fHKcVV0=", + "version": "0.4.23", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.23.tgz", + "integrity": "sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug==", "dev": true, "requires": { - "sax": "0.6.x", - "xmlbuilder": ">=1.0.0" - }, - "dependencies": { - "sax": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/sax/-/sax-0.6.1.tgz", - "integrity": "sha1-VjsZx8HeiS4Jv8Ty/DDjwn8JUrk=", - "dev": true - } + "sax": ">=0.6.0", + "xmlbuilder": "~11.0.0" } }, "xmlbuilder": { - "version": "15.1.1", - "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-15.1.1.tgz", - "integrity": "sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg==", + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", + "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", "dev": true }, "xtend": { @@ -6629,9 +16158,9 @@ "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" }, "y18n": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.2.tgz", - "integrity": "sha512-uGZHXkHnhF0XeeAPgnKfPv1bgKAYyVvmNL1xlKsPYZPaIHxGti2hHqvOCQv71XMsLxu1QjergkqogUnms5D3YQ==" + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==" }, "yallist": { "version": "3.1.1", @@ -6639,127 +16168,39 @@ "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" }, "yargs": { - "version": "3.32.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.32.0.tgz", - "integrity": "sha1-AwiOnr+edWtpdRYR0qXvWRSCyZU=", - "requires": { - "camelcase": "^2.0.1", - "cliui": "^3.0.3", - "decamelize": "^1.1.1", - "os-locale": "^1.4.0", - "string-width": "^1.0.1", - "window-size": "^0.1.4", - "y18n": "^3.2.0" - } - }, - "yargs-parser": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-4.2.1.tgz", - "integrity": "sha1-KczqwNxPA8bIe0qfIX3RjJ90hxw=", - "requires": { - "camelcase": "^3.0.0" - }, - "dependencies": { - "camelcase": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", - "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=" - } - } - }, - "yargs-unparser": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-1.6.0.tgz", - "integrity": "sha512-W9tKgmSn0DpSatfri0nx52Joq5hVXgeLiqR/5G0sZNDoLZFOr/xjBUDcShCOGNsBnEMNo1KAMBkTej1Hm62HTw==", + "version": "13.3.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", + "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", "dev": true, "requires": { - "flat": "^4.1.0", - "lodash": "^4.17.15", - "yargs": "^13.3.0" + "cliui": "^5.0.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^13.1.2" }, "dependencies": { "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true - }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", + "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", "dev": true }, - "cliui": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", - "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", - "dev": true, - "requires": { - "string-width": "^3.1.0", - "strip-ansi": "^5.2.0", - "wrap-ansi": "^5.1.0" - } - }, - "find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, - "requires": { - "locate-path": "^3.0.0" - } - }, - "get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", "dev": true }, "is-fullwidth-code-point": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true - }, - "locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dev": true, - "requires": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - } - }, - "p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "dev": true, - "requires": { - "p-limit": "^2.0.0" - } - }, - "path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", - "dev": true - }, - "require-main-filename": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", - "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", + "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==", "dev": true }, "string-width": { @@ -6781,59 +16222,35 @@ "requires": { "ansi-regex": "^4.1.0" } - }, - "which-module": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", - "dev": true - }, - "wrap-ansi": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", - "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.0", - "string-width": "^3.0.0", - "strip-ansi": "^5.0.0" - } - }, - "y18n": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.1.tgz", - "integrity": "sha512-wNcy4NvjMYL8gogWWYAO7ZFWFfHcbdbE57tZO8e4cbpj8tfUcwrwqSl3ad8HxpYWCdXcJUCeKKZS62Av1affwQ==", - "dev": true - }, - "yargs": { - "version": "13.3.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", - "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", - "dev": true, - "requires": { - "cliui": "^5.0.0", - "find-up": "^3.0.0", - "get-caller-file": "^2.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^3.0.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^13.1.2" - } - }, - "yargs-parser": { - "version": "13.1.2", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", - "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", - "dev": true, - "requires": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - } } } + }, + "yargs-parser": { + "version": "13.1.2", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", + "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", + "dev": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + }, + "yargs-unparser": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-1.6.0.tgz", + "integrity": "sha512-W9tKgmSn0DpSatfri0nx52Joq5hVXgeLiqR/5G0sZNDoLZFOr/xjBUDcShCOGNsBnEMNo1KAMBkTej1Hm62HTw==", + "dev": true, + "requires": { + "flat": "^4.1.0", + "lodash": "^4.17.15", + "yargs": "^13.3.0" + } + }, + "yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true } } -} +} \ No newline at end of file diff --git a/package.json b/package.json index 9f60e3966..0319a5b99 100644 --- a/package.json +++ b/package.json @@ -4,54 +4,72 @@ "private": false, "description": "Simple yet powerful absence management software for small and medium size business", "engines": { - "node": ">=13.0.0" + "node": ">=16.0.0" + }, + "optionalDependencies": { + "mysql2": "^1.6.4", + "redis": "^3.1.2", + "sqlite3": "^5.1.6" }, "dependencies": { - "bluebird": "^2.10.2", - "body-parser": "^1.8.4", + "@handlebars/allow-prototype-access": "^1.0.5", + "@slack/client": "^4.1.0", + "bluebird": "^3.5.4", + "body-parser": "^1.19.0", "connect-redis": "^6.0.0", - "connect-session-sequelize": "3.0.0", - "cookie-parser": "^1.3.5", - "csv": "~0.4.6", - "debug": "4.1.0", - "express": "^4.13.4", - "express-handlebars": "^3.0.0", - "express-session": "^1.13.0", - "formidable": "~1.0.17", - "handlebars": "4.5.0", - "html-to-text": "^3.2.0", - "ical-generator": "^0.2.7", - "joi": "~12.0.0", - "ldapauth-fork": "^4.0.2", - "moment": "^2.11.2", - "moment-timezone": "^0.5.14", - "morgan": "^1.3.2", - "nconf": "^0.8.4", - "node-uuid": "^1.4.7", - "nodemailer": "^1.11.0", - "nodemailer-smtp-transport": "^1.1.0", + "connect-session-sequelize": "6.0.0", + "cookie-parser": "^1.4.4", + "csv": "~5.1.1", + "debug": "~4.1.1", + "express": "^4.16.4", + "express-handlebars": "^3.0.2", + "express-session": "^1.16.1", + "formidable": "~1.2.1", + "html-to-text": "^5.1.1", + "ical-generator": "^1.7.1", + "joi": "~14.3.1", + "ldapauth-fork": "^4.2.0", + "moment": "^2.24.0", + "moment-timezone": "^0.5.25", + "morgan": "^1.9.1", + "multer": "^1.4.1", + "nconf": "^0.10.0", + "node-uuid": "^1.4.8", + "nodemailer": "^6.1.1", + "nodemailer-smtp-transport": "^2.7.4", "optimist": "^0.6.1", - "passport": "^0.3.2", + "passport": "^0.4.0", + "passport-google-oauth20": "^1.0.0", "passport-http-bearer": "^1.0.1", "passport-local": "^1.0.0", - "redis": "^3.1.2", - "sequelize": "^3.19.2", - "sequelize-cli": "2.5.1", - "serve-favicon": "^2.1.7", - "sqlite3": "^4.0.1", - "underscore": "^1.8.3", + "sequelize": "^5.8.2", + "sequelize-cli": "5.4.0", + "serve-favicon": "^2.5.0", + "underscore": "^1.9.1", "uuid": "^3.3.2", - "validator": "^3.43.0" + "validator": "^13.11.0" }, "devDependencies": { - "chai": "^2.2.0", + "chai": "^4.2.0", + "eslint": "^8.51.0", + "eslint-config-prettier": "^9.0.0", + "eslint-config-standard": "^17.1.0", + "eslint-plugin-import": "^2.28.1", + "eslint-plugin-mocha": "^10.2.0", + "eslint-plugin-n": "^16.2.0", + "eslint-plugin-promise": "^6.1.1", "mocha": "^6.2.2", - "node-sass": "^4.5.3", - "request-promise": "^4.2.2", - "selenium-webdriver": "2.53.3" + "node-sass": "^8.0.0", + "prettier": "1.17.0", + "request-promise": "^4.2.4", + "selenium-webdriver": "^3.6.0" }, "scripts": { + "prettier": "prettier --write \"**/*.js\"", + "lint": "eslint --ext .js \"**/*.js\"", + "lint:fix": "eslint --ext .js \"**/*.js\" --fix", "test": "node node_modules/mocha/bin/mocha --recursive t", + "test:chrome": "USE_CHROME=1 node node_modules/mocha/bin/mocha --recursive t", "start": "node bin/wwww", "db-update": "node node_modules/.bin/sequelize db:migrate --config=config/db.json --models-path=lib/model/db/", "carry-over-allowance": "node bin/calculate_carry_over_allowance_for_all_users.js", @@ -59,6 +77,6 @@ "preinstall": "npx npm-force-resolutions" }, "resolutions": { - "graceful-fs": "^4.2.4" + "graceful-fs": "4.2.11" } } diff --git a/public/css/bootstrap-datepicker3.standalone.css b/public/css/bootstrap-datepicker3.standalone.css index 409993cc8..415873174 100644 --- a/public/css/bootstrap-datepicker3.standalone.css +++ b/public/css/bootstrap-datepicker3.standalone.css @@ -24,7 +24,7 @@ padding: 4px; } .datepicker-dropdown:before { - content: ''; + content: ""; display: inline-block; border-left: 7px solid transparent; border-right: 7px solid transparent; @@ -34,7 +34,7 @@ position: absolute; } .datepicker-dropdown:after { - content: ''; + content: ""; display: inline-block; border-left: 6px solid transparent; border-right: 6px solid transparent; @@ -652,7 +652,12 @@ fieldset[disabled] .datepicker table tr td.active.highlighted.focus { .open > .dropdown-toggle.datepicker table tr td span.active:hover, .open > .dropdown-toggle.datepicker table tr td span.active:hover:hover, .open > .dropdown-toggle.datepicker table tr td span.active.disabled:hover, -.open > .dropdown-toggle.datepicker table tr td span.active.disabled:hover:hover, +.open +> .dropdown-toggle.datepicker +table +tr +td +span.active.disabled:hover:hover, .datepicker table tr td span.active:active:focus, .datepicker table tr td span.active:hover:active:focus, .datepicker table tr td span.active.disabled:active:focus, @@ -664,7 +669,12 @@ fieldset[disabled] .datepicker table tr td.active.highlighted.focus { .open > .dropdown-toggle.datepicker table tr td span.active:focus, .open > .dropdown-toggle.datepicker table tr td span.active:hover:focus, .open > .dropdown-toggle.datepicker table tr td span.active.disabled:focus, -.open > .dropdown-toggle.datepicker table tr td span.active.disabled:hover:focus, +.open +> .dropdown-toggle.datepicker +table +tr +td +span.active.disabled:hover:focus, .datepicker table tr td span.active:active.focus, .datepicker table tr td span.active:hover:active.focus, .datepicker table tr td span.active.disabled:active.focus, @@ -676,7 +686,12 @@ fieldset[disabled] .datepicker table tr td.active.highlighted.focus { .open > .dropdown-toggle.datepicker table tr td span.active.focus, .open > .dropdown-toggle.datepicker table tr td span.active:hover.focus, .open > .dropdown-toggle.datepicker table tr td span.active.disabled.focus, -.open > .dropdown-toggle.datepicker table tr td span.active.disabled:hover.focus { +.open +> .dropdown-toggle.datepicker +table +tr +td +span.active.disabled:hover.focus { color: #ffffff; background-color: #285e8e; border-color: #193c5a; diff --git a/public/css/bootstrap.min.css b/public/css/bootstrap.min.css index 03759e110..aafdbe379 100755 --- a/public/css/bootstrap.min.css +++ b/public/css/bootstrap.min.css @@ -7,8 +7,7133 @@ /*! * Generated using the Bootstrap Customizer (http://getbootstrap.com/customize/?id=2f747106c336fe71d867) * Config saved to config.json and https://gist.github.com/2f747106c336fe71d867 - *//*! + */ /*! * Bootstrap v3.3.6 (http://getbootstrap.com) * Copyright 2011-2015 Twitter, Inc. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) - *//*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background-color:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:bold}dfn{font-style:italic}h1{font-size:2em;margin:0.67em 0}mark{background:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-0.5em}sub{bottom:-0.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;height:0}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace, monospace;font-size:1em}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0}button{overflow:visible}button,select{text-transform:none}button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}input{line-height:normal}input[type="checkbox"],input[type="radio"]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:0}input[type="number"]::-webkit-inner-spin-button,input[type="number"]::-webkit-outer-spin-button{height:auto}input[type="search"]{-webkit-appearance:textfield;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none}fieldset{border:1px solid #c0c0c0;margin:0 2px;padding:0.35em 0.625em 0.75em}legend{border:0;padding:0}textarea{overflow:auto}optgroup{font-weight:bold}table{border-collapse:collapse;border-spacing:0}td,th{padding:0}/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */@media print{*,*:before,*:after{background:transparent !important;color:#000 !important;-webkit-box-shadow:none !important;box-shadow:none !important;text-shadow:none !important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href) ")"}abbr[title]:after{content:" (" attr(title) ")"}a[href^="#"]:after,a[href^="javascript:"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100% !important}p,h2,h3{orphans:3;widows:3}h2,h3{page-break-after:avoid}.navbar{display:none}.btn>.caret,.dropup>.btn>.caret{border-top-color:#000 !important}.label{border:1px solid #000}.table{border-collapse:collapse !important}.table td,.table th{background-color:#fff !important}.table-bordered th,.table-bordered td{border:1px solid #ddd !important}}@font-face{font-family:'Glyphicons Halflings';src:url('../fonts/glyphicons-halflings-regular.eot');src:url('../fonts/glyphicons-halflings-regular.eot?#iefix') format('embedded-opentype'),url('../fonts/glyphicons-halflings-regular.woff2') format('woff2'),url('../fonts/glyphicons-halflings-regular.woff') format('woff'),url('../fonts/glyphicons-halflings-regular.ttf') format('truetype'),url('../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular') format('svg')}.glyphicon{position:relative;top:1px;display:inline-block;font-family:'Glyphicons Halflings';font-style:normal;font-weight:normal;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.glyphicon-asterisk:before{content:"\002a"}.glyphicon-plus:before{content:"\002b"}.glyphicon-euro:before,.glyphicon-eur:before{content:"\20ac"}.glyphicon-minus:before{content:"\2212"}.glyphicon-cloud:before{content:"\2601"}.glyphicon-envelope:before{content:"\2709"}.glyphicon-pencil:before{content:"\270f"}.glyphicon-glass:before{content:"\e001"}.glyphicon-music:before{content:"\e002"}.glyphicon-search:before{content:"\e003"}.glyphicon-heart:before{content:"\e005"}.glyphicon-star:before{content:"\e006"}.glyphicon-star-empty:before{content:"\e007"}.glyphicon-user:before{content:"\e008"}.glyphicon-film:before{content:"\e009"}.glyphicon-th-large:before{content:"\e010"}.glyphicon-th:before{content:"\e011"}.glyphicon-th-list:before{content:"\e012"}.glyphicon-ok:before{content:"\e013"}.glyphicon-remove:before{content:"\e014"}.glyphicon-zoom-in:before{content:"\e015"}.glyphicon-zoom-out:before{content:"\e016"}.glyphicon-off:before{content:"\e017"}.glyphicon-signal:before{content:"\e018"}.glyphicon-cog:before{content:"\e019"}.glyphicon-trash:before{content:"\e020"}.glyphicon-home:before{content:"\e021"}.glyphicon-file:before{content:"\e022"}.glyphicon-time:before{content:"\e023"}.glyphicon-road:before{content:"\e024"}.glyphicon-download-alt:before{content:"\e025"}.glyphicon-download:before{content:"\e026"}.glyphicon-upload:before{content:"\e027"}.glyphicon-inbox:before{content:"\e028"}.glyphicon-play-circle:before{content:"\e029"}.glyphicon-repeat:before{content:"\e030"}.glyphicon-refresh:before{content:"\e031"}.glyphicon-list-alt:before{content:"\e032"}.glyphicon-lock:before{content:"\e033"}.glyphicon-flag:before{content:"\e034"}.glyphicon-headphones:before{content:"\e035"}.glyphicon-volume-off:before{content:"\e036"}.glyphicon-volume-down:before{content:"\e037"}.glyphicon-volume-up:before{content:"\e038"}.glyphicon-qrcode:before{content:"\e039"}.glyphicon-barcode:before{content:"\e040"}.glyphicon-tag:before{content:"\e041"}.glyphicon-tags:before{content:"\e042"}.glyphicon-book:before{content:"\e043"}.glyphicon-bookmark:before{content:"\e044"}.glyphicon-print:before{content:"\e045"}.glyphicon-camera:before{content:"\e046"}.glyphicon-font:before{content:"\e047"}.glyphicon-bold:before{content:"\e048"}.glyphicon-italic:before{content:"\e049"}.glyphicon-text-height:before{content:"\e050"}.glyphicon-text-width:before{content:"\e051"}.glyphicon-align-left:before{content:"\e052"}.glyphicon-align-center:before{content:"\e053"}.glyphicon-align-right:before{content:"\e054"}.glyphicon-align-justify:before{content:"\e055"}.glyphicon-list:before{content:"\e056"}.glyphicon-indent-left:before{content:"\e057"}.glyphicon-indent-right:before{content:"\e058"}.glyphicon-facetime-video:before{content:"\e059"}.glyphicon-picture:before{content:"\e060"}.glyphicon-map-marker:before{content:"\e062"}.glyphicon-adjust:before{content:"\e063"}.glyphicon-tint:before{content:"\e064"}.glyphicon-edit:before{content:"\e065"}.glyphicon-share:before{content:"\e066"}.glyphicon-check:before{content:"\e067"}.glyphicon-move:before{content:"\e068"}.glyphicon-step-backward:before{content:"\e069"}.glyphicon-fast-backward:before{content:"\e070"}.glyphicon-backward:before{content:"\e071"}.glyphicon-play:before{content:"\e072"}.glyphicon-pause:before{content:"\e073"}.glyphicon-stop:before{content:"\e074"}.glyphicon-forward:before{content:"\e075"}.glyphicon-fast-forward:before{content:"\e076"}.glyphicon-step-forward:before{content:"\e077"}.glyphicon-eject:before{content:"\e078"}.glyphicon-chevron-left:before{content:"\e079"}.glyphicon-chevron-right:before{content:"\e080"}.glyphicon-plus-sign:before{content:"\e081"}.glyphicon-minus-sign:before{content:"\e082"}.glyphicon-remove-sign:before{content:"\e083"}.glyphicon-ok-sign:before{content:"\e084"}.glyphicon-question-sign:before{content:"\e085"}.glyphicon-info-sign:before{content:"\e086"}.glyphicon-screenshot:before{content:"\e087"}.glyphicon-remove-circle:before{content:"\e088"}.glyphicon-ok-circle:before{content:"\e089"}.glyphicon-ban-circle:before{content:"\e090"}.glyphicon-arrow-left:before{content:"\e091"}.glyphicon-arrow-right:before{content:"\e092"}.glyphicon-arrow-up:before{content:"\e093"}.glyphicon-arrow-down:before{content:"\e094"}.glyphicon-share-alt:before{content:"\e095"}.glyphicon-resize-full:before{content:"\e096"}.glyphicon-resize-small:before{content:"\e097"}.glyphicon-exclamation-sign:before{content:"\e101"}.glyphicon-gift:before{content:"\e102"}.glyphicon-leaf:before{content:"\e103"}.glyphicon-fire:before{content:"\e104"}.glyphicon-eye-open:before{content:"\e105"}.glyphicon-eye-close:before{content:"\e106"}.glyphicon-warning-sign:before{content:"\e107"}.glyphicon-plane:before{content:"\e108"}.glyphicon-calendar:before{content:"\e109"}.glyphicon-random:before{content:"\e110"}.glyphicon-comment:before{content:"\e111"}.glyphicon-magnet:before{content:"\e112"}.glyphicon-chevron-up:before{content:"\e113"}.glyphicon-chevron-down:before{content:"\e114"}.glyphicon-retweet:before{content:"\e115"}.glyphicon-shopping-cart:before{content:"\e116"}.glyphicon-folder-close:before{content:"\e117"}.glyphicon-folder-open:before{content:"\e118"}.glyphicon-resize-vertical:before{content:"\e119"}.glyphicon-resize-horizontal:before{content:"\e120"}.glyphicon-hdd:before{content:"\e121"}.glyphicon-bullhorn:before{content:"\e122"}.glyphicon-bell:before{content:"\e123"}.glyphicon-certificate:before{content:"\e124"}.glyphicon-thumbs-up:before{content:"\e125"}.glyphicon-thumbs-down:before{content:"\e126"}.glyphicon-hand-right:before{content:"\e127"}.glyphicon-hand-left:before{content:"\e128"}.glyphicon-hand-up:before{content:"\e129"}.glyphicon-hand-down:before{content:"\e130"}.glyphicon-circle-arrow-right:before{content:"\e131"}.glyphicon-circle-arrow-left:before{content:"\e132"}.glyphicon-circle-arrow-up:before{content:"\e133"}.glyphicon-circle-arrow-down:before{content:"\e134"}.glyphicon-globe:before{content:"\e135"}.glyphicon-wrench:before{content:"\e136"}.glyphicon-tasks:before{content:"\e137"}.glyphicon-filter:before{content:"\e138"}.glyphicon-briefcase:before{content:"\e139"}.glyphicon-fullscreen:before{content:"\e140"}.glyphicon-dashboard:before{content:"\e141"}.glyphicon-paperclip:before{content:"\e142"}.glyphicon-heart-empty:before{content:"\e143"}.glyphicon-link:before{content:"\e144"}.glyphicon-phone:before{content:"\e145"}.glyphicon-pushpin:before{content:"\e146"}.glyphicon-usd:before{content:"\e148"}.glyphicon-gbp:before{content:"\e149"}.glyphicon-sort:before{content:"\e150"}.glyphicon-sort-by-alphabet:before{content:"\e151"}.glyphicon-sort-by-alphabet-alt:before{content:"\e152"}.glyphicon-sort-by-order:before{content:"\e153"}.glyphicon-sort-by-order-alt:before{content:"\e154"}.glyphicon-sort-by-attributes:before{content:"\e155"}.glyphicon-sort-by-attributes-alt:before{content:"\e156"}.glyphicon-unchecked:before{content:"\e157"}.glyphicon-expand:before{content:"\e158"}.glyphicon-collapse-down:before{content:"\e159"}.glyphicon-collapse-up:before{content:"\e160"}.glyphicon-log-in:before{content:"\e161"}.glyphicon-flash:before{content:"\e162"}.glyphicon-log-out:before{content:"\e163"}.glyphicon-new-window:before{content:"\e164"}.glyphicon-record:before{content:"\e165"}.glyphicon-save:before{content:"\e166"}.glyphicon-open:before{content:"\e167"}.glyphicon-saved:before{content:"\e168"}.glyphicon-import:before{content:"\e169"}.glyphicon-export:before{content:"\e170"}.glyphicon-send:before{content:"\e171"}.glyphicon-floppy-disk:before{content:"\e172"}.glyphicon-floppy-saved:before{content:"\e173"}.glyphicon-floppy-remove:before{content:"\e174"}.glyphicon-floppy-save:before{content:"\e175"}.glyphicon-floppy-open:before{content:"\e176"}.glyphicon-credit-card:before{content:"\e177"}.glyphicon-transfer:before{content:"\e178"}.glyphicon-cutlery:before{content:"\e179"}.glyphicon-header:before{content:"\e180"}.glyphicon-compressed:before{content:"\e181"}.glyphicon-earphone:before{content:"\e182"}.glyphicon-phone-alt:before{content:"\e183"}.glyphicon-tower:before{content:"\e184"}.glyphicon-stats:before{content:"\e185"}.glyphicon-sd-video:before{content:"\e186"}.glyphicon-hd-video:before{content:"\e187"}.glyphicon-subtitles:before{content:"\e188"}.glyphicon-sound-stereo:before{content:"\e189"}.glyphicon-sound-dolby:before{content:"\e190"}.glyphicon-sound-5-1:before{content:"\e191"}.glyphicon-sound-6-1:before{content:"\e192"}.glyphicon-sound-7-1:before{content:"\e193"}.glyphicon-copyright-mark:before{content:"\e194"}.glyphicon-registration-mark:before{content:"\e195"}.glyphicon-cloud-download:before{content:"\e197"}.glyphicon-cloud-upload:before{content:"\e198"}.glyphicon-tree-conifer:before{content:"\e199"}.glyphicon-tree-deciduous:before{content:"\e200"}.glyphicon-cd:before{content:"\e201"}.glyphicon-save-file:before{content:"\e202"}.glyphicon-open-file:before{content:"\e203"}.glyphicon-level-up:before{content:"\e204"}.glyphicon-copy:before{content:"\e205"}.glyphicon-paste:before{content:"\e206"}.glyphicon-alert:before{content:"\e209"}.glyphicon-equalizer:before{content:"\e210"}.glyphicon-king:before{content:"\e211"}.glyphicon-queen:before{content:"\e212"}.glyphicon-pawn:before{content:"\e213"}.glyphicon-bishop:before{content:"\e214"}.glyphicon-knight:before{content:"\e215"}.glyphicon-baby-formula:before{content:"\e216"}.glyphicon-tent:before{content:"\26fa"}.glyphicon-blackboard:before{content:"\e218"}.glyphicon-bed:before{content:"\e219"}.glyphicon-apple:before{content:"\f8ff"}.glyphicon-erase:before{content:"\e221"}.glyphicon-hourglass:before{content:"\231b"}.glyphicon-lamp:before{content:"\e223"}.glyphicon-duplicate:before{content:"\e224"}.glyphicon-piggy-bank:before{content:"\e225"}.glyphicon-scissors:before{content:"\e226"}.glyphicon-bitcoin:before{content:"\e227"}.glyphicon-btc:before{content:"\e227"}.glyphicon-xbt:before{content:"\e227"}.glyphicon-yen:before{content:"\00a5"}.glyphicon-jpy:before{content:"\00a5"}.glyphicon-ruble:before{content:"\20bd"}.glyphicon-rub:before{content:"\20bd"}.glyphicon-scale:before{content:"\e230"}.glyphicon-ice-lolly:before{content:"\e231"}.glyphicon-ice-lolly-tasted:before{content:"\e232"}.glyphicon-education:before{content:"\e233"}.glyphicon-option-horizontal:before{content:"\e234"}.glyphicon-option-vertical:before{content:"\e235"}.glyphicon-menu-hamburger:before{content:"\e236"}.glyphicon-modal-window:before{content:"\e237"}.glyphicon-oil:before{content:"\e238"}.glyphicon-grain:before{content:"\e239"}.glyphicon-sunglasses:before{content:"\e240"}.glyphicon-text-size:before{content:"\e241"}.glyphicon-text-color:before{content:"\e242"}.glyphicon-text-background:before{content:"\e243"}.glyphicon-object-align-top:before{content:"\e244"}.glyphicon-object-align-bottom:before{content:"\e245"}.glyphicon-object-align-horizontal:before{content:"\e246"}.glyphicon-object-align-left:before{content:"\e247"}.glyphicon-object-align-vertical:before{content:"\e248"}.glyphicon-object-align-right:before{content:"\e249"}.glyphicon-triangle-right:before{content:"\e250"}.glyphicon-triangle-left:before{content:"\e251"}.glyphicon-triangle-bottom:before{content:"\e252"}.glyphicon-triangle-top:before{content:"\e253"}.glyphicon-console:before{content:"\e254"}.glyphicon-superscript:before{content:"\e255"}.glyphicon-subscript:before{content:"\e256"}.glyphicon-menu-left:before{content:"\e257"}.glyphicon-menu-right:before{content:"\e258"}.glyphicon-menu-down:before{content:"\e259"}.glyphicon-menu-up:before{content:"\e260"}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}*:before,*:after{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{font-size:10px;-webkit-tap-highlight-color:rgba(0,0,0,0)}body{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;line-height:1.42857143;color:#333;background-color:#fff}input,button,select,textarea{font-family:inherit;font-size:inherit;line-height:inherit}a{color:#337ab7;text-decoration:none}a:hover,a:focus{color:#23527c;text-decoration:underline}a:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}figure{margin:0}img{vertical-align:middle}.img-responsive,.thumbnail>img,.thumbnail a>img,.carousel-inner>.item>img,.carousel-inner>.item>a>img{display:block;max-width:100%;height:auto}.img-rounded{border-radius:6px}.img-thumbnail{padding:4px;line-height:1.42857143;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:all .2s ease-in-out;-o-transition:all .2s ease-in-out;transition:all .2s ease-in-out;display:inline-block;max-width:100%;height:auto}.img-circle{border-radius:50%}hr{margin-top:20px;margin-bottom:20px;border:0;border-top:1px solid #eee}.sr-only{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0, 0, 0, 0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto}[role="button"]{cursor:pointer}h1,h2,h3,h4,h5,h6,.h1,.h2,.h3,.h4,.h5,.h6{font-family:inherit;font-weight:500;line-height:1.1;color:inherit}h1 small,h2 small,h3 small,h4 small,h5 small,h6 small,.h1 small,.h2 small,.h3 small,.h4 small,.h5 small,.h6 small,h1 .small,h2 .small,h3 .small,h4 .small,h5 .small,h6 .small,.h1 .small,.h2 .small,.h3 .small,.h4 .small,.h5 .small,.h6 .small{font-weight:normal;line-height:1;color:#777}h1,.h1,h2,.h2,h3,.h3{margin-top:20px;margin-bottom:10px}h1 small,.h1 small,h2 small,.h2 small,h3 small,.h3 small,h1 .small,.h1 .small,h2 .small,.h2 .small,h3 .small,.h3 .small{font-size:65%}h4,.h4,h5,.h5,h6,.h6{margin-top:10px;margin-bottom:10px}h4 small,.h4 small,h5 small,.h5 small,h6 small,.h6 small,h4 .small,.h4 .small,h5 .small,.h5 .small,h6 .small,.h6 .small{font-size:75%}h1,.h1{font-size:36px}h2,.h2{font-size:30px}h3,.h3{font-size:24px}h4,.h4{font-size:18px}h5,.h5{font-size:14px}h6,.h6{font-size:12px}p{margin:0 0 10px}.lead{margin-bottom:20px;font-size:16px;font-weight:300;line-height:1.4}@media (min-width:768px){.lead{font-size:21px}}small,.small{font-size:85%}mark,.mark{background-color:#fcf8e3;padding:.2em}.text-left{text-align:left}.text-right{text-align:right}.text-center{text-align:center}.text-justify{text-align:justify}.text-nowrap{white-space:nowrap}.text-lowercase{text-transform:lowercase}.text-uppercase{text-transform:uppercase}.text-capitalize{text-transform:capitalize}.text-muted{color:#777}.text-primary{color:#337ab7}a.text-primary:hover,a.text-primary:focus{color:#286090}.text-success{color:#3c763d}a.text-success:hover,a.text-success:focus{color:#2b542c}.text-info{color:#31708f}a.text-info:hover,a.text-info:focus{color:#245269}.text-warning{color:#8a6d3b}a.text-warning:hover,a.text-warning:focus{color:#66512c}.text-danger{color:#a94442}a.text-danger:hover,a.text-danger:focus{color:#843534}.bg-primary{color:#fff;background-color:#337ab7}a.bg-primary:hover,a.bg-primary:focus{background-color:#286090}.bg-success{background-color:#dff0d8}a.bg-success:hover,a.bg-success:focus{background-color:#c1e2b3}.bg-info{background-color:#d9edf7}a.bg-info:hover,a.bg-info:focus{background-color:#afd9ee}.bg-warning{background-color:#fcf8e3}a.bg-warning:hover,a.bg-warning:focus{background-color:#f7ecb5}.bg-danger{background-color:#f2dede}a.bg-danger:hover,a.bg-danger:focus{background-color:#e4b9b9}.page-header{padding-bottom:9px;margin:40px 0 20px;border-bottom:1px solid #eee}ul,ol{margin-top:0;margin-bottom:10px}ul ul,ol ul,ul ol,ol ol{margin-bottom:0}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;list-style:none;margin-left:-5px}.list-inline>li{display:inline-block;padding-left:5px;padding-right:5px}dl{margin-top:0;margin-bottom:20px}dt,dd{line-height:1.42857143}dt{font-weight:bold}dd{margin-left:0}@media (min-width:768px){.dl-horizontal dt{float:left;width:160px;clear:left;text-align:right;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.dl-horizontal dd{margin-left:180px}}abbr[title],abbr[data-original-title]{cursor:help;border-bottom:1px dotted #777}.initialism{font-size:90%;text-transform:uppercase}blockquote{padding:10px 20px;margin:0 0 20px;font-size:17.5px;border-left:5px solid #eee}blockquote p:last-child,blockquote ul:last-child,blockquote ol:last-child{margin-bottom:0}blockquote footer,blockquote small,blockquote .small{display:block;font-size:80%;line-height:1.42857143;color:#777}blockquote footer:before,blockquote small:before,blockquote .small:before{content:'\2014 \00A0'}.blockquote-reverse,blockquote.pull-right{padding-right:15px;padding-left:0;border-right:5px solid #eee;border-left:0;text-align:right}.blockquote-reverse footer:before,blockquote.pull-right footer:before,.blockquote-reverse small:before,blockquote.pull-right small:before,.blockquote-reverse .small:before,blockquote.pull-right .small:before{content:''}.blockquote-reverse footer:after,blockquote.pull-right footer:after,.blockquote-reverse small:after,blockquote.pull-right small:after,.blockquote-reverse .small:after,blockquote.pull-right .small:after{content:'\00A0 \2014'}address{margin-bottom:20px;font-style:normal;line-height:1.42857143}code,kbd,pre,samp{font-family:Menlo,Monaco,Consolas,"Courier New",monospace}code{padding:2px 4px;font-size:90%;color:#c7254e;background-color:#f9f2f4;border-radius:4px}kbd{padding:2px 4px;font-size:90%;color:#fff;background-color:#333;border-radius:3px;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,0.25);box-shadow:inset 0 -1px 0 rgba(0,0,0,0.25)}kbd kbd{padding:0;font-size:100%;font-weight:bold;-webkit-box-shadow:none;box-shadow:none}pre{display:block;padding:9.5px;margin:0 0 10px;font-size:13px;line-height:1.42857143;word-break:break-all;word-wrap:break-word;color:#333;background-color:#f5f7f8;border:1px solid #ccc;border-radius:4px}pre code{padding:0;font-size:inherit;color:inherit;white-space:pre-wrap;background-color:transparent;border-radius:0}.pre-scrollable{max-height:340px;overflow-y:scroll}.container{margin-right:auto;margin-left:auto;padding-left:15px;padding-right:15px}@media (min-width:768px){.container{width:750px}}@media (min-width:992px){.container{width:970px}}@media (min-width:1200px){.container{width:1170px}}.container-fluid{margin-right:auto;margin-left:auto;padding-left:15px;padding-right:15px}.row{margin-left:-15px;margin-right:-15px}.col-xs-1, .col-sm-1, .col-md-1, .col-lg-1, .col-xs-2, .col-sm-2, .col-md-2, .col-lg-2, .col-xs-3, .col-sm-3, .col-md-3, .col-lg-3, .col-xs-4, .col-sm-4, .col-md-4, .col-lg-4, .col-xs-5, .col-sm-5, .col-md-5, .col-lg-5, .col-xs-6, .col-sm-6, .col-md-6, .col-lg-6, .col-xs-7, .col-sm-7, .col-md-7, .col-lg-7, .col-xs-8, .col-sm-8, .col-md-8, .col-lg-8, .col-xs-9, .col-sm-9, .col-md-9, .col-lg-9, .col-xs-10, .col-sm-10, .col-md-10, .col-lg-10, .col-xs-11, .col-sm-11, .col-md-11, .col-lg-11, .col-xs-12, .col-sm-12, .col-md-12, .col-lg-12{position:relative;min-height:1px;padding-left:15px;padding-right:15px}.col-xs-1, .col-xs-2, .col-xs-3, .col-xs-4, .col-xs-5, .col-xs-6, .col-xs-7, .col-xs-8, .col-xs-9, .col-xs-10, .col-xs-11, .col-xs-12{float:left}.col-xs-12{width:100%}.col-xs-11{width:91.66666667%}.col-xs-10{width:83.33333333%}.col-xs-9{width:75%}.col-xs-8{width:66.66666667%}.col-xs-7{width:58.33333333%}.col-xs-6{width:50%}.col-xs-5{width:41.66666667%}.col-xs-4{width:33.33333333%}.col-xs-3{width:25%}.col-xs-2{width:16.66666667%}.col-xs-1{width:8.33333333%}.col-xs-pull-12{right:100%}.col-xs-pull-11{right:91.66666667%}.col-xs-pull-10{right:83.33333333%}.col-xs-pull-9{right:75%}.col-xs-pull-8{right:66.66666667%}.col-xs-pull-7{right:58.33333333%}.col-xs-pull-6{right:50%}.col-xs-pull-5{right:41.66666667%}.col-xs-pull-4{right:33.33333333%}.col-xs-pull-3{right:25%}.col-xs-pull-2{right:16.66666667%}.col-xs-pull-1{right:8.33333333%}.col-xs-pull-0{right:auto}.col-xs-push-12{left:100%}.col-xs-push-11{left:91.66666667%}.col-xs-push-10{left:83.33333333%}.col-xs-push-9{left:75%}.col-xs-push-8{left:66.66666667%}.col-xs-push-7{left:58.33333333%}.col-xs-push-6{left:50%}.col-xs-push-5{left:41.66666667%}.col-xs-push-4{left:33.33333333%}.col-xs-push-3{left:25%}.col-xs-push-2{left:16.66666667%}.col-xs-push-1{left:8.33333333%}.col-xs-push-0{left:auto}.col-xs-offset-12{margin-left:100%}.col-xs-offset-11{margin-left:91.66666667%}.col-xs-offset-10{margin-left:83.33333333%}.col-xs-offset-9{margin-left:75%}.col-xs-offset-8{margin-left:66.66666667%}.col-xs-offset-7{margin-left:58.33333333%}.col-xs-offset-6{margin-left:50%}.col-xs-offset-5{margin-left:41.66666667%}.col-xs-offset-4{margin-left:33.33333333%}.col-xs-offset-3{margin-left:25%}.col-xs-offset-2{margin-left:16.66666667%}.col-xs-offset-1{margin-left:8.33333333%}.col-xs-offset-0{margin-left:0}@media (min-width:768px){.col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12{float:left}.col-sm-12{width:100%}.col-sm-11{width:91.66666667%}.col-sm-10{width:83.33333333%}.col-sm-9{width:75%}.col-sm-8{width:66.66666667%}.col-sm-7{width:58.33333333%}.col-sm-6{width:50%}.col-sm-5{width:41.66666667%}.col-sm-4{width:33.33333333%}.col-sm-3{width:25%}.col-sm-2{width:16.66666667%}.col-sm-1{width:8.33333333%}.col-sm-pull-12{right:100%}.col-sm-pull-11{right:91.66666667%}.col-sm-pull-10{right:83.33333333%}.col-sm-pull-9{right:75%}.col-sm-pull-8{right:66.66666667%}.col-sm-pull-7{right:58.33333333%}.col-sm-pull-6{right:50%}.col-sm-pull-5{right:41.66666667%}.col-sm-pull-4{right:33.33333333%}.col-sm-pull-3{right:25%}.col-sm-pull-2{right:16.66666667%}.col-sm-pull-1{right:8.33333333%}.col-sm-pull-0{right:auto}.col-sm-push-12{left:100%}.col-sm-push-11{left:91.66666667%}.col-sm-push-10{left:83.33333333%}.col-sm-push-9{left:75%}.col-sm-push-8{left:66.66666667%}.col-sm-push-7{left:58.33333333%}.col-sm-push-6{left:50%}.col-sm-push-5{left:41.66666667%}.col-sm-push-4{left:33.33333333%}.col-sm-push-3{left:25%}.col-sm-push-2{left:16.66666667%}.col-sm-push-1{left:8.33333333%}.col-sm-push-0{left:auto}.col-sm-offset-12{margin-left:100%}.col-sm-offset-11{margin-left:91.66666667%}.col-sm-offset-10{margin-left:83.33333333%}.col-sm-offset-9{margin-left:75%}.col-sm-offset-8{margin-left:66.66666667%}.col-sm-offset-7{margin-left:58.33333333%}.col-sm-offset-6{margin-left:50%}.col-sm-offset-5{margin-left:41.66666667%}.col-sm-offset-4{margin-left:33.33333333%}.col-sm-offset-3{margin-left:25%}.col-sm-offset-2{margin-left:16.66666667%}.col-sm-offset-1{margin-left:8.33333333%}.col-sm-offset-0{margin-left:0}}@media (min-width:992px){.col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12{float:left}.col-md-12{width:100%}.col-md-11{width:91.66666667%}.col-md-10{width:83.33333333%}.col-md-9{width:75%}.col-md-8{width:66.66666667%}.col-md-7{width:58.33333333%}.col-md-6{width:50%}.col-md-5{width:41.66666667%}.col-md-4{width:33.33333333%}.col-md-3{width:25%}.col-md-2{width:16.66666667%}.col-md-1{width:8.33333333%}.col-md-pull-12{right:100%}.col-md-pull-11{right:91.66666667%}.col-md-pull-10{right:83.33333333%}.col-md-pull-9{right:75%}.col-md-pull-8{right:66.66666667%}.col-md-pull-7{right:58.33333333%}.col-md-pull-6{right:50%}.col-md-pull-5{right:41.66666667%}.col-md-pull-4{right:33.33333333%}.col-md-pull-3{right:25%}.col-md-pull-2{right:16.66666667%}.col-md-pull-1{right:8.33333333%}.col-md-pull-0{right:auto}.col-md-push-12{left:100%}.col-md-push-11{left:91.66666667%}.col-md-push-10{left:83.33333333%}.col-md-push-9{left:75%}.col-md-push-8{left:66.66666667%}.col-md-push-7{left:58.33333333%}.col-md-push-6{left:50%}.col-md-push-5{left:41.66666667%}.col-md-push-4{left:33.33333333%}.col-md-push-3{left:25%}.col-md-push-2{left:16.66666667%}.col-md-push-1{left:8.33333333%}.col-md-push-0{left:auto}.col-md-offset-12{margin-left:100%}.col-md-offset-11{margin-left:91.66666667%}.col-md-offset-10{margin-left:83.33333333%}.col-md-offset-9{margin-left:75%}.col-md-offset-8{margin-left:66.66666667%}.col-md-offset-7{margin-left:58.33333333%}.col-md-offset-6{margin-left:50%}.col-md-offset-5{margin-left:41.66666667%}.col-md-offset-4{margin-left:33.33333333%}.col-md-offset-3{margin-left:25%}.col-md-offset-2{margin-left:16.66666667%}.col-md-offset-1{margin-left:8.33333333%}.col-md-offset-0{margin-left:0}}@media (min-width:1200px){.col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12{float:left}.col-lg-12{width:100%}.col-lg-11{width:91.66666667%}.col-lg-10{width:83.33333333%}.col-lg-9{width:75%}.col-lg-8{width:66.66666667%}.col-lg-7{width:58.33333333%}.col-lg-6{width:50%}.col-lg-5{width:41.66666667%}.col-lg-4{width:33.33333333%}.col-lg-3{width:25%}.col-lg-2{width:16.66666667%}.col-lg-1{width:8.33333333%}.col-lg-pull-12{right:100%}.col-lg-pull-11{right:91.66666667%}.col-lg-pull-10{right:83.33333333%}.col-lg-pull-9{right:75%}.col-lg-pull-8{right:66.66666667%}.col-lg-pull-7{right:58.33333333%}.col-lg-pull-6{right:50%}.col-lg-pull-5{right:41.66666667%}.col-lg-pull-4{right:33.33333333%}.col-lg-pull-3{right:25%}.col-lg-pull-2{right:16.66666667%}.col-lg-pull-1{right:8.33333333%}.col-lg-pull-0{right:auto}.col-lg-push-12{left:100%}.col-lg-push-11{left:91.66666667%}.col-lg-push-10{left:83.33333333%}.col-lg-push-9{left:75%}.col-lg-push-8{left:66.66666667%}.col-lg-push-7{left:58.33333333%}.col-lg-push-6{left:50%}.col-lg-push-5{left:41.66666667%}.col-lg-push-4{left:33.33333333%}.col-lg-push-3{left:25%}.col-lg-push-2{left:16.66666667%}.col-lg-push-1{left:8.33333333%}.col-lg-push-0{left:auto}.col-lg-offset-12{margin-left:100%}.col-lg-offset-11{margin-left:91.66666667%}.col-lg-offset-10{margin-left:83.33333333%}.col-lg-offset-9{margin-left:75%}.col-lg-offset-8{margin-left:66.66666667%}.col-lg-offset-7{margin-left:58.33333333%}.col-lg-offset-6{margin-left:50%}.col-lg-offset-5{margin-left:41.66666667%}.col-lg-offset-4{margin-left:33.33333333%}.col-lg-offset-3{margin-left:25%}.col-lg-offset-2{margin-left:16.66666667%}.col-lg-offset-1{margin-left:8.33333333%}.col-lg-offset-0{margin-left:0}}table{background-color:transparent}caption{padding-top:8px;padding-bottom:8px;color:#777;text-align:left}th{text-align:left}.table{width:100%;max-width:100%;margin-bottom:20px}.table>thead>tr>th,.table>tbody>tr>th,.table>tfoot>tr>th,.table>thead>tr>td,.table>tbody>tr>td,.table>tfoot>tr>td{padding:8px;line-height:1.42857143;vertical-align:top;border-top:1px solid #ddd}.table>thead>tr>th{vertical-align:bottom;border-bottom:2px solid #ddd}.table>caption+thead>tr:first-child>th,.table>colgroup+thead>tr:first-child>th,.table>thead:first-child>tr:first-child>th,.table>caption+thead>tr:first-child>td,.table>colgroup+thead>tr:first-child>td,.table>thead:first-child>tr:first-child>td{border-top:0}.table>tbody+tbody{border-top:2px solid #ddd}.table .table{background-color:#fff}.table-condensed>thead>tr>th,.table-condensed>tbody>tr>th,.table-condensed>tfoot>tr>th,.table-condensed>thead>tr>td,.table-condensed>tbody>tr>td,.table-condensed>tfoot>tr>td{padding:5px}.table-bordered{border:1px solid #ddd}.table-bordered>thead>tr>th,.table-bordered>tbody>tr>th,.table-bordered>tfoot>tr>th,.table-bordered>thead>tr>td,.table-bordered>tbody>tr>td,.table-bordered>tfoot>tr>td{border:1px solid #ddd}.table-bordered>thead>tr>th,.table-bordered>thead>tr>td{border-bottom-width:2px}.table-striped>tbody>tr:nth-of-type(odd){background-color:#f9f9f9}.table-hover>tbody>tr:hover{background-color:#f5f7f8}table col[class*="col-"]{position:static;float:none;display:table-column}table td[class*="col-"],table th[class*="col-"]{position:static;float:none;display:table-cell}.table>thead>tr>td.active,.table>tbody>tr>td.active,.table>tfoot>tr>td.active,.table>thead>tr>th.active,.table>tbody>tr>th.active,.table>tfoot>tr>th.active,.table>thead>tr.active>td,.table>tbody>tr.active>td,.table>tfoot>tr.active>td,.table>thead>tr.active>th,.table>tbody>tr.active>th,.table>tfoot>tr.active>th{background-color:#f5f7f8}.table-hover>tbody>tr>td.active:hover,.table-hover>tbody>tr>th.active:hover,.table-hover>tbody>tr.active:hover>td,.table-hover>tbody>tr:hover>.active,.table-hover>tbody>tr.active:hover>th{background-color:#e6ebed}.table>thead>tr>td.success,.table>tbody>tr>td.success,.table>tfoot>tr>td.success,.table>thead>tr>th.success,.table>tbody>tr>th.success,.table>tfoot>tr>th.success,.table>thead>tr.success>td,.table>tbody>tr.success>td,.table>tfoot>tr.success>td,.table>thead>tr.success>th,.table>tbody>tr.success>th,.table>tfoot>tr.success>th{background-color:#dff0d8}.table-hover>tbody>tr>td.success:hover,.table-hover>tbody>tr>th.success:hover,.table-hover>tbody>tr.success:hover>td,.table-hover>tbody>tr:hover>.success,.table-hover>tbody>tr.success:hover>th{background-color:#d0e9c6}.table>thead>tr>td.info,.table>tbody>tr>td.info,.table>tfoot>tr>td.info,.table>thead>tr>th.info,.table>tbody>tr>th.info,.table>tfoot>tr>th.info,.table>thead>tr.info>td,.table>tbody>tr.info>td,.table>tfoot>tr.info>td,.table>thead>tr.info>th,.table>tbody>tr.info>th,.table>tfoot>tr.info>th{background-color:#d9edf7}.table-hover>tbody>tr>td.info:hover,.table-hover>tbody>tr>th.info:hover,.table-hover>tbody>tr.info:hover>td,.table-hover>tbody>tr:hover>.info,.table-hover>tbody>tr.info:hover>th{background-color:#c4e3f3}.table>thead>tr>td.warning,.table>tbody>tr>td.warning,.table>tfoot>tr>td.warning,.table>thead>tr>th.warning,.table>tbody>tr>th.warning,.table>tfoot>tr>th.warning,.table>thead>tr.warning>td,.table>tbody>tr.warning>td,.table>tfoot>tr.warning>td,.table>thead>tr.warning>th,.table>tbody>tr.warning>th,.table>tfoot>tr.warning>th{background-color:#fcf8e3}.table-hover>tbody>tr>td.warning:hover,.table-hover>tbody>tr>th.warning:hover,.table-hover>tbody>tr.warning:hover>td,.table-hover>tbody>tr:hover>.warning,.table-hover>tbody>tr.warning:hover>th{background-color:#faf2cc}.table>thead>tr>td.danger,.table>tbody>tr>td.danger,.table>tfoot>tr>td.danger,.table>thead>tr>th.danger,.table>tbody>tr>th.danger,.table>tfoot>tr>th.danger,.table>thead>tr.danger>td,.table>tbody>tr.danger>td,.table>tfoot>tr.danger>td,.table>thead>tr.danger>th,.table>tbody>tr.danger>th,.table>tfoot>tr.danger>th{background-color:#f2dede}.table-hover>tbody>tr>td.danger:hover,.table-hover>tbody>tr>th.danger:hover,.table-hover>tbody>tr.danger:hover>td,.table-hover>tbody>tr:hover>.danger,.table-hover>tbody>tr.danger:hover>th{background-color:#ebcccc}.table-responsive{overflow-x:auto;min-height:0.01%}@media screen and (max-width:767px){.table-responsive{width:100%;margin-bottom:15px;overflow-y:hidden;-ms-overflow-style:-ms-autohiding-scrollbar;border:1px solid #ddd}.table-responsive>.table{margin-bottom:0}.table-responsive>.table>thead>tr>th,.table-responsive>.table>tbody>tr>th,.table-responsive>.table>tfoot>tr>th,.table-responsive>.table>thead>tr>td,.table-responsive>.table>tbody>tr>td,.table-responsive>.table>tfoot>tr>td{white-space:nowrap}.table-responsive>.table-bordered{border:0}.table-responsive>.table-bordered>thead>tr>th:first-child,.table-responsive>.table-bordered>tbody>tr>th:first-child,.table-responsive>.table-bordered>tfoot>tr>th:first-child,.table-responsive>.table-bordered>thead>tr>td:first-child,.table-responsive>.table-bordered>tbody>tr>td:first-child,.table-responsive>.table-bordered>tfoot>tr>td:first-child{border-left:0}.table-responsive>.table-bordered>thead>tr>th:last-child,.table-responsive>.table-bordered>tbody>tr>th:last-child,.table-responsive>.table-bordered>tfoot>tr>th:last-child,.table-responsive>.table-bordered>thead>tr>td:last-child,.table-responsive>.table-bordered>tbody>tr>td:last-child,.table-responsive>.table-bordered>tfoot>tr>td:last-child{border-right:0}.table-responsive>.table-bordered>tbody>tr:last-child>th,.table-responsive>.table-bordered>tfoot>tr:last-child>th,.table-responsive>.table-bordered>tbody>tr:last-child>td,.table-responsive>.table-bordered>tfoot>tr:last-child>td{border-bottom:0}}fieldset{padding:0;margin:0;border:0;min-width:0}legend{display:block;width:100%;padding:0;margin-bottom:20px;font-size:21px;line-height:inherit;color:#333;border:0;border-bottom:1px solid #e5e5e5}label{display:inline-block;max-width:100%;margin-bottom:5px;font-weight:bold}input[type="search"]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}input[type="radio"],input[type="checkbox"]{margin:4px 0 0;margin-top:1px \9;line-height:normal}input[type="file"]{display:block}input[type="range"]{display:block;width:100%}select[multiple],select[size]{height:auto}input[type="file"]:focus,input[type="radio"]:focus,input[type="checkbox"]:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}output{display:block;padding-top:7px;font-size:14px;line-height:1.42857143;color:#555}.form-control{display:block;width:100%;height:34px;padding:6px 12px;font-size:14px;line-height:1.42857143;color:#555;background-color:#fff;background-image:none;border:1px solid #ccc;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-webkit-transition:border-color ease-in-out .15s, -webkit-box-shadow ease-in-out .15s;-o-transition:border-color ease-in-out .15s, box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s, box-shadow ease-in-out .15s}.form-control:focus{border-color:#66afe9;outline:0;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6);box-shadow:inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6)}.form-control::-moz-placeholder{color:#999;opacity:1}.form-control:-ms-input-placeholder{color:#999}.form-control::-webkit-input-placeholder{color:#999}.form-control::-ms-expand{border:0;background-color:transparent}.form-control[disabled],.form-control[readonly],fieldset[disabled] .form-control{background-color:#eee;opacity:1}.form-control[disabled],fieldset[disabled] .form-control{cursor:not-allowed}textarea.form-control{height:auto}input[type="search"]{-webkit-appearance:none}@media screen and (-webkit-min-device-pixel-ratio:0){input[type="date"].form-control,input[type="time"].form-control,input[type="datetime-local"].form-control,input[type="month"].form-control{line-height:34px}input[type="date"].input-sm,input[type="time"].input-sm,input[type="datetime-local"].input-sm,input[type="month"].input-sm,.input-group-sm input[type="date"],.input-group-sm input[type="time"],.input-group-sm input[type="datetime-local"],.input-group-sm input[type="month"]{line-height:30px}input[type="date"].input-lg,input[type="time"].input-lg,input[type="datetime-local"].input-lg,input[type="month"].input-lg,.input-group-lg input[type="date"],.input-group-lg input[type="time"],.input-group-lg input[type="datetime-local"],.input-group-lg input[type="month"]{line-height:46px}}.form-group{margin-bottom:15px}.radio,.checkbox{position:relative;display:block;margin-top:10px;margin-bottom:10px}.radio label,.checkbox label{min-height:20px;padding-left:20px;margin-bottom:0;font-weight:normal;cursor:pointer}.radio input[type="radio"],.radio-inline input[type="radio"],.checkbox input[type="checkbox"],.checkbox-inline input[type="checkbox"]{position:absolute;margin-left:-20px;margin-top:4px \9}.radio+.radio,.checkbox+.checkbox{margin-top:-5px}.radio-inline,.checkbox-inline{position:relative;display:inline-block;padding-left:20px;margin-bottom:0;vertical-align:middle;font-weight:normal;cursor:pointer}.radio-inline+.radio-inline,.checkbox-inline+.checkbox-inline{margin-top:0;margin-left:10px}input[type="radio"][disabled],input[type="checkbox"][disabled],input[type="radio"].disabled,input[type="checkbox"].disabled,fieldset[disabled] input[type="radio"],fieldset[disabled] input[type="checkbox"]{cursor:not-allowed}.radio-inline.disabled,.checkbox-inline.disabled,fieldset[disabled] .radio-inline,fieldset[disabled] .checkbox-inline{cursor:not-allowed}.radio.disabled label,.checkbox.disabled label,fieldset[disabled] .radio label,fieldset[disabled] .checkbox label{cursor:not-allowed}.form-control-static{padding-top:7px;padding-bottom:7px;margin-bottom:0;min-height:34px}.form-control-static.input-lg,.form-control-static.input-sm{padding-left:0;padding-right:0}.input-sm{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-sm{height:30px;line-height:30px}textarea.input-sm,select[multiple].input-sm{height:auto}.form-group-sm .form-control{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.form-group-sm select.form-control{height:30px;line-height:30px}.form-group-sm textarea.form-control,.form-group-sm select[multiple].form-control{height:auto}.form-group-sm .form-control-static{height:30px;min-height:32px;padding:6px 10px;font-size:12px;line-height:1.5}.input-lg{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}select.input-lg{height:46px;line-height:46px}textarea.input-lg,select[multiple].input-lg{height:auto}.form-group-lg .form-control{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}.form-group-lg select.form-control{height:46px;line-height:46px}.form-group-lg textarea.form-control,.form-group-lg select[multiple].form-control{height:auto}.form-group-lg .form-control-static{height:46px;min-height:38px;padding:11px 16px;font-size:18px;line-height:1.3333333}.has-feedback{position:relative}.has-feedback .form-control{padding-right:42.5px}.form-control-feedback{position:absolute;top:0;right:0;z-index:2;display:block;width:34px;height:34px;line-height:34px;text-align:center;pointer-events:none}.input-lg+.form-control-feedback,.input-group-lg+.form-control-feedback,.form-group-lg .form-control+.form-control-feedback{width:46px;height:46px;line-height:46px}.input-sm+.form-control-feedback,.input-group-sm+.form-control-feedback,.form-group-sm .form-control+.form-control-feedback{width:30px;height:30px;line-height:30px}.has-success .help-block,.has-success .control-label,.has-success .radio,.has-success .checkbox,.has-success .radio-inline,.has-success .checkbox-inline,.has-success.radio label,.has-success.checkbox label,.has-success.radio-inline label,.has-success.checkbox-inline label{color:#3c763d}.has-success .form-control{border-color:#3c763d;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.has-success .form-control:focus{border-color:#2b542c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #67b168;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #67b168}.has-success .input-group-addon{color:#3c763d;border-color:#3c763d;background-color:#dff0d8}.has-success .form-control-feedback{color:#3c763d}.has-warning .help-block,.has-warning .control-label,.has-warning .radio,.has-warning .checkbox,.has-warning .radio-inline,.has-warning .checkbox-inline,.has-warning.radio label,.has-warning.checkbox label,.has-warning.radio-inline label,.has-warning.checkbox-inline label{color:#8a6d3b}.has-warning .form-control{border-color:#8a6d3b;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.has-warning .form-control:focus{border-color:#66512c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #c0a16b;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #c0a16b}.has-warning .input-group-addon{color:#8a6d3b;border-color:#8a6d3b;background-color:#fcf8e3}.has-warning .form-control-feedback{color:#8a6d3b}.has-error .help-block,.has-error .control-label,.has-error .radio,.has-error .checkbox,.has-error .radio-inline,.has-error .checkbox-inline,.has-error.radio label,.has-error.checkbox label,.has-error.radio-inline label,.has-error.checkbox-inline label{color:#a94442}.has-error .form-control{border-color:#a94442;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.has-error .form-control:focus{border-color:#843534;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #ce8483;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #ce8483}.has-error .input-group-addon{color:#a94442;border-color:#a94442;background-color:#f2dede}.has-error .form-control-feedback{color:#a94442}.has-feedback label~.form-control-feedback{top:25px}.has-feedback label.sr-only~.form-control-feedback{top:0}.help-block{display:block;margin-top:5px;margin-bottom:10px;color:#737373}@media (min-width:768px){.form-inline .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.form-inline .form-control{display:inline-block;width:auto;vertical-align:middle}.form-inline .form-control-static{display:inline-block}.form-inline .input-group{display:inline-table;vertical-align:middle}.form-inline .input-group .input-group-addon,.form-inline .input-group .input-group-btn,.form-inline .input-group .form-control{width:auto}.form-inline .input-group>.form-control{width:100%}.form-inline .control-label{margin-bottom:0;vertical-align:middle}.form-inline .radio,.form-inline .checkbox{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.form-inline .radio label,.form-inline .checkbox label{padding-left:0}.form-inline .radio input[type="radio"],.form-inline .checkbox input[type="checkbox"]{position:relative;margin-left:0}.form-inline .has-feedback .form-control-feedback{top:0}}.form-horizontal .radio,.form-horizontal .checkbox,.form-horizontal .radio-inline,.form-horizontal .checkbox-inline{margin-top:0;margin-bottom:0;padding-top:7px}.form-horizontal .radio,.form-horizontal .checkbox{min-height:27px}.form-horizontal .form-group{margin-left:-15px;margin-right:-15px}@media (min-width:768px){.form-horizontal .control-label{text-align:right;margin-bottom:0;padding-top:7px}}.form-horizontal .has-feedback .form-control-feedback{right:15px}@media (min-width:768px){.form-horizontal .form-group-lg .control-label{padding-top:11px;font-size:18px}}@media (min-width:768px){.form-horizontal .form-group-sm .control-label{padding-top:6px;font-size:12px}}.btn{display:inline-block;margin-bottom:0;font-weight:normal;text-align:center;vertical-align:middle;-ms-touch-action:manipulation;touch-action:manipulation;cursor:pointer;background-image:none;border:1px solid transparent;white-space:nowrap;padding:6px 12px;font-size:14px;line-height:1.42857143;border-radius:4px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.btn:focus,.btn:active:focus,.btn.active:focus,.btn.focus,.btn:active.focus,.btn.active.focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.btn:hover,.btn:focus,.btn.focus{color:#333;text-decoration:none}.btn:active,.btn.active{outline:0;background-image:none;-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,0.125);box-shadow:inset 0 3px 5px rgba(0,0,0,0.125)}.btn.disabled,.btn[disabled],fieldset[disabled] .btn{cursor:not-allowed;opacity:.65;filter:alpha(opacity=65);-webkit-box-shadow:none;box-shadow:none}a.btn.disabled,fieldset[disabled] a.btn{pointer-events:none}.btn-default{color:#333;background-color:#fff;border-color:#ccc}.btn-default:focus,.btn-default.focus{color:#333;background-color:#e6e6e6;border-color:#8c8c8c}.btn-default:hover{color:#333;background-color:#e6e6e6;border-color:#adadad}.btn-default:active,.btn-default.active,.open>.dropdown-toggle.btn-default{color:#333;background-color:#e6e6e6;border-color:#adadad}.btn-default:active:hover,.btn-default.active:hover,.open>.dropdown-toggle.btn-default:hover,.btn-default:active:focus,.btn-default.active:focus,.open>.dropdown-toggle.btn-default:focus,.btn-default:active.focus,.btn-default.active.focus,.open>.dropdown-toggle.btn-default.focus{color:#333;background-color:#d4d4d4;border-color:#8c8c8c}.btn-default:active,.btn-default.active,.open>.dropdown-toggle.btn-default{background-image:none}.btn-default.disabled:hover,.btn-default[disabled]:hover,fieldset[disabled] .btn-default:hover,.btn-default.disabled:focus,.btn-default[disabled]:focus,fieldset[disabled] .btn-default:focus,.btn-default.disabled.focus,.btn-default[disabled].focus,fieldset[disabled] .btn-default.focus{background-color:#fff;border-color:#ccc}.btn-default .badge{color:#fff;background-color:#333}.btn-primary{color:#fff;background-color:#337ab7;border-color:#2e6da4}.btn-primary:focus,.btn-primary.focus{color:#fff;background-color:#286090;border-color:#122b40}.btn-primary:hover{color:#fff;background-color:#286090;border-color:#204d74}.btn-primary:active,.btn-primary.active,.open>.dropdown-toggle.btn-primary{color:#fff;background-color:#286090;border-color:#204d74}.btn-primary:active:hover,.btn-primary.active:hover,.open>.dropdown-toggle.btn-primary:hover,.btn-primary:active:focus,.btn-primary.active:focus,.open>.dropdown-toggle.btn-primary:focus,.btn-primary:active.focus,.btn-primary.active.focus,.open>.dropdown-toggle.btn-primary.focus{color:#fff;background-color:#204d74;border-color:#122b40}.btn-primary:active,.btn-primary.active,.open>.dropdown-toggle.btn-primary{background-image:none}.btn-primary.disabled:hover,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary:hover,.btn-primary.disabled:focus,.btn-primary[disabled]:focus,fieldset[disabled] .btn-primary:focus,.btn-primary.disabled.focus,.btn-primary[disabled].focus,fieldset[disabled] .btn-primary.focus{background-color:#337ab7;border-color:#2e6da4}.btn-primary .badge{color:#337ab7;background-color:#fff}.btn-success{color:#fff;background-color:#5cb85c;border-color:#4cae4c}.btn-success:focus,.btn-success.focus{color:#fff;background-color:#449d44;border-color:#255625}.btn-success:hover{color:#fff;background-color:#449d44;border-color:#398439}.btn-success:active,.btn-success.active,.open>.dropdown-toggle.btn-success{color:#fff;background-color:#449d44;border-color:#398439}.btn-success:active:hover,.btn-success.active:hover,.open>.dropdown-toggle.btn-success:hover,.btn-success:active:focus,.btn-success.active:focus,.open>.dropdown-toggle.btn-success:focus,.btn-success:active.focus,.btn-success.active.focus,.open>.dropdown-toggle.btn-success.focus{color:#fff;background-color:#398439;border-color:#255625}.btn-success:active,.btn-success.active,.open>.dropdown-toggle.btn-success{background-image:none}.btn-success.disabled:hover,.btn-success[disabled]:hover,fieldset[disabled] .btn-success:hover,.btn-success.disabled:focus,.btn-success[disabled]:focus,fieldset[disabled] .btn-success:focus,.btn-success.disabled.focus,.btn-success[disabled].focus,fieldset[disabled] .btn-success.focus{background-color:#5cb85c;border-color:#4cae4c}.btn-success .badge{color:#5cb85c;background-color:#fff}.btn-info{color:#fff;background-color:#5bc0de;border-color:#46b8da}.btn-info:focus,.btn-info.focus{color:#fff;background-color:#31b0d5;border-color:#1b6d85}.btn-info:hover{color:#fff;background-color:#31b0d5;border-color:#269abc}.btn-info:active,.btn-info.active,.open>.dropdown-toggle.btn-info{color:#fff;background-color:#31b0d5;border-color:#269abc}.btn-info:active:hover,.btn-info.active:hover,.open>.dropdown-toggle.btn-info:hover,.btn-info:active:focus,.btn-info.active:focus,.open>.dropdown-toggle.btn-info:focus,.btn-info:active.focus,.btn-info.active.focus,.open>.dropdown-toggle.btn-info.focus{color:#fff;background-color:#269abc;border-color:#1b6d85}.btn-info:active,.btn-info.active,.open>.dropdown-toggle.btn-info{background-image:none}.btn-info.disabled:hover,.btn-info[disabled]:hover,fieldset[disabled] .btn-info:hover,.btn-info.disabled:focus,.btn-info[disabled]:focus,fieldset[disabled] .btn-info:focus,.btn-info.disabled.focus,.btn-info[disabled].focus,fieldset[disabled] .btn-info.focus{background-color:#5bc0de;border-color:#46b8da}.btn-info .badge{color:#5bc0de;background-color:#fff}.btn-warning{color:#fff;background-color:#f0ad4e;border-color:#eea236}.btn-warning:focus,.btn-warning.focus{color:#fff;background-color:#ec971f;border-color:#985f0d}.btn-warning:hover{color:#fff;background-color:#ec971f;border-color:#d58512}.btn-warning:active,.btn-warning.active,.open>.dropdown-toggle.btn-warning{color:#fff;background-color:#ec971f;border-color:#d58512}.btn-warning:active:hover,.btn-warning.active:hover,.open>.dropdown-toggle.btn-warning:hover,.btn-warning:active:focus,.btn-warning.active:focus,.open>.dropdown-toggle.btn-warning:focus,.btn-warning:active.focus,.btn-warning.active.focus,.open>.dropdown-toggle.btn-warning.focus{color:#fff;background-color:#d58512;border-color:#985f0d}.btn-warning:active,.btn-warning.active,.open>.dropdown-toggle.btn-warning{background-image:none}.btn-warning.disabled:hover,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning:hover,.btn-warning.disabled:focus,.btn-warning[disabled]:focus,fieldset[disabled] .btn-warning:focus,.btn-warning.disabled.focus,.btn-warning[disabled].focus,fieldset[disabled] .btn-warning.focus{background-color:#f0ad4e;border-color:#eea236}.btn-warning .badge{color:#f0ad4e;background-color:#fff}.btn-danger{color:#fff;background-color:#d9534f;border-color:#d43f3a}.btn-danger:focus,.btn-danger.focus{color:#fff;background-color:#c9302c;border-color:#761c19}.btn-danger:hover{color:#fff;background-color:#c9302c;border-color:#ac2925}.btn-danger:active,.btn-danger.active,.open>.dropdown-toggle.btn-danger{color:#fff;background-color:#c9302c;border-color:#ac2925}.btn-danger:active:hover,.btn-danger.active:hover,.open>.dropdown-toggle.btn-danger:hover,.btn-danger:active:focus,.btn-danger.active:focus,.open>.dropdown-toggle.btn-danger:focus,.btn-danger:active.focus,.btn-danger.active.focus,.open>.dropdown-toggle.btn-danger.focus{color:#fff;background-color:#ac2925;border-color:#761c19}.btn-danger:active,.btn-danger.active,.open>.dropdown-toggle.btn-danger{background-image:none}.btn-danger.disabled:hover,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger:hover,.btn-danger.disabled:focus,.btn-danger[disabled]:focus,fieldset[disabled] .btn-danger:focus,.btn-danger.disabled.focus,.btn-danger[disabled].focus,fieldset[disabled] .btn-danger.focus{background-color:#d9534f;border-color:#d43f3a}.btn-danger .badge{color:#d9534f;background-color:#fff}.btn-link{color:#337ab7;font-weight:normal;border-radius:0}.btn-link,.btn-link:active,.btn-link.active,.btn-link[disabled],fieldset[disabled] .btn-link{background-color:transparent;-webkit-box-shadow:none;box-shadow:none}.btn-link,.btn-link:hover,.btn-link:focus,.btn-link:active{border-color:transparent}.btn-link:hover,.btn-link:focus{color:#23527c;text-decoration:underline;background-color:transparent}.btn-link[disabled]:hover,fieldset[disabled] .btn-link:hover,.btn-link[disabled]:focus,fieldset[disabled] .btn-link:focus{color:#777;text-decoration:none}.btn-lg,.btn-group-lg>.btn{padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}.btn-sm,.btn-group-sm>.btn{padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.btn-xs,.btn-group-xs>.btn{padding:1px 5px;font-size:12px;line-height:1.5;border-radius:3px}.btn-block{display:block;width:100%}.btn-block+.btn-block{margin-top:5px}input[type="submit"].btn-block,input[type="reset"].btn-block,input[type="button"].btn-block{width:100%}.fade{opacity:0;-webkit-transition:opacity .15s linear;-o-transition:opacity .15s linear;transition:opacity .15s linear}.fade.in{opacity:1}.collapse{display:none}.collapse.in{display:block}tr.collapse.in{display:table-row}tbody.collapse.in{display:table-row-group}.collapsing{position:relative;height:0;overflow:hidden;-webkit-transition-property:height, visibility;-o-transition-property:height, visibility;transition-property:height, visibility;-webkit-transition-duration:.35s;-o-transition-duration:.35s;transition-duration:.35s;-webkit-transition-timing-function:ease;-o-transition-timing-function:ease;transition-timing-function:ease}.caret{display:inline-block;width:0;height:0;margin-left:2px;vertical-align:middle;border-top:4px dashed;border-top:4px solid \9;border-right:4px solid transparent;border-left:4px solid transparent}.dropup,.dropdown{position:relative}.dropdown-toggle:focus{outline:0}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:160px;padding:5px 0;margin:2px 0 0;list-style:none;font-size:14px;text-align:left;background-color:#fff;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.15);border-radius:4px;-webkit-box-shadow:0 6px 12px rgba(0,0,0,0.175);box-shadow:0 6px 12px rgba(0,0,0,0.175);-webkit-background-clip:padding-box;background-clip:padding-box}.dropdown-menu.pull-right{right:0;left:auto}.dropdown-menu .divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.dropdown-menu>li>a{display:block;padding:3px 20px;clear:both;font-weight:normal;line-height:1.42857143;color:#333;white-space:nowrap}.dropdown-menu>li>a:hover,.dropdown-menu>li>a:focus{text-decoration:none;color:#262626;background-color:#f5f7f8}.dropdown-menu>.active>a,.dropdown-menu>.active>a:hover,.dropdown-menu>.active>a:focus{color:#fff;text-decoration:none;outline:0;background-color:#337ab7}.dropdown-menu>.disabled>a,.dropdown-menu>.disabled>a:hover,.dropdown-menu>.disabled>a:focus{color:#777}.dropdown-menu>.disabled>a:hover,.dropdown-menu>.disabled>a:focus{text-decoration:none;background-color:transparent;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);cursor:not-allowed}.open>.dropdown-menu{display:block}.open>a{outline:0}.dropdown-menu-right{left:auto;right:0}.dropdown-menu-left{left:0;right:auto}.dropdown-header{display:block;padding:3px 20px;font-size:12px;line-height:1.42857143;color:#777;white-space:nowrap}.dropdown-backdrop{position:fixed;left:0;right:0;bottom:0;top:0;z-index:990}.pull-right>.dropdown-menu{right:0;left:auto}.dropup .caret,.navbar-fixed-bottom .dropdown .caret{border-top:0;border-bottom:4px dashed;border-bottom:4px solid \9;content:""}.dropup .dropdown-menu,.navbar-fixed-bottom .dropdown .dropdown-menu{top:auto;bottom:100%;margin-bottom:2px}@media (min-width:768px){.navbar-right .dropdown-menu{left:auto;right:0}.navbar-right .dropdown-menu-left{left:0;right:auto}}.btn-group,.btn-group-vertical{position:relative;display:inline-block;vertical-align:middle}.btn-group>.btn,.btn-group-vertical>.btn{position:relative;float:left}.btn-group>.btn:hover,.btn-group-vertical>.btn:hover,.btn-group>.btn:focus,.btn-group-vertical>.btn:focus,.btn-group>.btn:active,.btn-group-vertical>.btn:active,.btn-group>.btn.active,.btn-group-vertical>.btn.active{z-index:2}.btn-group .btn+.btn,.btn-group .btn+.btn-group,.btn-group .btn-group+.btn,.btn-group .btn-group+.btn-group{margin-left:-1px}.btn-toolbar{margin-left:-5px}.btn-toolbar .btn,.btn-toolbar .btn-group,.btn-toolbar .input-group{float:left}.btn-toolbar>.btn,.btn-toolbar>.btn-group,.btn-toolbar>.input-group{margin-left:5px}.btn-group>.btn:not(:first-child):not(:last-child):not(.dropdown-toggle){border-radius:0}.btn-group>.btn:first-child{margin-left:0}.btn-group>.btn:first-child:not(:last-child):not(.dropdown-toggle){border-bottom-right-radius:0;border-top-right-radius:0}.btn-group>.btn:last-child:not(:first-child),.btn-group>.dropdown-toggle:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0}.btn-group>.btn-group{float:left}.btn-group>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-bottom-right-radius:0;border-top-right-radius:0}.btn-group>.btn-group:last-child:not(:first-child)>.btn:first-child{border-bottom-left-radius:0;border-top-left-radius:0}.btn-group .dropdown-toggle:active,.btn-group.open .dropdown-toggle{outline:0}.btn-group>.btn+.dropdown-toggle{padding-left:8px;padding-right:8px}.btn-group>.btn-lg+.dropdown-toggle{padding-left:12px;padding-right:12px}.btn-group.open .dropdown-toggle{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,0.125);box-shadow:inset 0 3px 5px rgba(0,0,0,0.125)}.btn-group.open .dropdown-toggle.btn-link{-webkit-box-shadow:none;box-shadow:none}.btn .caret{margin-left:0}.btn-lg .caret{border-width:5px 5px 0;border-bottom-width:0}.dropup .btn-lg .caret{border-width:0 5px 5px}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group,.btn-group-vertical>.btn-group>.btn{display:block;float:none;width:100%;max-width:100%}.btn-group-vertical>.btn-group>.btn{float:none}.btn-group-vertical>.btn+.btn,.btn-group-vertical>.btn+.btn-group,.btn-group-vertical>.btn-group+.btn,.btn-group-vertical>.btn-group+.btn-group{margin-top:-1px;margin-left:0}.btn-group-vertical>.btn:not(:first-child):not(:last-child){border-radius:0}.btn-group-vertical>.btn:first-child:not(:last-child){border-top-right-radius:4px;border-top-left-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn:last-child:not(:first-child){border-top-right-radius:0;border-top-left-radius:0;border-bottom-right-radius:4px;border-bottom-left-radius:4px}.btn-group-vertical>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group-vertical>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group-vertical>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn-group:last-child:not(:first-child)>.btn:first-child{border-top-right-radius:0;border-top-left-radius:0}.btn-group-justified{display:table;width:100%;table-layout:fixed;border-collapse:separate}.btn-group-justified>.btn,.btn-group-justified>.btn-group{float:none;display:table-cell;width:1%}.btn-group-justified>.btn-group .btn{width:100%}.btn-group-justified>.btn-group .dropdown-menu{left:auto}[data-toggle="buttons"]>.btn input[type="radio"],[data-toggle="buttons"]>.btn-group>.btn input[type="radio"],[data-toggle="buttons"]>.btn input[type="checkbox"],[data-toggle="buttons"]>.btn-group>.btn input[type="checkbox"]{position:absolute;clip:rect(0, 0, 0, 0);pointer-events:none}.input-group{position:relative;display:table;border-collapse:separate}.input-group[class*="col-"]{float:none;padding-left:0;padding-right:0}.input-group .form-control{position:relative;z-index:2;float:left;width:100%;margin-bottom:0}.input-group .form-control:focus{z-index:3}.input-group-lg>.form-control,.input-group-lg>.input-group-addon,.input-group-lg>.input-group-btn>.btn{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}select.input-group-lg>.form-control,select.input-group-lg>.input-group-addon,select.input-group-lg>.input-group-btn>.btn{height:46px;line-height:46px}textarea.input-group-lg>.form-control,textarea.input-group-lg>.input-group-addon,textarea.input-group-lg>.input-group-btn>.btn,select[multiple].input-group-lg>.form-control,select[multiple].input-group-lg>.input-group-addon,select[multiple].input-group-lg>.input-group-btn>.btn{height:auto}.input-group-sm>.form-control,.input-group-sm>.input-group-addon,.input-group-sm>.input-group-btn>.btn{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-group-sm>.form-control,select.input-group-sm>.input-group-addon,select.input-group-sm>.input-group-btn>.btn{height:30px;line-height:30px}textarea.input-group-sm>.form-control,textarea.input-group-sm>.input-group-addon,textarea.input-group-sm>.input-group-btn>.btn,select[multiple].input-group-sm>.form-control,select[multiple].input-group-sm>.input-group-addon,select[multiple].input-group-sm>.input-group-btn>.btn{height:auto}.input-group-addon,.input-group-btn,.input-group .form-control{display:table-cell}.input-group-addon:not(:first-child):not(:last-child),.input-group-btn:not(:first-child):not(:last-child),.input-group .form-control:not(:first-child):not(:last-child){border-radius:0}.input-group-addon,.input-group-btn{width:1%;white-space:nowrap;vertical-align:middle}.input-group-addon{padding:6px 12px;font-size:14px;font-weight:normal;line-height:1;color:#555;text-align:center;background-color:#eee;border:1px solid #ccc;border-radius:4px}.input-group-addon.input-sm{padding:5px 10px;font-size:12px;border-radius:3px}.input-group-addon.input-lg{padding:10px 16px;font-size:18px;border-radius:6px}.input-group-addon input[type="radio"],.input-group-addon input[type="checkbox"]{margin-top:0}.input-group .form-control:first-child,.input-group-addon:first-child,.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group>.btn,.input-group-btn:first-child>.dropdown-toggle,.input-group-btn:last-child>.btn:not(:last-child):not(.dropdown-toggle),.input-group-btn:last-child>.btn-group:not(:last-child)>.btn{border-bottom-right-radius:0;border-top-right-radius:0}.input-group-addon:first-child{border-right:0}.input-group .form-control:last-child,.input-group-addon:last-child,.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group>.btn,.input-group-btn:last-child>.dropdown-toggle,.input-group-btn:first-child>.btn:not(:first-child),.input-group-btn:first-child>.btn-group:not(:first-child)>.btn{border-bottom-left-radius:0;border-top-left-radius:0}.input-group-addon:last-child{border-left:0}.input-group-btn{position:relative;font-size:0;white-space:nowrap}.input-group-btn>.btn{position:relative}.input-group-btn>.btn+.btn{margin-left:-1px}.input-group-btn>.btn:hover,.input-group-btn>.btn:focus,.input-group-btn>.btn:active{z-index:2}.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group{margin-right:-1px}.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group{z-index:2;margin-left:-1px}.nav{margin-bottom:0;padding-left:0;list-style:none}.nav>li{position:relative;display:block}.nav>li>a{position:relative;display:block;padding:10px 15px}.nav>li>a:hover,.nav>li>a:focus{text-decoration:none;background-color:#eee}.nav>li.disabled>a{color:#777}.nav>li.disabled>a:hover,.nav>li.disabled>a:focus{color:#777;text-decoration:none;background-color:transparent;cursor:not-allowed}.nav .open>a,.nav .open>a:hover,.nav .open>a:focus{background-color:#eee;border-color:#337ab7}.nav .nav-divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.nav>li>a>img{max-width:none}.nav-tabs{border-bottom:1px solid #ddd}.nav-tabs>li{float:left;margin-bottom:-1px}.nav-tabs>li>a{margin-right:2px;line-height:1.42857143;border:1px solid transparent;border-radius:4px 4px 0 0}.nav-tabs>li>a:hover{border-color:#eee #eee #ddd}.nav-tabs>li.active>a,.nav-tabs>li.active>a:hover,.nav-tabs>li.active>a:focus{color:#555;background-color:#fff;border:1px solid #ddd;border-bottom-color:transparent;cursor:default}.nav-tabs.nav-justified{width:100%;border-bottom:0}.nav-tabs.nav-justified>li{float:none}.nav-tabs.nav-justified>li>a{text-align:center;margin-bottom:5px}.nav-tabs.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-tabs.nav-justified>li{display:table-cell;width:1%}.nav-tabs.nav-justified>li>a{margin-bottom:0}}.nav-tabs.nav-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:hover,.nav-tabs.nav-justified>.active>a:focus{border:1px solid #ddd}@media (min-width:768px){.nav-tabs.nav-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:hover,.nav-tabs.nav-justified>.active>a:focus{border-bottom-color:#fff}}.nav-pills>li{float:left}.nav-pills>li>a{border-radius:4px}.nav-pills>li+li{margin-left:2px}.nav-pills>li.active>a,.nav-pills>li.active>a:hover,.nav-pills>li.active>a:focus{color:#fff;background-color:#337ab7}.nav-stacked>li{float:none}.nav-stacked>li+li{margin-top:2px;margin-left:0}.nav-justified{width:100%}.nav-justified>li{float:none}.nav-justified>li>a{text-align:center;margin-bottom:5px}.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-justified>li{display:table-cell;width:1%}.nav-justified>li>a{margin-bottom:0}}.nav-tabs-justified{border-bottom:0}.nav-tabs-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:hover,.nav-tabs-justified>.active>a:focus{border:1px solid #ddd}@media (min-width:768px){.nav-tabs-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:hover,.nav-tabs-justified>.active>a:focus{border-bottom-color:#fff}}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-right-radius:0;border-top-left-radius:0}.navbar{position:relative;min-height:50px;margin-bottom:20px;border:1px solid transparent}@media (min-width:768px){.navbar{border-radius:4px}}@media (min-width:768px){.navbar-header{float:left}}.navbar-collapse{overflow-x:visible;padding-right:15px;padding-left:15px;border-top:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.1);box-shadow:inset 0 1px 0 rgba(255,255,255,0.1);-webkit-overflow-scrolling:touch}.navbar-collapse.in{overflow-y:auto}@media (min-width:768px){.navbar-collapse{width:auto;border-top:0;-webkit-box-shadow:none;box-shadow:none}.navbar-collapse.collapse{display:block !important;height:auto !important;padding-bottom:0;overflow:visible !important}.navbar-collapse.in{overflow-y:visible}.navbar-fixed-top .navbar-collapse,.navbar-static-top .navbar-collapse,.navbar-fixed-bottom .navbar-collapse{padding-left:0;padding-right:0}}.navbar-fixed-top .navbar-collapse,.navbar-fixed-bottom .navbar-collapse{max-height:340px}@media (max-device-width:480px) and (orientation:landscape){.navbar-fixed-top .navbar-collapse,.navbar-fixed-bottom .navbar-collapse{max-height:200px}}.container>.navbar-header,.container-fluid>.navbar-header,.container>.navbar-collapse,.container-fluid>.navbar-collapse{margin-right:-15px;margin-left:-15px}@media (min-width:768px){.container>.navbar-header,.container-fluid>.navbar-header,.container>.navbar-collapse,.container-fluid>.navbar-collapse{margin-right:0;margin-left:0}}.navbar-static-top{z-index:1000;border-width:0 0 1px}@media (min-width:768px){.navbar-static-top{border-radius:0}}.navbar-fixed-top,.navbar-fixed-bottom{position:fixed;right:0;left:0;z-index:1030}@media (min-width:768px){.navbar-fixed-top,.navbar-fixed-bottom{border-radius:0}}.navbar-fixed-top{top:0;border-width:0 0 1px}.navbar-fixed-bottom{bottom:0;margin-bottom:0;border-width:1px 0 0}.navbar-brand{float:left;padding:15px 15px;font-size:18px;line-height:20px;height:50px}.navbar-brand:hover,.navbar-brand:focus{text-decoration:none}.navbar-brand>img{display:block}@media (min-width:768px){.navbar>.container .navbar-brand,.navbar>.container-fluid .navbar-brand{margin-left:-15px}}.navbar-toggle{position:relative;float:right;margin-right:15px;padding:9px 10px;margin-top:8px;margin-bottom:8px;background-color:transparent;background-image:none;border:1px solid transparent;border-radius:4px}.navbar-toggle:focus{outline:0}.navbar-toggle .icon-bar{display:block;width:22px;height:2px;border-radius:1px}.navbar-toggle .icon-bar+.icon-bar{margin-top:4px}@media (min-width:768px){.navbar-toggle{display:none}}.navbar-nav{margin:7.5px -15px}.navbar-nav>li>a{padding-top:10px;padding-bottom:10px;line-height:20px}@media (max-width:767px){.navbar-nav .open .dropdown-menu{position:static;float:none;width:auto;margin-top:0;background-color:transparent;border:0;-webkit-box-shadow:none;box-shadow:none}.navbar-nav .open .dropdown-menu>li>a,.navbar-nav .open .dropdown-menu .dropdown-header{padding:5px 15px 5px 25px}.navbar-nav .open .dropdown-menu>li>a{line-height:20px}.navbar-nav .open .dropdown-menu>li>a:hover,.navbar-nav .open .dropdown-menu>li>a:focus{background-image:none}}@media (min-width:768px){.navbar-nav{float:left;margin:0}.navbar-nav>li{float:left}.navbar-nav>li>a{padding-top:15px;padding-bottom:15px}}.navbar-form{margin-left:-15px;margin-right:-15px;padding:10px 15px;border-top:1px solid transparent;border-bottom:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.1);box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.1);margin-top:8px;margin-bottom:8px}@media (min-width:768px){.navbar-form .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.navbar-form .form-control{display:inline-block;width:auto;vertical-align:middle}.navbar-form .form-control-static{display:inline-block}.navbar-form .input-group{display:inline-table;vertical-align:middle}.navbar-form .input-group .input-group-addon,.navbar-form .input-group .input-group-btn,.navbar-form .input-group .form-control{width:auto}.navbar-form .input-group>.form-control{width:100%}.navbar-form .control-label{margin-bottom:0;vertical-align:middle}.navbar-form .radio,.navbar-form .checkbox{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.navbar-form .radio label,.navbar-form .checkbox label{padding-left:0}.navbar-form .radio input[type="radio"],.navbar-form .checkbox input[type="checkbox"]{position:relative;margin-left:0}.navbar-form .has-feedback .form-control-feedback{top:0}}@media (max-width:767px){.navbar-form .form-group{margin-bottom:5px}.navbar-form .form-group:last-child{margin-bottom:0}}@media (min-width:768px){.navbar-form{width:auto;border:0;margin-left:0;margin-right:0;padding-top:0;padding-bottom:0;-webkit-box-shadow:none;box-shadow:none}}.navbar-nav>li>.dropdown-menu{margin-top:0;border-top-right-radius:0;border-top-left-radius:0}.navbar-fixed-bottom .navbar-nav>li>.dropdown-menu{margin-bottom:0;border-top-right-radius:4px;border-top-left-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.navbar-btn{margin-top:8px;margin-bottom:8px}.navbar-btn.btn-sm{margin-top:10px;margin-bottom:10px}.navbar-btn.btn-xs{margin-top:14px;margin-bottom:14px}.navbar-text{margin-top:15px;margin-bottom:15px}@media (min-width:768px){.navbar-text{float:left;margin-left:15px;margin-right:15px}}@media (min-width:768px){.navbar-left{float:left !important}.navbar-right{float:right !important;margin-right:-15px}.navbar-right~.navbar-right{margin-right:0}}.navbar-default{background-color:#f5f7f8;border-color:#e2e7ea}.navbar-default .navbar-brand{color:#777}.navbar-default .navbar-brand:hover,.navbar-default .navbar-brand:focus{color:#5e5e5e;background-color:transparent}.navbar-default .navbar-text{color:#777}.navbar-default .navbar-nav>li>a{color:#777}.navbar-default .navbar-nav>li>a:hover,.navbar-default .navbar-nav>li>a:focus{color:#333;background-color:transparent}.navbar-default .navbar-nav>.active>a,.navbar-default .navbar-nav>.active>a:hover,.navbar-default .navbar-nav>.active>a:focus{color:#555;background-color:#e2e7ea}.navbar-default .navbar-nav>.disabled>a,.navbar-default .navbar-nav>.disabled>a:hover,.navbar-default .navbar-nav>.disabled>a:focus{color:#ccc;background-color:transparent}.navbar-default .navbar-toggle{border-color:#ddd}.navbar-default .navbar-toggle:hover,.navbar-default .navbar-toggle:focus{background-color:#ddd}.navbar-default .navbar-toggle .icon-bar{background-color:#888}.navbar-default .navbar-collapse,.navbar-default .navbar-form{border-color:#e2e7ea}.navbar-default .navbar-nav>.open>a,.navbar-default .navbar-nav>.open>a:hover,.navbar-default .navbar-nav>.open>a:focus{background-color:#e2e7ea;color:#555}@media (max-width:767px){.navbar-default .navbar-nav .open .dropdown-menu>li>a{color:#777}.navbar-default .navbar-nav .open .dropdown-menu>li>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>li>a:focus{color:#333;background-color:transparent}.navbar-default .navbar-nav .open .dropdown-menu>.active>a,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:focus{color:#555;background-color:#e2e7ea}.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:focus{color:#ccc;background-color:transparent}}.navbar-default .navbar-link{color:#777}.navbar-default .navbar-link:hover{color:#333}.navbar-default .btn-link{color:#777}.navbar-default .btn-link:hover,.navbar-default .btn-link:focus{color:#333}.navbar-default .btn-link[disabled]:hover,fieldset[disabled] .navbar-default .btn-link:hover,.navbar-default .btn-link[disabled]:focus,fieldset[disabled] .navbar-default .btn-link:focus{color:#ccc}.navbar-inverse{background-color:#222;border-color:#080808}.navbar-inverse .navbar-brand{color:#9d9d9d}.navbar-inverse .navbar-brand:hover,.navbar-inverse .navbar-brand:focus{color:#fff;background-color:transparent}.navbar-inverse .navbar-text{color:#9d9d9d}.navbar-inverse .navbar-nav>li>a{color:#9d9d9d}.navbar-inverse .navbar-nav>li>a:hover,.navbar-inverse .navbar-nav>li>a:focus{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav>.active>a,.navbar-inverse .navbar-nav>.active>a:hover,.navbar-inverse .navbar-nav>.active>a:focus{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav>.disabled>a,.navbar-inverse .navbar-nav>.disabled>a:hover,.navbar-inverse .navbar-nav>.disabled>a:focus{color:#444;background-color:transparent}.navbar-inverse .navbar-toggle{border-color:#333}.navbar-inverse .navbar-toggle:hover,.navbar-inverse .navbar-toggle:focus{background-color:#333}.navbar-inverse .navbar-toggle .icon-bar{background-color:#fff}.navbar-inverse .navbar-collapse,.navbar-inverse .navbar-form{border-color:#101010}.navbar-inverse .navbar-nav>.open>a,.navbar-inverse .navbar-nav>.open>a:hover,.navbar-inverse .navbar-nav>.open>a:focus{background-color:#080808;color:#fff}@media (max-width:767px){.navbar-inverse .navbar-nav .open .dropdown-menu>.dropdown-header{border-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu .divider{background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a{color:#9d9d9d}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:focus{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:focus{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:focus{color:#444;background-color:transparent}}.navbar-inverse .navbar-link{color:#9d9d9d}.navbar-inverse .navbar-link:hover{color:#fff}.navbar-inverse .btn-link{color:#9d9d9d}.navbar-inverse .btn-link:hover,.navbar-inverse .btn-link:focus{color:#fff}.navbar-inverse .btn-link[disabled]:hover,fieldset[disabled] .navbar-inverse .btn-link:hover,.navbar-inverse .btn-link[disabled]:focus,fieldset[disabled] .navbar-inverse .btn-link:focus{color:#444}.breadcrumb{padding:8px 15px;margin-bottom:20px;list-style:none;background-color:#f5f7f8;border-radius:4px}.breadcrumb>li{display:inline-block}.breadcrumb>li+li:before{content:"/\00a0";padding:0 5px;color:#ccc}.breadcrumb>.active{color:#777}.pagination{display:inline-block;padding-left:0;margin:20px 0;border-radius:4px}.pagination>li{display:inline}.pagination>li>a,.pagination>li>span{position:relative;float:left;padding:6px 12px;line-height:1.42857143;text-decoration:none;color:#337ab7;background-color:#fff;border:1px solid #ddd;margin-left:-1px}.pagination>li:first-child>a,.pagination>li:first-child>span{margin-left:0;border-bottom-left-radius:4px;border-top-left-radius:4px}.pagination>li:last-child>a,.pagination>li:last-child>span{border-bottom-right-radius:4px;border-top-right-radius:4px}.pagination>li>a:hover,.pagination>li>span:hover,.pagination>li>a:focus,.pagination>li>span:focus{z-index:2;color:#23527c;background-color:#eee;border-color:#ddd}.pagination>.active>a,.pagination>.active>span,.pagination>.active>a:hover,.pagination>.active>span:hover,.pagination>.active>a:focus,.pagination>.active>span:focus{z-index:3;color:#fff;background-color:#337ab7;border-color:#337ab7;cursor:default}.pagination>.disabled>span,.pagination>.disabled>span:hover,.pagination>.disabled>span:focus,.pagination>.disabled>a,.pagination>.disabled>a:hover,.pagination>.disabled>a:focus{color:#777;background-color:#fff;border-color:#ddd;cursor:not-allowed}.pagination-lg>li>a,.pagination-lg>li>span{padding:10px 16px;font-size:18px;line-height:1.3333333}.pagination-lg>li:first-child>a,.pagination-lg>li:first-child>span{border-bottom-left-radius:6px;border-top-left-radius:6px}.pagination-lg>li:last-child>a,.pagination-lg>li:last-child>span{border-bottom-right-radius:6px;border-top-right-radius:6px}.pagination-sm>li>a,.pagination-sm>li>span{padding:5px 10px;font-size:12px;line-height:1.5}.pagination-sm>li:first-child>a,.pagination-sm>li:first-child>span{border-bottom-left-radius:3px;border-top-left-radius:3px}.pagination-sm>li:last-child>a,.pagination-sm>li:last-child>span{border-bottom-right-radius:3px;border-top-right-radius:3px}.pager{padding-left:0;margin:20px 0;list-style:none;text-align:center}.pager li{display:inline}.pager li>a,.pager li>span{display:inline-block;padding:5px 14px;background-color:#fff;border:1px solid #ddd;border-radius:15px}.pager li>a:hover,.pager li>a:focus{text-decoration:none;background-color:#eee}.pager .next>a,.pager .next>span{float:right}.pager .previous>a,.pager .previous>span{float:left}.pager .disabled>a,.pager .disabled>a:hover,.pager .disabled>a:focus,.pager .disabled>span{color:#777;background-color:#fff;cursor:not-allowed}.label{display:inline;padding:.2em .6em .3em;font-size:75%;font-weight:bold;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25em}a.label:hover,a.label:focus{color:#fff;text-decoration:none;cursor:pointer}.label:empty{display:none}.btn .label{position:relative;top:-1px}.label-default{background-color:#777}.label-default[href]:hover,.label-default[href]:focus{background-color:#5e5e5e}.label-primary{background-color:#337ab7}.label-primary[href]:hover,.label-primary[href]:focus{background-color:#286090}.label-success{background-color:#5cb85c}.label-success[href]:hover,.label-success[href]:focus{background-color:#449d44}.label-info{background-color:#5bc0de}.label-info[href]:hover,.label-info[href]:focus{background-color:#31b0d5}.label-warning{background-color:#f0ad4e}.label-warning[href]:hover,.label-warning[href]:focus{background-color:#ec971f}.label-danger{background-color:#d9534f}.label-danger[href]:hover,.label-danger[href]:focus{background-color:#c9302c}.badge{display:inline-block;min-width:10px;padding:3px 7px;font-size:12px;font-weight:bold;color:#fff;line-height:1;vertical-align:middle;white-space:nowrap;text-align:center;background-color:#777;border-radius:10px}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}.btn-xs .badge,.btn-group-xs>.btn .badge{top:0;padding:1px 5px}a.badge:hover,a.badge:focus{color:#fff;text-decoration:none;cursor:pointer}.list-group-item.active>.badge,.nav-pills>.active>a>.badge{color:#337ab7;background-color:#fff}.list-group-item>.badge{float:right}.list-group-item>.badge+.badge{margin-right:5px}.nav-pills>li>a>.badge{margin-left:3px}.jumbotron{padding-top:30px;padding-bottom:30px;margin-bottom:30px;color:inherit;background-color:#eee}.jumbotron h1,.jumbotron .h1{color:inherit}.jumbotron p{margin-bottom:15px;font-size:21px;font-weight:200}.jumbotron>hr{border-top-color:#d5d5d5}.container .jumbotron,.container-fluid .jumbotron{border-radius:6px;padding-left:15px;padding-right:15px}.jumbotron .container{max-width:100%}@media screen and (min-width:768px){.jumbotron{padding-top:48px;padding-bottom:48px}.container .jumbotron,.container-fluid .jumbotron{padding-left:60px;padding-right:60px}.jumbotron h1,.jumbotron .h1{font-size:63px}}.thumbnail{display:block;padding:4px;margin-bottom:20px;line-height:1.42857143;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:border .2s ease-in-out;-o-transition:border .2s ease-in-out;transition:border .2s ease-in-out}.thumbnail>img,.thumbnail a>img{margin-left:auto;margin-right:auto}a.thumbnail:hover,a.thumbnail:focus,a.thumbnail.active{border-color:#337ab7}.thumbnail .caption{padding:9px;color:#333}.alert{padding:15px;margin-bottom:20px;border:1px solid transparent;border-radius:4px}.alert h4{margin-top:0;color:inherit}.alert .alert-link{font-weight:bold}.alert>p,.alert>ul{margin-bottom:0}.alert>p+p{margin-top:5px}.alert-dismissable,.alert-dismissible{padding-right:35px}.alert-dismissable .close,.alert-dismissible .close{position:relative;top:-2px;right:-21px;color:inherit}.alert-success{background-color:#dff0d8;border-color:#d6e9c6;color:#3c763d}.alert-success hr{border-top-color:#c9e2b3}.alert-success .alert-link{color:#2b542c}.alert-info{background-color:#d9edf7;border-color:#bce8f1;color:#31708f}.alert-info hr{border-top-color:#a6e1ec}.alert-info .alert-link{color:#245269}.alert-warning{background-color:#fcf8e3;border-color:#faebcc;color:#8a6d3b}.alert-warning hr{border-top-color:#f7e1b5}.alert-warning .alert-link{color:#66512c}.alert-danger{background-color:#f2dede;border-color:#ebccd1;color:#a94442}.alert-danger hr{border-top-color:#e4b9c0}.alert-danger .alert-link{color:#843534}@-webkit-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@-o-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}.progress{overflow:hidden;height:20px;margin-bottom:20px;background-color:#f5f7f8;border-radius:4px;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.1);box-shadow:inset 0 1px 2px rgba(0,0,0,0.1)}.progress-bar{float:left;width:0%;height:100%;font-size:12px;line-height:20px;color:#fff;text-align:center;background-color:#337ab7;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);-webkit-transition:width .6s ease;-o-transition:width .6s ease;transition:width .6s ease}.progress-striped .progress-bar,.progress-bar-striped{background-image:-webkit-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:-o-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);-webkit-background-size:40px 40px;background-size:40px 40px}.progress.active .progress-bar,.progress-bar.active{-webkit-animation:progress-bar-stripes 2s linear infinite;-o-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite}.progress-bar-success{background-color:#5cb85c}.progress-striped .progress-bar-success{background-image:-webkit-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:-o-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent)}.progress-bar-info{background-color:#5bc0de}.progress-striped .progress-bar-info{background-image:-webkit-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:-o-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent)}.progress-bar-warning{background-color:#f0ad4e}.progress-striped .progress-bar-warning{background-image:-webkit-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:-o-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent)}.progress-bar-danger{background-color:#d9534f}.progress-striped .progress-bar-danger{background-image:-webkit-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:-o-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent)}.media{margin-top:15px}.media:first-child{margin-top:0}.media,.media-body{zoom:1;overflow:hidden}.media-body{width:10000px}.media-object{display:block}.media-object.img-thumbnail{max-width:none}.media-right,.media>.pull-right{padding-left:10px}.media-left,.media>.pull-left{padding-right:10px}.media-left,.media-right,.media-body{display:table-cell;vertical-align:top}.media-middle{vertical-align:middle}.media-bottom{vertical-align:bottom}.media-heading{margin-top:0;margin-bottom:5px}.media-list{padding-left:0;list-style:none}.list-group{margin-bottom:20px;padding-left:0}.list-group-item{position:relative;display:block;padding:10px 15px;margin-bottom:-1px;background-color:#fff;border:1px solid #ddd}.list-group-item:first-child{border-top-right-radius:4px;border-top-left-radius:4px}.list-group-item:last-child{margin-bottom:0;border-bottom-right-radius:4px;border-bottom-left-radius:4px}a.list-group-item,button.list-group-item{color:#555}a.list-group-item .list-group-item-heading,button.list-group-item .list-group-item-heading{color:#333}a.list-group-item:hover,button.list-group-item:hover,a.list-group-item:focus,button.list-group-item:focus{text-decoration:none;color:#555;background-color:#f5f7f8}button.list-group-item{width:100%;text-align:left}.list-group-item.disabled,.list-group-item.disabled:hover,.list-group-item.disabled:focus{background-color:#eee;color:#777;cursor:not-allowed}.list-group-item.disabled .list-group-item-heading,.list-group-item.disabled:hover .list-group-item-heading,.list-group-item.disabled:focus .list-group-item-heading{color:inherit}.list-group-item.disabled .list-group-item-text,.list-group-item.disabled:hover .list-group-item-text,.list-group-item.disabled:focus .list-group-item-text{color:#777}.list-group-item.active,.list-group-item.active:hover,.list-group-item.active:focus{z-index:2;color:#fff;background-color:#337ab7;border-color:#337ab7}.list-group-item.active .list-group-item-heading,.list-group-item.active:hover .list-group-item-heading,.list-group-item.active:focus .list-group-item-heading,.list-group-item.active .list-group-item-heading>small,.list-group-item.active:hover .list-group-item-heading>small,.list-group-item.active:focus .list-group-item-heading>small,.list-group-item.active .list-group-item-heading>.small,.list-group-item.active:hover .list-group-item-heading>.small,.list-group-item.active:focus .list-group-item-heading>.small{color:inherit}.list-group-item.active .list-group-item-text,.list-group-item.active:hover .list-group-item-text,.list-group-item.active:focus .list-group-item-text{color:#c7ddef}.list-group-item-success{color:#3c763d;background-color:#dff0d8}a.list-group-item-success,button.list-group-item-success{color:#3c763d}a.list-group-item-success .list-group-item-heading,button.list-group-item-success .list-group-item-heading{color:inherit}a.list-group-item-success:hover,button.list-group-item-success:hover,a.list-group-item-success:focus,button.list-group-item-success:focus{color:#3c763d;background-color:#d0e9c6}a.list-group-item-success.active,button.list-group-item-success.active,a.list-group-item-success.active:hover,button.list-group-item-success.active:hover,a.list-group-item-success.active:focus,button.list-group-item-success.active:focus{color:#fff;background-color:#3c763d;border-color:#3c763d}.list-group-item-info{color:#31708f;background-color:#d9edf7}a.list-group-item-info,button.list-group-item-info{color:#31708f}a.list-group-item-info .list-group-item-heading,button.list-group-item-info .list-group-item-heading{color:inherit}a.list-group-item-info:hover,button.list-group-item-info:hover,a.list-group-item-info:focus,button.list-group-item-info:focus{color:#31708f;background-color:#c4e3f3}a.list-group-item-info.active,button.list-group-item-info.active,a.list-group-item-info.active:hover,button.list-group-item-info.active:hover,a.list-group-item-info.active:focus,button.list-group-item-info.active:focus{color:#fff;background-color:#31708f;border-color:#31708f}.list-group-item-warning{color:#8a6d3b;background-color:#fcf8e3}a.list-group-item-warning,button.list-group-item-warning{color:#8a6d3b}a.list-group-item-warning .list-group-item-heading,button.list-group-item-warning .list-group-item-heading{color:inherit}a.list-group-item-warning:hover,button.list-group-item-warning:hover,a.list-group-item-warning:focus,button.list-group-item-warning:focus{color:#8a6d3b;background-color:#faf2cc}a.list-group-item-warning.active,button.list-group-item-warning.active,a.list-group-item-warning.active:hover,button.list-group-item-warning.active:hover,a.list-group-item-warning.active:focus,button.list-group-item-warning.active:focus{color:#fff;background-color:#8a6d3b;border-color:#8a6d3b}.list-group-item-danger{color:#a94442;background-color:#f2dede}a.list-group-item-danger,button.list-group-item-danger{color:#a94442}a.list-group-item-danger .list-group-item-heading,button.list-group-item-danger .list-group-item-heading{color:inherit}a.list-group-item-danger:hover,button.list-group-item-danger:hover,a.list-group-item-danger:focus,button.list-group-item-danger:focus{color:#a94442;background-color:#ebcccc}a.list-group-item-danger.active,button.list-group-item-danger.active,a.list-group-item-danger.active:hover,button.list-group-item-danger.active:hover,a.list-group-item-danger.active:focus,button.list-group-item-danger.active:focus{color:#fff;background-color:#a94442;border-color:#a94442}.list-group-item-heading{margin-top:0;margin-bottom:5px}.list-group-item-text{margin-bottom:0;line-height:1.3}.panel{margin-bottom:20px;background-color:#fff;border:1px solid transparent;border-radius:4px;-webkit-box-shadow:0 1px 1px rgba(0,0,0,0.05);box-shadow:0 1px 1px rgba(0,0,0,0.05)}.panel-body{padding:15px}.panel-heading{padding:10px 15px;border-bottom:1px solid transparent;border-top-right-radius:3px;border-top-left-radius:3px}.panel-heading>.dropdown .dropdown-toggle{color:inherit}.panel-title{margin-top:0;margin-bottom:0;font-size:16px;color:inherit}.panel-title>a,.panel-title>small,.panel-title>.small,.panel-title>small>a,.panel-title>.small>a{color:inherit}.panel-footer{padding:10px 15px;background-color:#f5f7f8;border-top:1px solid #ddd;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.list-group,.panel>.panel-collapse>.list-group{margin-bottom:0}.panel>.list-group .list-group-item,.panel>.panel-collapse>.list-group .list-group-item{border-width:1px 0;border-radius:0}.panel>.list-group:first-child .list-group-item:first-child,.panel>.panel-collapse>.list-group:first-child .list-group-item:first-child{border-top:0;border-top-right-radius:3px;border-top-left-radius:3px}.panel>.list-group:last-child .list-group-item:last-child,.panel>.panel-collapse>.list-group:last-child .list-group-item:last-child{border-bottom:0;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.panel-heading+.panel-collapse>.list-group .list-group-item:first-child{border-top-right-radius:0;border-top-left-radius:0}.panel-heading+.list-group .list-group-item:first-child{border-top-width:0}.list-group+.panel-footer{border-top-width:0}.panel>.table,.panel>.table-responsive>.table,.panel>.panel-collapse>.table{margin-bottom:0}.panel>.table caption,.panel>.table-responsive>.table caption,.panel>.panel-collapse>.table caption{padding-left:15px;padding-right:15px}.panel>.table:first-child,.panel>.table-responsive:first-child>.table:first-child{border-top-right-radius:3px;border-top-left-radius:3px}.panel>.table:first-child>thead:first-child>tr:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child{border-top-left-radius:3px;border-top-right-radius:3px}.panel>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table:first-child>thead:first-child>tr:first-child th:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:first-child{border-top-left-radius:3px}.panel>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table:first-child>thead:first-child>tr:first-child th:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:last-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:last-child{border-top-right-radius:3px}.panel>.table:last-child,.panel>.table-responsive:last-child>.table:last-child{border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.table:last-child>tbody:last-child>tr:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child{border-bottom-left-radius:3px;border-bottom-right-radius:3px}.panel>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:first-child{border-bottom-left-radius:3px}.panel>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:last-child{border-bottom-right-radius:3px}.panel>.panel-body+.table,.panel>.panel-body+.table-responsive,.panel>.table+.panel-body,.panel>.table-responsive+.panel-body{border-top:1px solid #ddd}.panel>.table>tbody:first-child>tr:first-child th,.panel>.table>tbody:first-child>tr:first-child td{border-top:0}.panel>.table-bordered,.panel>.table-responsive>.table-bordered{border:0}.panel>.table-bordered>thead>tr>th:first-child,.panel>.table-responsive>.table-bordered>thead>tr>th:first-child,.panel>.table-bordered>tbody>tr>th:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:first-child,.panel>.table-bordered>tfoot>tr>th:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:first-child,.panel>.table-bordered>thead>tr>td:first-child,.panel>.table-responsive>.table-bordered>thead>tr>td:first-child,.panel>.table-bordered>tbody>tr>td:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:first-child,.panel>.table-bordered>tfoot>tr>td:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:first-child{border-left:0}.panel>.table-bordered>thead>tr>th:last-child,.panel>.table-responsive>.table-bordered>thead>tr>th:last-child,.panel>.table-bordered>tbody>tr>th:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:last-child,.panel>.table-bordered>tfoot>tr>th:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:last-child,.panel>.table-bordered>thead>tr>td:last-child,.panel>.table-responsive>.table-bordered>thead>tr>td:last-child,.panel>.table-bordered>tbody>tr>td:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:last-child,.panel>.table-bordered>tfoot>tr>td:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:last-child{border-right:0}.panel>.table-bordered>thead>tr:first-child>td,.panel>.table-responsive>.table-bordered>thead>tr:first-child>td,.panel>.table-bordered>tbody>tr:first-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>td,.panel>.table-bordered>thead>tr:first-child>th,.panel>.table-responsive>.table-bordered>thead>tr:first-child>th,.panel>.table-bordered>tbody>tr:first-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>th{border-bottom:0}.panel>.table-bordered>tbody>tr:last-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>td,.panel>.table-bordered>tfoot>tr:last-child>td,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>td,.panel>.table-bordered>tbody>tr:last-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>th,.panel>.table-bordered>tfoot>tr:last-child>th,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>th{border-bottom:0}.panel>.table-responsive{border:0;margin-bottom:0}.panel-group{margin-bottom:20px}.panel-group .panel{margin-bottom:0;border-radius:4px}.panel-group .panel+.panel{margin-top:5px}.panel-group .panel-heading{border-bottom:0}.panel-group .panel-heading+.panel-collapse>.panel-body,.panel-group .panel-heading+.panel-collapse>.list-group{border-top:1px solid #ddd}.panel-group .panel-footer{border-top:0}.panel-group .panel-footer+.panel-collapse .panel-body{border-bottom:1px solid #ddd}.panel-default{border-color:#ddd}.panel-default>.panel-heading{color:#333;background-color:#f5f7f8;border-color:#ddd}.panel-default>.panel-heading+.panel-collapse>.panel-body{border-top-color:#ddd}.panel-default>.panel-heading .badge{color:#f5f7f8;background-color:#333}.panel-default>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#ddd}.panel-primary{border-color:#337ab7}.panel-primary>.panel-heading{color:#fff;background-color:#337ab7;border-color:#337ab7}.panel-primary>.panel-heading+.panel-collapse>.panel-body{border-top-color:#337ab7}.panel-primary>.panel-heading .badge{color:#337ab7;background-color:#fff}.panel-primary>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#337ab7}.panel-success{border-color:#d6e9c6}.panel-success>.panel-heading{color:#3c763d;background-color:#dff0d8;border-color:#d6e9c6}.panel-success>.panel-heading+.panel-collapse>.panel-body{border-top-color:#d6e9c6}.panel-success>.panel-heading .badge{color:#dff0d8;background-color:#3c763d}.panel-success>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#d6e9c6}.panel-info{border-color:#bce8f1}.panel-info>.panel-heading{color:#31708f;background-color:#d9edf7;border-color:#bce8f1}.panel-info>.panel-heading+.panel-collapse>.panel-body{border-top-color:#bce8f1}.panel-info>.panel-heading .badge{color:#d9edf7;background-color:#31708f}.panel-info>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#bce8f1}.panel-warning{border-color:#faebcc}.panel-warning>.panel-heading{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc}.panel-warning>.panel-heading+.panel-collapse>.panel-body{border-top-color:#faebcc}.panel-warning>.panel-heading .badge{color:#fcf8e3;background-color:#8a6d3b}.panel-warning>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#faebcc}.panel-danger{border-color:#ebccd1}.panel-danger>.panel-heading{color:#a94442;background-color:#f2dede;border-color:#ebccd1}.panel-danger>.panel-heading+.panel-collapse>.panel-body{border-top-color:#ebccd1}.panel-danger>.panel-heading .badge{color:#f2dede;background-color:#a94442}.panel-danger>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#ebccd1}.embed-responsive{position:relative;display:block;height:0;padding:0;overflow:hidden}.embed-responsive .embed-responsive-item,.embed-responsive iframe,.embed-responsive embed,.embed-responsive object,.embed-responsive video{position:absolute;top:0;left:0;bottom:0;height:100%;width:100%;border:0}.embed-responsive-16by9{padding-bottom:56.25%}.embed-responsive-4by3{padding-bottom:75%}.well{min-height:20px;padding:19px;margin-bottom:20px;background-color:#f5f7f8;border:1px solid #e0e6e9;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.05);box-shadow:inset 0 1px 1px rgba(0,0,0,0.05)}.well blockquote{border-color:#ddd;border-color:rgba(0,0,0,0.15)}.well-lg{padding:24px;border-radius:6px}.well-sm{padding:9px;border-radius:3px}.close{float:right;font-size:21px;font-weight:bold;line-height:1;color:#000;text-shadow:0 1px 0 #fff;opacity:.2;filter:alpha(opacity=20)}.close:hover,.close:focus{color:#000;text-decoration:none;cursor:pointer;opacity:.5;filter:alpha(opacity=50)}button.close{padding:0;cursor:pointer;background:transparent;border:0;-webkit-appearance:none}.modal-open{overflow:hidden}.modal{display:none;overflow:hidden;position:fixed;top:0;right:0;bottom:0;left:0;z-index:1050;-webkit-overflow-scrolling:touch;outline:0}.modal.fade .modal-dialog{-webkit-transform:translate(0, -25%);-ms-transform:translate(0, -25%);-o-transform:translate(0, -25%);transform:translate(0, -25%);-webkit-transition:-webkit-transform 0.3s ease-out;-o-transition:-o-transform 0.3s ease-out;transition:transform 0.3s ease-out}.modal.in .modal-dialog{-webkit-transform:translate(0, 0);-ms-transform:translate(0, 0);-o-transform:translate(0, 0);transform:translate(0, 0)}.modal-open .modal{overflow-x:hidden;overflow-y:auto}.modal-dialog{position:relative;width:auto;margin:10px}.modal-content{position:relative;background-color:#fff;border:1px solid #999;border:1px solid rgba(0,0,0,0.2);border-radius:6px;-webkit-box-shadow:0 3px 9px rgba(0,0,0,0.5);box-shadow:0 3px 9px rgba(0,0,0,0.5);-webkit-background-clip:padding-box;background-clip:padding-box;outline:0}.modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;background-color:#000}.modal-backdrop.fade{opacity:0;filter:alpha(opacity=0)}.modal-backdrop.in{opacity:.5;filter:alpha(opacity=50)}.modal-header{padding:15px;border-bottom:1px solid #e5e5e5}.modal-header .close{margin-top:-2px}.modal-title{margin:0;line-height:1.42857143}.modal-body{position:relative;padding:15px}.modal-footer{padding:15px;text-align:right;border-top:1px solid #e5e5e5}.modal-footer .btn+.btn{margin-left:5px;margin-bottom:0}.modal-footer .btn-group .btn+.btn{margin-left:-1px}.modal-footer .btn-block+.btn-block{margin-left:0}.modal-scrollbar-measure{position:absolute;top:-9999px;width:50px;height:50px;overflow:scroll}@media (min-width:768px){.modal-dialog{width:600px;margin:30px auto}.modal-content{-webkit-box-shadow:0 5px 15px rgba(0,0,0,0.5);box-shadow:0 5px 15px rgba(0,0,0,0.5)}.modal-sm{width:300px}}@media (min-width:992px){.modal-lg{width:900px}}.tooltip{position:absolute;z-index:1070;display:block;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-style:normal;font-weight:normal;letter-spacing:normal;line-break:auto;line-height:1.42857143;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;white-space:normal;word-break:normal;word-spacing:normal;word-wrap:normal;font-size:12px;opacity:0;filter:alpha(opacity=0)}.tooltip.in{opacity:.9;filter:alpha(opacity=90)}.tooltip.top{margin-top:-3px;padding:5px 0}.tooltip.right{margin-left:3px;padding:0 5px}.tooltip.bottom{margin-top:3px;padding:5px 0}.tooltip.left{margin-left:-3px;padding:0 5px}.tooltip-inner{max-width:200px;padding:3px 8px;color:#fff;text-align:center;background-color:#000;border-radius:4px}.tooltip-arrow{position:absolute;width:0;height:0;border-color:transparent;border-style:solid}.tooltip.top .tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-left .tooltip-arrow{bottom:0;right:5px;margin-bottom:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-right .tooltip-arrow{bottom:0;left:5px;margin-bottom:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-width:5px 5px 5px 0;border-right-color:#000}.tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-width:5px 0 5px 5px;border-left-color:#000}.tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-left .tooltip-arrow{top:0;right:5px;margin-top:-5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-right .tooltip-arrow{top:0;left:5px;margin-top:-5px;border-width:0 5px 5px;border-bottom-color:#000}.popover{position:absolute;top:0;left:0;z-index:1060;display:none;max-width:276px;padding:1px;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-style:normal;font-weight:normal;letter-spacing:normal;line-break:auto;line-height:1.42857143;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;white-space:normal;word-break:normal;word-spacing:normal;word-wrap:normal;font-size:14px;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.2);border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,0.2);box-shadow:0 5px 10px rgba(0,0,0,0.2)}.popover.top{margin-top:-10px}.popover.right{margin-left:10px}.popover.bottom{margin-top:10px}.popover.left{margin-left:-10px}.popover-title{margin:0;padding:8px 14px;font-size:14px;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;border-radius:5px 5px 0 0}.popover-content{padding:9px 14px}.popover>.arrow,.popover>.arrow:after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.popover>.arrow{border-width:11px}.popover>.arrow:after{border-width:10px;content:""}.popover.top>.arrow{left:50%;margin-left:-11px;border-bottom-width:0;border-top-color:#999;border-top-color:rgba(0,0,0,0.25);bottom:-11px}.popover.top>.arrow:after{content:" ";bottom:1px;margin-left:-10px;border-bottom-width:0;border-top-color:#fff}.popover.right>.arrow{top:50%;left:-11px;margin-top:-11px;border-left-width:0;border-right-color:#999;border-right-color:rgba(0,0,0,0.25)}.popover.right>.arrow:after{content:" ";left:1px;bottom:-10px;border-left-width:0;border-right-color:#fff}.popover.bottom>.arrow{left:50%;margin-left:-11px;border-top-width:0;border-bottom-color:#999;border-bottom-color:rgba(0,0,0,0.25);top:-11px}.popover.bottom>.arrow:after{content:" ";top:1px;margin-left:-10px;border-top-width:0;border-bottom-color:#fff}.popover.left>.arrow{top:50%;right:-11px;margin-top:-11px;border-right-width:0;border-left-color:#999;border-left-color:rgba(0,0,0,0.25)}.popover.left>.arrow:after{content:" ";right:1px;border-right-width:0;border-left-color:#fff;bottom:-10px}.carousel{position:relative}.carousel-inner{position:relative;overflow:hidden;width:100%}.carousel-inner>.item{display:none;position:relative;-webkit-transition:.6s ease-in-out left;-o-transition:.6s ease-in-out left;transition:.6s ease-in-out left}.carousel-inner>.item>img,.carousel-inner>.item>a>img{line-height:1}@media all and (transform-3d),(-webkit-transform-3d){.carousel-inner>.item{-webkit-transition:-webkit-transform 0.6s ease-in-out;-o-transition:-o-transform 0.6s ease-in-out;transition:transform 0.6s ease-in-out;-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-perspective:1000px;perspective:1000px}.carousel-inner>.item.next,.carousel-inner>.item.active.right{-webkit-transform:translate3d(100%, 0, 0);transform:translate3d(100%, 0, 0);left:0}.carousel-inner>.item.prev,.carousel-inner>.item.active.left{-webkit-transform:translate3d(-100%, 0, 0);transform:translate3d(-100%, 0, 0);left:0}.carousel-inner>.item.next.left,.carousel-inner>.item.prev.right,.carousel-inner>.item.active{-webkit-transform:translate3d(0, 0, 0);transform:translate3d(0, 0, 0);left:0}}.carousel-inner>.active,.carousel-inner>.next,.carousel-inner>.prev{display:block}.carousel-inner>.active{left:0}.carousel-inner>.next,.carousel-inner>.prev{position:absolute;top:0;width:100%}.carousel-inner>.next{left:100%}.carousel-inner>.prev{left:-100%}.carousel-inner>.next.left,.carousel-inner>.prev.right{left:0}.carousel-inner>.active.left{left:-100%}.carousel-inner>.active.right{left:100%}.carousel-control{position:absolute;top:0;left:0;bottom:0;width:15%;opacity:.5;filter:alpha(opacity=50);font-size:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,0.6);background-color:rgba(0,0,0,0)}.carousel-control.left{background-image:-webkit-linear-gradient(left, rgba(0,0,0,0.5) 0, rgba(0,0,0,0.0001) 100%);background-image:-o-linear-gradient(left, rgba(0,0,0,0.5) 0, rgba(0,0,0,0.0001) 100%);background-image:-webkit-gradient(linear, left top, right top, color-stop(0, rgba(0,0,0,0.5)), to(rgba(0,0,0,0.0001)));background-image:linear-gradient(to right, rgba(0,0,0,0.5) 0, rgba(0,0,0,0.0001) 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1)}.carousel-control.right{left:auto;right:0;background-image:-webkit-linear-gradient(left, rgba(0,0,0,0.0001) 0, rgba(0,0,0,0.5) 100%);background-image:-o-linear-gradient(left, rgba(0,0,0,0.0001) 0, rgba(0,0,0,0.5) 100%);background-image:-webkit-gradient(linear, left top, right top, color-stop(0, rgba(0,0,0,0.0001)), to(rgba(0,0,0,0.5)));background-image:linear-gradient(to right, rgba(0,0,0,0.0001) 0, rgba(0,0,0,0.5) 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1)}.carousel-control:hover,.carousel-control:focus{outline:0;color:#fff;text-decoration:none;opacity:.9;filter:alpha(opacity=90)}.carousel-control .icon-prev,.carousel-control .icon-next,.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right{position:absolute;top:50%;margin-top:-10px;z-index:5;display:inline-block}.carousel-control .icon-prev,.carousel-control .glyphicon-chevron-left{left:50%;margin-left:-10px}.carousel-control .icon-next,.carousel-control .glyphicon-chevron-right{right:50%;margin-right:-10px}.carousel-control .icon-prev,.carousel-control .icon-next{width:20px;height:20px;line-height:1;font-family:serif}.carousel-control .icon-prev:before{content:'\2039'}.carousel-control .icon-next:before{content:'\203a'}.carousel-indicators{position:absolute;bottom:10px;left:50%;z-index:15;width:60%;margin-left:-30%;padding-left:0;list-style:none;text-align:center}.carousel-indicators li{display:inline-block;width:10px;height:10px;margin:1px;text-indent:-999px;border:1px solid #fff;border-radius:10px;cursor:pointer;background-color:#000 \9;background-color:rgba(0,0,0,0)}.carousel-indicators .active{margin:0;width:12px;height:12px;background-color:#fff}.carousel-caption{position:absolute;left:15%;right:15%;bottom:20px;z-index:10;padding-top:20px;padding-bottom:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,0.6)}.carousel-caption .btn{text-shadow:none}@media screen and (min-width:768px){.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right,.carousel-control .icon-prev,.carousel-control .icon-next{width:30px;height:30px;margin-top:-10px;font-size:30px}.carousel-control .glyphicon-chevron-left,.carousel-control .icon-prev{margin-left:-10px}.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next{margin-right:-10px}.carousel-caption{left:20%;right:20%;padding-bottom:30px}.carousel-indicators{bottom:20px}}.clearfix:before,.clearfix:after,.dl-horizontal dd:before,.dl-horizontal dd:after,.container:before,.container:after,.container-fluid:before,.container-fluid:after,.row:before,.row:after,.form-horizontal .form-group:before,.form-horizontal .form-group:after,.btn-toolbar:before,.btn-toolbar:after,.btn-group-vertical>.btn-group:before,.btn-group-vertical>.btn-group:after,.nav:before,.nav:after,.navbar:before,.navbar:after,.navbar-header:before,.navbar-header:after,.navbar-collapse:before,.navbar-collapse:after,.pager:before,.pager:after,.panel-body:before,.panel-body:after,.modal-header:before,.modal-header:after,.modal-footer:before,.modal-footer:after{content:" ";display:table}.clearfix:after,.dl-horizontal dd:after,.container:after,.container-fluid:after,.row:after,.form-horizontal .form-group:after,.btn-toolbar:after,.btn-group-vertical>.btn-group:after,.nav:after,.navbar:after,.navbar-header:after,.navbar-collapse:after,.pager:after,.panel-body:after,.modal-header:after,.modal-footer:after{clear:both}.center-block{display:block;margin-left:auto;margin-right:auto}.pull-right{float:right !important}.pull-left{float:left !important}.hide{display:none !important}.show{display:block !important}.invisible{visibility:hidden}.text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.hidden{display:none !important}.affix{position:fixed}@-ms-viewport{width:device-width}.visible-xs,.visible-sm,.visible-md,.visible-lg{display:none !important}.visible-xs-block,.visible-xs-inline,.visible-xs-inline-block,.visible-sm-block,.visible-sm-inline,.visible-sm-inline-block,.visible-md-block,.visible-md-inline,.visible-md-inline-block,.visible-lg-block,.visible-lg-inline,.visible-lg-inline-block{display:none !important}@media (max-width:767px){.visible-xs{display:block !important}table.visible-xs{display:table !important}tr.visible-xs{display:table-row !important}th.visible-xs,td.visible-xs{display:table-cell !important}}@media (max-width:767px){.visible-xs-block{display:block !important}}@media (max-width:767px){.visible-xs-inline{display:inline !important}}@media (max-width:767px){.visible-xs-inline-block{display:inline-block !important}}@media (min-width:768px) and (max-width:991px){.visible-sm{display:block !important}table.visible-sm{display:table !important}tr.visible-sm{display:table-row !important}th.visible-sm,td.visible-sm{display:table-cell !important}}@media (min-width:768px) and (max-width:991px){.visible-sm-block{display:block !important}}@media (min-width:768px) and (max-width:991px){.visible-sm-inline{display:inline !important}}@media (min-width:768px) and (max-width:991px){.visible-sm-inline-block{display:inline-block !important}}@media (min-width:992px) and (max-width:1199px){.visible-md{display:block !important}table.visible-md{display:table !important}tr.visible-md{display:table-row !important}th.visible-md,td.visible-md{display:table-cell !important}}@media (min-width:992px) and (max-width:1199px){.visible-md-block{display:block !important}}@media (min-width:992px) and (max-width:1199px){.visible-md-inline{display:inline !important}}@media (min-width:992px) and (max-width:1199px){.visible-md-inline-block{display:inline-block !important}}@media (min-width:1200px){.visible-lg{display:block !important}table.visible-lg{display:table !important}tr.visible-lg{display:table-row !important}th.visible-lg,td.visible-lg{display:table-cell !important}}@media (min-width:1200px){.visible-lg-block{display:block !important}}@media (min-width:1200px){.visible-lg-inline{display:inline !important}}@media (min-width:1200px){.visible-lg-inline-block{display:inline-block !important}}@media (max-width:767px){.hidden-xs{display:none !important}}@media (min-width:768px) and (max-width:991px){.hidden-sm{display:none !important}}@media (min-width:992px) and (max-width:1199px){.hidden-md{display:none !important}}@media (min-width:1200px){.hidden-lg{display:none !important}}.visible-print{display:none !important}@media print{.visible-print{display:block !important}table.visible-print{display:table !important}tr.visible-print{display:table-row !important}th.visible-print,td.visible-print{display:table-cell !important}}.visible-print-block{display:none !important}@media print{.visible-print-block{display:block !important}}.visible-print-inline{display:none !important}@media print{.visible-print-inline{display:inline !important}}.visible-print-inline-block{display:none !important}@media print{.visible-print-inline-block{display:inline-block !important}}@media print{.hidden-print{display:none !important}} \ No newline at end of file + */ /*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */ +html { + font-family: sans-serif; + -ms-text-size-adjust: 100%; + -webkit-text-size-adjust: 100%; +} +body { + margin: 0; +} +article, +aside, +details, +figcaption, +figure, +footer, +header, +hgroup, +main, +menu, +nav, +section, +summary { + display: block; +} +audio, +canvas, +progress, +video { + display: inline-block; + vertical-align: baseline; +} +audio:not([controls]) { + display: none; + height: 0; +} +[hidden], +template { + display: none; +} +a { + background-color: transparent; +} +a:active, +a:hover { + outline: 0; +} +abbr[title] { + border-bottom: 1px dotted; +} +b, +strong { + font-weight: bold; +} +dfn { + font-style: italic; +} +h1 { + font-size: 2em; + margin: 0.67em 0; +} +mark { + background: #ff0; + color: #000; +} +small { + font-size: 80%; +} +sub, +sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; +} +sup { + top: -0.5em; +} +sub { + bottom: -0.25em; +} +img { + border: 0; +} +svg:not(:root) { + overflow: hidden; +} +figure { + margin: 1em 40px; +} +hr { + -webkit-box-sizing: content-box; + -moz-box-sizing: content-box; + box-sizing: content-box; + height: 0; +} +pre { + overflow: auto; +} +code, +kbd, +pre, +samp { + font-family: monospace, monospace; + font-size: 1em; +} +button, +input, +optgroup, +select, +textarea { + color: inherit; + font: inherit; + margin: 0; +} +button { + overflow: visible; +} +button, +select { + text-transform: none; +} +button, +html input[type="button"], +input[type="reset"], +input[type="submit"] { + -webkit-appearance: button; + cursor: pointer; +} +button[disabled], +html input[disabled] { + cursor: default; +} +button::-moz-focus-inner, +input::-moz-focus-inner { + border: 0; + padding: 0; +} +input { + line-height: normal; +} +input[type="checkbox"], +input[type="radio"] { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + padding: 0; +} +input[type="number"]::-webkit-inner-spin-button, +input[type="number"]::-webkit-outer-spin-button { + height: auto; +} +input[type="search"] { + -webkit-appearance: textfield; + -webkit-box-sizing: content-box; + -moz-box-sizing: content-box; + box-sizing: content-box; +} +input[type="search"]::-webkit-search-cancel-button, +input[type="search"]::-webkit-search-decoration { + -webkit-appearance: none; +} +fieldset { + border: 1px solid #c0c0c0; + margin: 0 2px; + padding: 0.35em 0.625em 0.75em; +} +legend { + border: 0; + padding: 0; +} +textarea { + overflow: auto; +} +optgroup { + font-weight: bold; +} +table { + border-collapse: collapse; + border-spacing: 0; +} +td, +th { + padding: 0; +} /*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */ +@media print { + *, + *:before, + *:after { + background: transparent !important; + color: #000 !important; + -webkit-box-shadow: none !important; + box-shadow: none !important; + text-shadow: none !important; + } + a, + a:visited { + text-decoration: underline; + } + a[href]:after { + content: " (" attr(href) ")"; + } + abbr[title]:after { + content: " (" attr(title) ")"; + } + a[href^="#"]:after, + a[href^="javascript:"]:after { + content: ""; + } + pre, + blockquote { + border: 1px solid #999; + page-break-inside: avoid; + } + thead { + display: table-header-group; + } + tr, + img { + page-break-inside: avoid; + } + img { + max-width: 100% !important; + } + p, + h2, + h3 { + orphans: 3; + widows: 3; + } + h2, + h3 { + page-break-after: avoid; + } + .navbar { + display: none; + } + .btn > .caret, + .dropup > .btn > .caret { + border-top-color: #000 !important; + } + .label { + border: 1px solid #000; + } + .table { + border-collapse: collapse !important; + } + .table td, + .table th { + background-color: #fff !important; + } + .table-bordered th, + .table-bordered td { + border: 1px solid #ddd !important; + } +} +@font-face { + font-family: "Glyphicons Halflings"; + src: url("../fonts/glyphicons-halflings-regular.eot"); + src: url("../fonts/glyphicons-halflings-regular.eot?#iefix") + format("embedded-opentype"), + url("../fonts/glyphicons-halflings-regular.woff2") format("woff2"), + url("../fonts/glyphicons-halflings-regular.woff") format("woff"), + url("../fonts/glyphicons-halflings-regular.ttf") format("truetype"), + url("../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular") + format("svg"); +} +.glyphicon { + position: relative; + top: 1px; + display: inline-block; + font-family: "Glyphicons Halflings"; + font-style: normal; + font-weight: normal; + line-height: 1; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} +.glyphicon-asterisk:before { + content: "\002a"; +} +.glyphicon-plus:before { + content: "\002b"; +} +.glyphicon-euro:before, +.glyphicon-eur:before { + content: "\20ac"; +} +.glyphicon-minus:before { + content: "\2212"; +} +.glyphicon-cloud:before { + content: "\2601"; +} +.glyphicon-envelope:before { + content: "\2709"; +} +.glyphicon-pencil:before { + content: "\270f"; +} +.glyphicon-glass:before { + content: "\e001"; +} +.glyphicon-music:before { + content: "\e002"; +} +.glyphicon-search:before { + content: "\e003"; +} +.glyphicon-heart:before { + content: "\e005"; +} +.glyphicon-star:before { + content: "\e006"; +} +.glyphicon-star-empty:before { + content: "\e007"; +} +.glyphicon-user:before { + content: "\e008"; +} +.glyphicon-film:before { + content: "\e009"; +} +.glyphicon-th-large:before { + content: "\e010"; +} +.glyphicon-th:before { + content: "\e011"; +} +.glyphicon-th-list:before { + content: "\e012"; +} +.glyphicon-ok:before { + content: "\e013"; +} +.glyphicon-remove:before { + content: "\e014"; +} +.glyphicon-zoom-in:before { + content: "\e015"; +} +.glyphicon-zoom-out:before { + content: "\e016"; +} +.glyphicon-off:before { + content: "\e017"; +} +.glyphicon-signal:before { + content: "\e018"; +} +.glyphicon-cog:before { + content: "\e019"; +} +.glyphicon-trash:before { + content: "\e020"; +} +.glyphicon-home:before { + content: "\e021"; +} +.glyphicon-file:before { + content: "\e022"; +} +.glyphicon-time:before { + content: "\e023"; +} +.glyphicon-road:before { + content: "\e024"; +} +.glyphicon-download-alt:before { + content: "\e025"; +} +.glyphicon-download:before { + content: "\e026"; +} +.glyphicon-upload:before { + content: "\e027"; +} +.glyphicon-inbox:before { + content: "\e028"; +} +.glyphicon-play-circle:before { + content: "\e029"; +} +.glyphicon-repeat:before { + content: "\e030"; +} +.glyphicon-refresh:before { + content: "\e031"; +} +.glyphicon-list-alt:before { + content: "\e032"; +} +.glyphicon-lock:before { + content: "\e033"; +} +.glyphicon-flag:before { + content: "\e034"; +} +.glyphicon-headphones:before { + content: "\e035"; +} +.glyphicon-volume-off:before { + content: "\e036"; +} +.glyphicon-volume-down:before { + content: "\e037"; +} +.glyphicon-volume-up:before { + content: "\e038"; +} +.glyphicon-qrcode:before { + content: "\e039"; +} +.glyphicon-barcode:before { + content: "\e040"; +} +.glyphicon-tag:before { + content: "\e041"; +} +.glyphicon-tags:before { + content: "\e042"; +} +.glyphicon-book:before { + content: "\e043"; +} +.glyphicon-bookmark:before { + content: "\e044"; +} +.glyphicon-print:before { + content: "\e045"; +} +.glyphicon-camera:before { + content: "\e046"; +} +.glyphicon-font:before { + content: "\e047"; +} +.glyphicon-bold:before { + content: "\e048"; +} +.glyphicon-italic:before { + content: "\e049"; +} +.glyphicon-text-height:before { + content: "\e050"; +} +.glyphicon-text-width:before { + content: "\e051"; +} +.glyphicon-align-left:before { + content: "\e052"; +} +.glyphicon-align-center:before { + content: "\e053"; +} +.glyphicon-align-right:before { + content: "\e054"; +} +.glyphicon-align-justify:before { + content: "\e055"; +} +.glyphicon-list:before { + content: "\e056"; +} +.glyphicon-indent-left:before { + content: "\e057"; +} +.glyphicon-indent-right:before { + content: "\e058"; +} +.glyphicon-facetime-video:before { + content: "\e059"; +} +.glyphicon-picture:before { + content: "\e060"; +} +.glyphicon-map-marker:before { + content: "\e062"; +} +.glyphicon-adjust:before { + content: "\e063"; +} +.glyphicon-tint:before { + content: "\e064"; +} +.glyphicon-edit:before { + content: "\e065"; +} +.glyphicon-share:before { + content: "\e066"; +} +.glyphicon-check:before { + content: "\e067"; +} +.glyphicon-move:before { + content: "\e068"; +} +.glyphicon-step-backward:before { + content: "\e069"; +} +.glyphicon-fast-backward:before { + content: "\e070"; +} +.glyphicon-backward:before { + content: "\e071"; +} +.glyphicon-play:before { + content: "\e072"; +} +.glyphicon-pause:before { + content: "\e073"; +} +.glyphicon-stop:before { + content: "\e074"; +} +.glyphicon-forward:before { + content: "\e075"; +} +.glyphicon-fast-forward:before { + content: "\e076"; +} +.glyphicon-step-forward:before { + content: "\e077"; +} +.glyphicon-eject:before { + content: "\e078"; +} +.glyphicon-chevron-left:before { + content: "\e079"; +} +.glyphicon-chevron-right:before { + content: "\e080"; +} +.glyphicon-plus-sign:before { + content: "\e081"; +} +.glyphicon-minus-sign:before { + content: "\e082"; +} +.glyphicon-remove-sign:before { + content: "\e083"; +} +.glyphicon-ok-sign:before { + content: "\e084"; +} +.glyphicon-question-sign:before { + content: "\e085"; +} +.glyphicon-info-sign:before { + content: "\e086"; +} +.glyphicon-screenshot:before { + content: "\e087"; +} +.glyphicon-remove-circle:before { + content: "\e088"; +} +.glyphicon-ok-circle:before { + content: "\e089"; +} +.glyphicon-ban-circle:before { + content: "\e090"; +} +.glyphicon-arrow-left:before { + content: "\e091"; +} +.glyphicon-arrow-right:before { + content: "\e092"; +} +.glyphicon-arrow-up:before { + content: "\e093"; +} +.glyphicon-arrow-down:before { + content: "\e094"; +} +.glyphicon-share-alt:before { + content: "\e095"; +} +.glyphicon-resize-full:before { + content: "\e096"; +} +.glyphicon-resize-small:before { + content: "\e097"; +} +.glyphicon-exclamation-sign:before { + content: "\e101"; +} +.glyphicon-gift:before { + content: "\e102"; +} +.glyphicon-leaf:before { + content: "\e103"; +} +.glyphicon-fire:before { + content: "\e104"; +} +.glyphicon-eye-open:before { + content: "\e105"; +} +.glyphicon-eye-close:before { + content: "\e106"; +} +.glyphicon-warning-sign:before { + content: "\e107"; +} +.glyphicon-plane:before { + content: "\e108"; +} +.glyphicon-calendar:before { + content: "\e109"; +} +.glyphicon-random:before { + content: "\e110"; +} +.glyphicon-comment:before { + content: "\e111"; +} +.glyphicon-magnet:before { + content: "\e112"; +} +.glyphicon-chevron-up:before { + content: "\e113"; +} +.glyphicon-chevron-down:before { + content: "\e114"; +} +.glyphicon-retweet:before { + content: "\e115"; +} +.glyphicon-shopping-cart:before { + content: "\e116"; +} +.glyphicon-folder-close:before { + content: "\e117"; +} +.glyphicon-folder-open:before { + content: "\e118"; +} +.glyphicon-resize-vertical:before { + content: "\e119"; +} +.glyphicon-resize-horizontal:before { + content: "\e120"; +} +.glyphicon-hdd:before { + content: "\e121"; +} +.glyphicon-bullhorn:before { + content: "\e122"; +} +.glyphicon-bell:before { + content: "\e123"; +} +.glyphicon-certificate:before { + content: "\e124"; +} +.glyphicon-thumbs-up:before { + content: "\e125"; +} +.glyphicon-thumbs-down:before { + content: "\e126"; +} +.glyphicon-hand-right:before { + content: "\e127"; +} +.glyphicon-hand-left:before { + content: "\e128"; +} +.glyphicon-hand-up:before { + content: "\e129"; +} +.glyphicon-hand-down:before { + content: "\e130"; +} +.glyphicon-circle-arrow-right:before { + content: "\e131"; +} +.glyphicon-circle-arrow-left:before { + content: "\e132"; +} +.glyphicon-circle-arrow-up:before { + content: "\e133"; +} +.glyphicon-circle-arrow-down:before { + content: "\e134"; +} +.glyphicon-globe:before { + content: "\e135"; +} +.glyphicon-wrench:before { + content: "\e136"; +} +.glyphicon-tasks:before { + content: "\e137"; +} +.glyphicon-filter:before { + content: "\e138"; +} +.glyphicon-briefcase:before { + content: "\e139"; +} +.glyphicon-fullscreen:before { + content: "\e140"; +} +.glyphicon-dashboard:before { + content: "\e141"; +} +.glyphicon-paperclip:before { + content: "\e142"; +} +.glyphicon-heart-empty:before { + content: "\e143"; +} +.glyphicon-link:before { + content: "\e144"; +} +.glyphicon-phone:before { + content: "\e145"; +} +.glyphicon-pushpin:before { + content: "\e146"; +} +.glyphicon-usd:before { + content: "\e148"; +} +.glyphicon-gbp:before { + content: "\e149"; +} +.glyphicon-sort:before { + content: "\e150"; +} +.glyphicon-sort-by-alphabet:before { + content: "\e151"; +} +.glyphicon-sort-by-alphabet-alt:before { + content: "\e152"; +} +.glyphicon-sort-by-order:before { + content: "\e153"; +} +.glyphicon-sort-by-order-alt:before { + content: "\e154"; +} +.glyphicon-sort-by-attributes:before { + content: "\e155"; +} +.glyphicon-sort-by-attributes-alt:before { + content: "\e156"; +} +.glyphicon-unchecked:before { + content: "\e157"; +} +.glyphicon-expand:before { + content: "\e158"; +} +.glyphicon-collapse-down:before { + content: "\e159"; +} +.glyphicon-collapse-up:before { + content: "\e160"; +} +.glyphicon-log-in:before { + content: "\e161"; +} +.glyphicon-flash:before { + content: "\e162"; +} +.glyphicon-log-out:before { + content: "\e163"; +} +.glyphicon-new-window:before { + content: "\e164"; +} +.glyphicon-record:before { + content: "\e165"; +} +.glyphicon-save:before { + content: "\e166"; +} +.glyphicon-open:before { + content: "\e167"; +} +.glyphicon-saved:before { + content: "\e168"; +} +.glyphicon-import:before { + content: "\e169"; +} +.glyphicon-export:before { + content: "\e170"; +} +.glyphicon-send:before { + content: "\e171"; +} +.glyphicon-floppy-disk:before { + content: "\e172"; +} +.glyphicon-floppy-saved:before { + content: "\e173"; +} +.glyphicon-floppy-remove:before { + content: "\e174"; +} +.glyphicon-floppy-save:before { + content: "\e175"; +} +.glyphicon-floppy-open:before { + content: "\e176"; +} +.glyphicon-credit-card:before { + content: "\e177"; +} +.glyphicon-transfer:before { + content: "\e178"; +} +.glyphicon-cutlery:before { + content: "\e179"; +} +.glyphicon-header:before { + content: "\e180"; +} +.glyphicon-compressed:before { + content: "\e181"; +} +.glyphicon-earphone:before { + content: "\e182"; +} +.glyphicon-phone-alt:before { + content: "\e183"; +} +.glyphicon-tower:before { + content: "\e184"; +} +.glyphicon-stats:before { + content: "\e185"; +} +.glyphicon-sd-video:before { + content: "\e186"; +} +.glyphicon-hd-video:before { + content: "\e187"; +} +.glyphicon-subtitles:before { + content: "\e188"; +} +.glyphicon-sound-stereo:before { + content: "\e189"; +} +.glyphicon-sound-dolby:before { + content: "\e190"; +} +.glyphicon-sound-5-1:before { + content: "\e191"; +} +.glyphicon-sound-6-1:before { + content: "\e192"; +} +.glyphicon-sound-7-1:before { + content: "\e193"; +} +.glyphicon-copyright-mark:before { + content: "\e194"; +} +.glyphicon-registration-mark:before { + content: "\e195"; +} +.glyphicon-cloud-download:before { + content: "\e197"; +} +.glyphicon-cloud-upload:before { + content: "\e198"; +} +.glyphicon-tree-conifer:before { + content: "\e199"; +} +.glyphicon-tree-deciduous:before { + content: "\e200"; +} +.glyphicon-cd:before { + content: "\e201"; +} +.glyphicon-save-file:before { + content: "\e202"; +} +.glyphicon-open-file:before { + content: "\e203"; +} +.glyphicon-level-up:before { + content: "\e204"; +} +.glyphicon-copy:before { + content: "\e205"; +} +.glyphicon-paste:before { + content: "\e206"; +} +.glyphicon-alert:before { + content: "\e209"; +} +.glyphicon-equalizer:before { + content: "\e210"; +} +.glyphicon-king:before { + content: "\e211"; +} +.glyphicon-queen:before { + content: "\e212"; +} +.glyphicon-pawn:before { + content: "\e213"; +} +.glyphicon-bishop:before { + content: "\e214"; +} +.glyphicon-knight:before { + content: "\e215"; +} +.glyphicon-baby-formula:before { + content: "\e216"; +} +.glyphicon-tent:before { + content: "\26fa"; +} +.glyphicon-blackboard:before { + content: "\e218"; +} +.glyphicon-bed:before { + content: "\e219"; +} +.glyphicon-apple:before { + content: "\f8ff"; +} +.glyphicon-erase:before { + content: "\e221"; +} +.glyphicon-hourglass:before { + content: "\231b"; +} +.glyphicon-lamp:before { + content: "\e223"; +} +.glyphicon-duplicate:before { + content: "\e224"; +} +.glyphicon-piggy-bank:before { + content: "\e225"; +} +.glyphicon-scissors:before { + content: "\e226"; +} +.glyphicon-bitcoin:before { + content: "\e227"; +} +.glyphicon-btc:before { + content: "\e227"; +} +.glyphicon-xbt:before { + content: "\e227"; +} +.glyphicon-yen:before { + content: "\00a5"; +} +.glyphicon-jpy:before { + content: "\00a5"; +} +.glyphicon-ruble:before { + content: "\20bd"; +} +.glyphicon-rub:before { + content: "\20bd"; +} +.glyphicon-scale:before { + content: "\e230"; +} +.glyphicon-ice-lolly:before { + content: "\e231"; +} +.glyphicon-ice-lolly-tasted:before { + content: "\e232"; +} +.glyphicon-education:before { + content: "\e233"; +} +.glyphicon-option-horizontal:before { + content: "\e234"; +} +.glyphicon-option-vertical:before { + content: "\e235"; +} +.glyphicon-menu-hamburger:before { + content: "\e236"; +} +.glyphicon-modal-window:before { + content: "\e237"; +} +.glyphicon-oil:before { + content: "\e238"; +} +.glyphicon-grain:before { + content: "\e239"; +} +.glyphicon-sunglasses:before { + content: "\e240"; +} +.glyphicon-text-size:before { + content: "\e241"; +} +.glyphicon-text-color:before { + content: "\e242"; +} +.glyphicon-text-background:before { + content: "\e243"; +} +.glyphicon-object-align-top:before { + content: "\e244"; +} +.glyphicon-object-align-bottom:before { + content: "\e245"; +} +.glyphicon-object-align-horizontal:before { + content: "\e246"; +} +.glyphicon-object-align-left:before { + content: "\e247"; +} +.glyphicon-object-align-vertical:before { + content: "\e248"; +} +.glyphicon-object-align-right:before { + content: "\e249"; +} +.glyphicon-triangle-right:before { + content: "\e250"; +} +.glyphicon-triangle-left:before { + content: "\e251"; +} +.glyphicon-triangle-bottom:before { + content: "\e252"; +} +.glyphicon-triangle-top:before { + content: "\e253"; +} +.glyphicon-console:before { + content: "\e254"; +} +.glyphicon-superscript:before { + content: "\e255"; +} +.glyphicon-subscript:before { + content: "\e256"; +} +.glyphicon-menu-left:before { + content: "\e257"; +} +.glyphicon-menu-right:before { + content: "\e258"; +} +.glyphicon-menu-down:before { + content: "\e259"; +} +.glyphicon-menu-up:before { + content: "\e260"; +} +* { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} +*:before, +*:after { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} +html { + font-size: 10px; + -webkit-tap-highlight-color: rgba(0, 0, 0, 0); +} +body { + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: 14px; + line-height: 1.42857143; + color: #333; + background-color: #fff; +} +input, +button, +select, +textarea { + font-family: inherit; + font-size: inherit; + line-height: inherit; +} +a { + color: #337ab7; + text-decoration: none; +} +a:hover, +a:focus { + color: #23527c; + text-decoration: underline; +} +a:focus { + outline: thin dotted; + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; +} +figure { + margin: 0; +} +img { + vertical-align: middle; +} +.img-responsive, +.thumbnail > img, +.thumbnail a > img, +.carousel-inner > .item > img, +.carousel-inner > .item > a > img { + display: block; + max-width: 100%; + height: auto; +} +.img-rounded { + border-radius: 6px; +} +.img-thumbnail { + padding: 4px; + line-height: 1.42857143; + background-color: #fff; + border: 1px solid #ddd; + border-radius: 4px; + -webkit-transition: all 0.2s ease-in-out; + -o-transition: all 0.2s ease-in-out; + transition: all 0.2s ease-in-out; + display: inline-block; + max-width: 100%; + height: auto; +} +.img-circle { + border-radius: 50%; +} +hr { + margin-top: 20px; + margin-bottom: 20px; + border: 0; + border-top: 1px solid #eee; +} +.sr-only { + position: absolute; + width: 1px; + height: 1px; + margin: -1px; + padding: 0; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0; +} +.sr-only-focusable:active, +.sr-only-focusable:focus { + position: static; + width: auto; + height: auto; + margin: 0; + overflow: visible; + clip: auto; +} +[role="button"] { + cursor: pointer; +} +h1, +h2, +h3, +h4, +h5, +h6, +.h1, +.h2, +.h3, +.h4, +.h5, +.h6 { + font-family: inherit; + font-weight: 500; + line-height: 1.1; + color: inherit; +} +h1 small, +h2 small, +h3 small, +h4 small, +h5 small, +h6 small, +.h1 small, +.h2 small, +.h3 small, +.h4 small, +.h5 small, +.h6 small, +h1 .small, +h2 .small, +h3 .small, +h4 .small, +h5 .small, +h6 .small, +.h1 .small, +.h2 .small, +.h3 .small, +.h4 .small, +.h5 .small, +.h6 .small { + font-weight: normal; + line-height: 1; + color: #777; +} +h1, +.h1, +h2, +.h2, +h3, +.h3 { + margin-top: 20px; + margin-bottom: 10px; +} +h1 small, +.h1 small, +h2 small, +.h2 small, +h3 small, +.h3 small, +h1 .small, +.h1 .small, +h2 .small, +.h2 .small, +h3 .small, +.h3 .small { + font-size: 65%; +} +h4, +.h4, +h5, +.h5, +h6, +.h6 { + margin-top: 10px; + margin-bottom: 10px; +} +h4 small, +.h4 small, +h5 small, +.h5 small, +h6 small, +.h6 small, +h4 .small, +.h4 .small, +h5 .small, +.h5 .small, +h6 .small, +.h6 .small { + font-size: 75%; +} +h1, +.h1 { + font-size: 36px; +} +h2, +.h2 { + font-size: 30px; +} +h3, +.h3 { + font-size: 24px; +} +h4, +.h4 { + font-size: 18px; +} +h5, +.h5 { + font-size: 14px; +} +h6, +.h6 { + font-size: 12px; +} +p { + margin: 0 0 10px; +} +.lead { + margin-bottom: 20px; + font-size: 16px; + font-weight: 300; + line-height: 1.4; +} +@media (min-width: 768px) { + .lead { + font-size: 21px; + } +} +small, +.small { + font-size: 85%; +} +mark, +.mark { + background-color: #fcf8e3; + padding: 0.2em; +} +.text-left { + text-align: left; +} +.text-right { + text-align: right; +} +.text-center { + text-align: center; +} +.text-justify { + text-align: justify; +} +.text-nowrap { + white-space: nowrap; +} +.text-lowercase { + text-transform: lowercase; +} +.text-uppercase { + text-transform: uppercase; +} +.text-capitalize { + text-transform: capitalize; +} +.text-muted { + color: #777; +} +.text-primary { + color: #337ab7; +} +a.text-primary:hover, +a.text-primary:focus { + color: #286090; +} +.text-success { + color: #3c763d; +} +a.text-success:hover, +a.text-success:focus { + color: #2b542c; +} +.text-info { + color: #31708f; +} +a.text-info:hover, +a.text-info:focus { + color: #245269; +} +.text-warning { + color: #8a6d3b; +} +a.text-warning:hover, +a.text-warning:focus { + color: #66512c; +} +.text-danger { + color: #a94442; +} +a.text-danger:hover, +a.text-danger:focus { + color: #843534; +} +.bg-primary { + color: #fff; + background-color: #337ab7; +} +a.bg-primary:hover, +a.bg-primary:focus { + background-color: #286090; +} +.bg-success { + background-color: #dff0d8; +} +a.bg-success:hover, +a.bg-success:focus { + background-color: #c1e2b3; +} +.bg-info { + background-color: #d9edf7; +} +a.bg-info:hover, +a.bg-info:focus { + background-color: #afd9ee; +} +.bg-warning { + background-color: #fcf8e3; +} +a.bg-warning:hover, +a.bg-warning:focus { + background-color: #f7ecb5; +} +.bg-danger { + background-color: #f2dede; +} +a.bg-danger:hover, +a.bg-danger:focus { + background-color: #e4b9b9; +} +.page-header { + padding-bottom: 9px; + margin: 40px 0 20px; + border-bottom: 1px solid #eee; +} +ul, +ol { + margin-top: 0; + margin-bottom: 10px; +} +ul ul, +ol ul, +ul ol, +ol ol { + margin-bottom: 0; +} +.list-unstyled { + padding-left: 0; + list-style: none; +} +.list-inline { + padding-left: 0; + list-style: none; + margin-left: -5px; +} +.list-inline > li { + display: inline-block; + padding-left: 5px; + padding-right: 5px; +} +dl { + margin-top: 0; + margin-bottom: 20px; +} +dt, +dd { + line-height: 1.42857143; +} +dt { + font-weight: bold; +} +dd { + margin-left: 0; +} +@media (min-width: 768px) { + .dl-horizontal dt { + float: left; + width: 160px; + clear: left; + text-align: right; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } + .dl-horizontal dd { + margin-left: 180px; + } +} +abbr[title], +abbr[data-original-title] { + cursor: help; + border-bottom: 1px dotted #777; +} +.initialism { + font-size: 90%; + text-transform: uppercase; +} +blockquote { + padding: 10px 20px; + margin: 0 0 20px; + font-size: 17.5px; + border-left: 5px solid #eee; +} +blockquote p:last-child, +blockquote ul:last-child, +blockquote ol:last-child { + margin-bottom: 0; +} +blockquote footer, +blockquote small, +blockquote .small { + display: block; + font-size: 80%; + line-height: 1.42857143; + color: #777; +} +blockquote footer:before, +blockquote small:before, +blockquote .small:before { + content: "\2014 \00A0"; +} +.blockquote-reverse, +blockquote.pull-right { + padding-right: 15px; + padding-left: 0; + border-right: 5px solid #eee; + border-left: 0; + text-align: right; +} +.blockquote-reverse footer:before, +blockquote.pull-right footer:before, +.blockquote-reverse small:before, +blockquote.pull-right small:before, +.blockquote-reverse .small:before, +blockquote.pull-right .small:before { + content: ""; +} +.blockquote-reverse footer:after, +blockquote.pull-right footer:after, +.blockquote-reverse small:after, +blockquote.pull-right small:after, +.blockquote-reverse .small:after, +blockquote.pull-right .small:after { + content: "\00A0 \2014"; +} +address { + margin-bottom: 20px; + font-style: normal; + line-height: 1.42857143; +} +code, +kbd, +pre, +samp { + font-family: Menlo, Monaco, Consolas, "Courier New", monospace; +} +code { + padding: 2px 4px; + font-size: 90%; + color: #c7254e; + background-color: #f9f2f4; + border-radius: 4px; +} +kbd { + padding: 2px 4px; + font-size: 90%; + color: #fff; + background-color: #333; + border-radius: 3px; + -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.25); + box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.25); +} +kbd kbd { + padding: 0; + font-size: 100%; + font-weight: bold; + -webkit-box-shadow: none; + box-shadow: none; +} +pre { + display: block; + padding: 9.5px; + margin: 0 0 10px; + font-size: 13px; + line-height: 1.42857143; + word-break: break-all; + word-wrap: break-word; + color: #333; + background-color: #f5f7f8; + border: 1px solid #ccc; + border-radius: 4px; +} +pre code { + padding: 0; + font-size: inherit; + color: inherit; + white-space: pre-wrap; + background-color: transparent; + border-radius: 0; +} +.pre-scrollable { + max-height: 340px; + overflow-y: scroll; +} +.container { + margin-right: auto; + margin-left: auto; + padding-left: 15px; + padding-right: 15px; +} +@media (min-width: 768px) { + .container { + width: 750px; + } +} +@media (min-width: 992px) { + .container { + width: 970px; + } +} +@media (min-width: 1200px) { + .container { + width: 1170px; + } +} +.container-fluid { + margin-right: auto; + margin-left: auto; + padding-left: 15px; + padding-right: 15px; +} +.row { + margin-left: -15px; + margin-right: -15px; +} +.col-xs-1, +.col-sm-1, +.col-md-1, +.col-lg-1, +.col-xs-2, +.col-sm-2, +.col-md-2, +.col-lg-2, +.col-xs-3, +.col-sm-3, +.col-md-3, +.col-lg-3, +.col-xs-4, +.col-sm-4, +.col-md-4, +.col-lg-4, +.col-xs-5, +.col-sm-5, +.col-md-5, +.col-lg-5, +.col-xs-6, +.col-sm-6, +.col-md-6, +.col-lg-6, +.col-xs-7, +.col-sm-7, +.col-md-7, +.col-lg-7, +.col-xs-8, +.col-sm-8, +.col-md-8, +.col-lg-8, +.col-xs-9, +.col-sm-9, +.col-md-9, +.col-lg-9, +.col-xs-10, +.col-sm-10, +.col-md-10, +.col-lg-10, +.col-xs-11, +.col-sm-11, +.col-md-11, +.col-lg-11, +.col-xs-12, +.col-sm-12, +.col-md-12, +.col-lg-12 { + position: relative; + min-height: 1px; + padding-left: 15px; + padding-right: 15px; +} +.col-xs-1, +.col-xs-2, +.col-xs-3, +.col-xs-4, +.col-xs-5, +.col-xs-6, +.col-xs-7, +.col-xs-8, +.col-xs-9, +.col-xs-10, +.col-xs-11, +.col-xs-12 { + float: left; +} +.col-xs-12 { + width: 100%; +} +.col-xs-11 { + width: 91.66666667%; +} +.col-xs-10 { + width: 83.33333333%; +} +.col-xs-9 { + width: 75%; +} +.col-xs-8 { + width: 66.66666667%; +} +.col-xs-7 { + width: 58.33333333%; +} +.col-xs-6 { + width: 50%; +} +.col-xs-5 { + width: 41.66666667%; +} +.col-xs-4 { + width: 33.33333333%; +} +.col-xs-3 { + width: 25%; +} +.col-xs-2 { + width: 16.66666667%; +} +.col-xs-1 { + width: 8.33333333%; +} +.col-xs-pull-12 { + right: 100%; +} +.col-xs-pull-11 { + right: 91.66666667%; +} +.col-xs-pull-10 { + right: 83.33333333%; +} +.col-xs-pull-9 { + right: 75%; +} +.col-xs-pull-8 { + right: 66.66666667%; +} +.col-xs-pull-7 { + right: 58.33333333%; +} +.col-xs-pull-6 { + right: 50%; +} +.col-xs-pull-5 { + right: 41.66666667%; +} +.col-xs-pull-4 { + right: 33.33333333%; +} +.col-xs-pull-3 { + right: 25%; +} +.col-xs-pull-2 { + right: 16.66666667%; +} +.col-xs-pull-1 { + right: 8.33333333%; +} +.col-xs-pull-0 { + right: auto; +} +.col-xs-push-12 { + left: 100%; +} +.col-xs-push-11 { + left: 91.66666667%; +} +.col-xs-push-10 { + left: 83.33333333%; +} +.col-xs-push-9 { + left: 75%; +} +.col-xs-push-8 { + left: 66.66666667%; +} +.col-xs-push-7 { + left: 58.33333333%; +} +.col-xs-push-6 { + left: 50%; +} +.col-xs-push-5 { + left: 41.66666667%; +} +.col-xs-push-4 { + left: 33.33333333%; +} +.col-xs-push-3 { + left: 25%; +} +.col-xs-push-2 { + left: 16.66666667%; +} +.col-xs-push-1 { + left: 8.33333333%; +} +.col-xs-push-0 { + left: auto; +} +.col-xs-offset-12 { + margin-left: 100%; +} +.col-xs-offset-11 { + margin-left: 91.66666667%; +} +.col-xs-offset-10 { + margin-left: 83.33333333%; +} +.col-xs-offset-9 { + margin-left: 75%; +} +.col-xs-offset-8 { + margin-left: 66.66666667%; +} +.col-xs-offset-7 { + margin-left: 58.33333333%; +} +.col-xs-offset-6 { + margin-left: 50%; +} +.col-xs-offset-5 { + margin-left: 41.66666667%; +} +.col-xs-offset-4 { + margin-left: 33.33333333%; +} +.col-xs-offset-3 { + margin-left: 25%; +} +.col-xs-offset-2 { + margin-left: 16.66666667%; +} +.col-xs-offset-1 { + margin-left: 8.33333333%; +} +.col-xs-offset-0 { + margin-left: 0; +} +@media (min-width: 768px) { + .col-sm-1, + .col-sm-2, + .col-sm-3, + .col-sm-4, + .col-sm-5, + .col-sm-6, + .col-sm-7, + .col-sm-8, + .col-sm-9, + .col-sm-10, + .col-sm-11, + .col-sm-12 { + float: left; + } + .col-sm-12 { + width: 100%; + } + .col-sm-11 { + width: 91.66666667%; + } + .col-sm-10 { + width: 83.33333333%; + } + .col-sm-9 { + width: 75%; + } + .col-sm-8 { + width: 66.66666667%; + } + .col-sm-7 { + width: 58.33333333%; + } + .col-sm-6 { + width: 50%; + } + .col-sm-5 { + width: 41.66666667%; + } + .col-sm-4 { + width: 33.33333333%; + } + .col-sm-3 { + width: 25%; + } + .col-sm-2 { + width: 16.66666667%; + } + .col-sm-1 { + width: 8.33333333%; + } + .col-sm-pull-12 { + right: 100%; + } + .col-sm-pull-11 { + right: 91.66666667%; + } + .col-sm-pull-10 { + right: 83.33333333%; + } + .col-sm-pull-9 { + right: 75%; + } + .col-sm-pull-8 { + right: 66.66666667%; + } + .col-sm-pull-7 { + right: 58.33333333%; + } + .col-sm-pull-6 { + right: 50%; + } + .col-sm-pull-5 { + right: 41.66666667%; + } + .col-sm-pull-4 { + right: 33.33333333%; + } + .col-sm-pull-3 { + right: 25%; + } + .col-sm-pull-2 { + right: 16.66666667%; + } + .col-sm-pull-1 { + right: 8.33333333%; + } + .col-sm-pull-0 { + right: auto; + } + .col-sm-push-12 { + left: 100%; + } + .col-sm-push-11 { + left: 91.66666667%; + } + .col-sm-push-10 { + left: 83.33333333%; + } + .col-sm-push-9 { + left: 75%; + } + .col-sm-push-8 { + left: 66.66666667%; + } + .col-sm-push-7 { + left: 58.33333333%; + } + .col-sm-push-6 { + left: 50%; + } + .col-sm-push-5 { + left: 41.66666667%; + } + .col-sm-push-4 { + left: 33.33333333%; + } + .col-sm-push-3 { + left: 25%; + } + .col-sm-push-2 { + left: 16.66666667%; + } + .col-sm-push-1 { + left: 8.33333333%; + } + .col-sm-push-0 { + left: auto; + } + .col-sm-offset-12 { + margin-left: 100%; + } + .col-sm-offset-11 { + margin-left: 91.66666667%; + } + .col-sm-offset-10 { + margin-left: 83.33333333%; + } + .col-sm-offset-9 { + margin-left: 75%; + } + .col-sm-offset-8 { + margin-left: 66.66666667%; + } + .col-sm-offset-7 { + margin-left: 58.33333333%; + } + .col-sm-offset-6 { + margin-left: 50%; + } + .col-sm-offset-5 { + margin-left: 41.66666667%; + } + .col-sm-offset-4 { + margin-left: 33.33333333%; + } + .col-sm-offset-3 { + margin-left: 25%; + } + .col-sm-offset-2 { + margin-left: 16.66666667%; + } + .col-sm-offset-1 { + margin-left: 8.33333333%; + } + .col-sm-offset-0 { + margin-left: 0; + } +} +@media (min-width: 992px) { + .col-md-1, + .col-md-2, + .col-md-3, + .col-md-4, + .col-md-5, + .col-md-6, + .col-md-7, + .col-md-8, + .col-md-9, + .col-md-10, + .col-md-11, + .col-md-12 { + float: left; + } + .col-md-12 { + width: 100%; + } + .col-md-11 { + width: 91.66666667%; + } + .col-md-10 { + width: 83.33333333%; + } + .col-md-9 { + width: 75%; + } + .col-md-8 { + width: 66.66666667%; + } + .col-md-7 { + width: 58.33333333%; + } + .col-md-6 { + width: 50%; + } + .col-md-5 { + width: 41.66666667%; + } + .col-md-4 { + width: 33.33333333%; + } + .col-md-3 { + width: 25%; + } + .col-md-2 { + width: 16.66666667%; + } + .col-md-1 { + width: 8.33333333%; + } + .col-md-pull-12 { + right: 100%; + } + .col-md-pull-11 { + right: 91.66666667%; + } + .col-md-pull-10 { + right: 83.33333333%; + } + .col-md-pull-9 { + right: 75%; + } + .col-md-pull-8 { + right: 66.66666667%; + } + .col-md-pull-7 { + right: 58.33333333%; + } + .col-md-pull-6 { + right: 50%; + } + .col-md-pull-5 { + right: 41.66666667%; + } + .col-md-pull-4 { + right: 33.33333333%; + } + .col-md-pull-3 { + right: 25%; + } + .col-md-pull-2 { + right: 16.66666667%; + } + .col-md-pull-1 { + right: 8.33333333%; + } + .col-md-pull-0 { + right: auto; + } + .col-md-push-12 { + left: 100%; + } + .col-md-push-11 { + left: 91.66666667%; + } + .col-md-push-10 { + left: 83.33333333%; + } + .col-md-push-9 { + left: 75%; + } + .col-md-push-8 { + left: 66.66666667%; + } + .col-md-push-7 { + left: 58.33333333%; + } + .col-md-push-6 { + left: 50%; + } + .col-md-push-5 { + left: 41.66666667%; + } + .col-md-push-4 { + left: 33.33333333%; + } + .col-md-push-3 { + left: 25%; + } + .col-md-push-2 { + left: 16.66666667%; + } + .col-md-push-1 { + left: 8.33333333%; + } + .col-md-push-0 { + left: auto; + } + .col-md-offset-12 { + margin-left: 100%; + } + .col-md-offset-11 { + margin-left: 91.66666667%; + } + .col-md-offset-10 { + margin-left: 83.33333333%; + } + .col-md-offset-9 { + margin-left: 75%; + } + .col-md-offset-8 { + margin-left: 66.66666667%; + } + .col-md-offset-7 { + margin-left: 58.33333333%; + } + .col-md-offset-6 { + margin-left: 50%; + } + .col-md-offset-5 { + margin-left: 41.66666667%; + } + .col-md-offset-4 { + margin-left: 33.33333333%; + } + .col-md-offset-3 { + margin-left: 25%; + } + .col-md-offset-2 { + margin-left: 16.66666667%; + } + .col-md-offset-1 { + margin-left: 8.33333333%; + } + .col-md-offset-0 { + margin-left: 0; + } +} +@media (min-width: 1200px) { + .col-lg-1, + .col-lg-2, + .col-lg-3, + .col-lg-4, + .col-lg-5, + .col-lg-6, + .col-lg-7, + .col-lg-8, + .col-lg-9, + .col-lg-10, + .col-lg-11, + .col-lg-12 { + float: left; + } + .col-lg-12 { + width: 100%; + } + .col-lg-11 { + width: 91.66666667%; + } + .col-lg-10 { + width: 83.33333333%; + } + .col-lg-9 { + width: 75%; + } + .col-lg-8 { + width: 66.66666667%; + } + .col-lg-7 { + width: 58.33333333%; + } + .col-lg-6 { + width: 50%; + } + .col-lg-5 { + width: 41.66666667%; + } + .col-lg-4 { + width: 33.33333333%; + } + .col-lg-3 { + width: 25%; + } + .col-lg-2 { + width: 16.66666667%; + } + .col-lg-1 { + width: 8.33333333%; + } + .col-lg-pull-12 { + right: 100%; + } + .col-lg-pull-11 { + right: 91.66666667%; + } + .col-lg-pull-10 { + right: 83.33333333%; + } + .col-lg-pull-9 { + right: 75%; + } + .col-lg-pull-8 { + right: 66.66666667%; + } + .col-lg-pull-7 { + right: 58.33333333%; + } + .col-lg-pull-6 { + right: 50%; + } + .col-lg-pull-5 { + right: 41.66666667%; + } + .col-lg-pull-4 { + right: 33.33333333%; + } + .col-lg-pull-3 { + right: 25%; + } + .col-lg-pull-2 { + right: 16.66666667%; + } + .col-lg-pull-1 { + right: 8.33333333%; + } + .col-lg-pull-0 { + right: auto; + } + .col-lg-push-12 { + left: 100%; + } + .col-lg-push-11 { + left: 91.66666667%; + } + .col-lg-push-10 { + left: 83.33333333%; + } + .col-lg-push-9 { + left: 75%; + } + .col-lg-push-8 { + left: 66.66666667%; + } + .col-lg-push-7 { + left: 58.33333333%; + } + .col-lg-push-6 { + left: 50%; + } + .col-lg-push-5 { + left: 41.66666667%; + } + .col-lg-push-4 { + left: 33.33333333%; + } + .col-lg-push-3 { + left: 25%; + } + .col-lg-push-2 { + left: 16.66666667%; + } + .col-lg-push-1 { + left: 8.33333333%; + } + .col-lg-push-0 { + left: auto; + } + .col-lg-offset-12 { + margin-left: 100%; + } + .col-lg-offset-11 { + margin-left: 91.66666667%; + } + .col-lg-offset-10 { + margin-left: 83.33333333%; + } + .col-lg-offset-9 { + margin-left: 75%; + } + .col-lg-offset-8 { + margin-left: 66.66666667%; + } + .col-lg-offset-7 { + margin-left: 58.33333333%; + } + .col-lg-offset-6 { + margin-left: 50%; + } + .col-lg-offset-5 { + margin-left: 41.66666667%; + } + .col-lg-offset-4 { + margin-left: 33.33333333%; + } + .col-lg-offset-3 { + margin-left: 25%; + } + .col-lg-offset-2 { + margin-left: 16.66666667%; + } + .col-lg-offset-1 { + margin-left: 8.33333333%; + } + .col-lg-offset-0 { + margin-left: 0; + } +} +table { + background-color: transparent; +} +caption { + padding-top: 8px; + padding-bottom: 8px; + color: #777; + text-align: left; +} +th { + text-align: left; +} +.table { + width: 100%; + max-width: 100%; + margin-bottom: 20px; +} +.table > thead > tr > th, +.table > tbody > tr > th, +.table > tfoot > tr > th, +.table > thead > tr > td, +.table > tbody > tr > td, +.table > tfoot > tr > td { + padding: 8px; + line-height: 1.42857143; + vertical-align: top; + border-top: 1px solid #ddd; +} +.table > thead > tr > th { + vertical-align: bottom; + border-bottom: 2px solid #ddd; +} +.table > caption + thead > tr:first-child > th, +.table > colgroup + thead > tr:first-child > th, +.table > thead:first-child > tr:first-child > th, +.table > caption + thead > tr:first-child > td, +.table > colgroup + thead > tr:first-child > td, +.table > thead:first-child > tr:first-child > td { + border-top: 0; +} +.table > tbody + tbody { + border-top: 2px solid #ddd; +} +.table .table { + background-color: #fff; +} +.table-condensed > thead > tr > th, +.table-condensed > tbody > tr > th, +.table-condensed > tfoot > tr > th, +.table-condensed > thead > tr > td, +.table-condensed > tbody > tr > td, +.table-condensed > tfoot > tr > td { + padding: 5px; +} +.table-bordered { + border: 1px solid #ddd; +} +.table-bordered > thead > tr > th, +.table-bordered > tbody > tr > th, +.table-bordered > tfoot > tr > th, +.table-bordered > thead > tr > td, +.table-bordered > tbody > tr > td, +.table-bordered > tfoot > tr > td { + border: 1px solid #ddd; +} +.table-bordered > thead > tr > th, +.table-bordered > thead > tr > td { + border-bottom-width: 2px; +} +.table-striped > tbody > tr:nth-of-type(odd) { + background-color: #f9f9f9; +} +.table-hover > tbody > tr:hover { + background-color: #f5f7f8; +} +table col[class*="col-"] { + position: static; + float: none; + display: table-column; +} +table td[class*="col-"], +table th[class*="col-"] { + position: static; + float: none; + display: table-cell; +} +.table > thead > tr > td.active, +.table > tbody > tr > td.active, +.table > tfoot > tr > td.active, +.table > thead > tr > th.active, +.table > tbody > tr > th.active, +.table > tfoot > tr > th.active, +.table > thead > tr.active > td, +.table > tbody > tr.active > td, +.table > tfoot > tr.active > td, +.table > thead > tr.active > th, +.table > tbody > tr.active > th, +.table > tfoot > tr.active > th { + background-color: #f5f7f8; +} +.table-hover > tbody > tr > td.active:hover, +.table-hover > tbody > tr > th.active:hover, +.table-hover > tbody > tr.active:hover > td, +.table-hover > tbody > tr:hover > .active, +.table-hover > tbody > tr.active:hover > th { + background-color: #e6ebed; +} +.table > thead > tr > td.success, +.table > tbody > tr > td.success, +.table > tfoot > tr > td.success, +.table > thead > tr > th.success, +.table > tbody > tr > th.success, +.table > tfoot > tr > th.success, +.table > thead > tr.success > td, +.table > tbody > tr.success > td, +.table > tfoot > tr.success > td, +.table > thead > tr.success > th, +.table > tbody > tr.success > th, +.table > tfoot > tr.success > th { + background-color: #dff0d8; +} +.table-hover > tbody > tr > td.success:hover, +.table-hover > tbody > tr > th.success:hover, +.table-hover > tbody > tr.success:hover > td, +.table-hover > tbody > tr:hover > .success, +.table-hover > tbody > tr.success:hover > th { + background-color: #d0e9c6; +} +.table > thead > tr > td.info, +.table > tbody > tr > td.info, +.table > tfoot > tr > td.info, +.table > thead > tr > th.info, +.table > tbody > tr > th.info, +.table > tfoot > tr > th.info, +.table > thead > tr.info > td, +.table > tbody > tr.info > td, +.table > tfoot > tr.info > td, +.table > thead > tr.info > th, +.table > tbody > tr.info > th, +.table > tfoot > tr.info > th { + background-color: #d9edf7; +} +.table-hover > tbody > tr > td.info:hover, +.table-hover > tbody > tr > th.info:hover, +.table-hover > tbody > tr.info:hover > td, +.table-hover > tbody > tr:hover > .info, +.table-hover > tbody > tr.info:hover > th { + background-color: #c4e3f3; +} +.table > thead > tr > td.warning, +.table > tbody > tr > td.warning, +.table > tfoot > tr > td.warning, +.table > thead > tr > th.warning, +.table > tbody > tr > th.warning, +.table > tfoot > tr > th.warning, +.table > thead > tr.warning > td, +.table > tbody > tr.warning > td, +.table > tfoot > tr.warning > td, +.table > thead > tr.warning > th, +.table > tbody > tr.warning > th, +.table > tfoot > tr.warning > th { + background-color: #fcf8e3; +} +.table-hover > tbody > tr > td.warning:hover, +.table-hover > tbody > tr > th.warning:hover, +.table-hover > tbody > tr.warning:hover > td, +.table-hover > tbody > tr:hover > .warning, +.table-hover > tbody > tr.warning:hover > th { + background-color: #faf2cc; +} +.table > thead > tr > td.danger, +.table > tbody > tr > td.danger, +.table > tfoot > tr > td.danger, +.table > thead > tr > th.danger, +.table > tbody > tr > th.danger, +.table > tfoot > tr > th.danger, +.table > thead > tr.danger > td, +.table > tbody > tr.danger > td, +.table > tfoot > tr.danger > td, +.table > thead > tr.danger > th, +.table > tbody > tr.danger > th, +.table > tfoot > tr.danger > th { + background-color: #f2dede; +} +.table-hover > tbody > tr > td.danger:hover, +.table-hover > tbody > tr > th.danger:hover, +.table-hover > tbody > tr.danger:hover > td, +.table-hover > tbody > tr:hover > .danger, +.table-hover > tbody > tr.danger:hover > th { + background-color: #ebcccc; +} +.table-responsive { + overflow-x: auto; + min-height: 0.01%; +} +@media screen and (max-width: 767px) { + .table-responsive { + width: 100%; + margin-bottom: 15px; + overflow-y: hidden; + -ms-overflow-style: -ms-autohiding-scrollbar; + border: 1px solid #ddd; + } + .table-responsive > .table { + margin-bottom: 0; + } + .table-responsive > .table > thead > tr > th, + .table-responsive > .table > tbody > tr > th, + .table-responsive > .table > tfoot > tr > th, + .table-responsive > .table > thead > tr > td, + .table-responsive > .table > tbody > tr > td, + .table-responsive > .table > tfoot > tr > td { + white-space: nowrap; + } + .table-responsive > .table-bordered { + border: 0; + } + .table-responsive > .table-bordered > thead > tr > th:first-child, + .table-responsive > .table-bordered > tbody > tr > th:first-child, + .table-responsive > .table-bordered > tfoot > tr > th:first-child, + .table-responsive > .table-bordered > thead > tr > td:first-child, + .table-responsive > .table-bordered > tbody > tr > td:first-child, + .table-responsive > .table-bordered > tfoot > tr > td:first-child { + border-left: 0; + } + .table-responsive > .table-bordered > thead > tr > th:last-child, + .table-responsive > .table-bordered > tbody > tr > th:last-child, + .table-responsive > .table-bordered > tfoot > tr > th:last-child, + .table-responsive > .table-bordered > thead > tr > td:last-child, + .table-responsive > .table-bordered > tbody > tr > td:last-child, + .table-responsive > .table-bordered > tfoot > tr > td:last-child { + border-right: 0; + } + .table-responsive > .table-bordered > tbody > tr:last-child > th, + .table-responsive > .table-bordered > tfoot > tr:last-child > th, + .table-responsive > .table-bordered > tbody > tr:last-child > td, + .table-responsive > .table-bordered > tfoot > tr:last-child > td { + border-bottom: 0; + } +} +fieldset { + padding: 0; + margin: 0; + border: 0; + min-width: 0; +} +legend { + display: block; + width: 100%; + padding: 0; + margin-bottom: 20px; + font-size: 21px; + line-height: inherit; + color: #333; + border: 0; + border-bottom: 1px solid #e5e5e5; +} +label { + display: inline-block; + max-width: 100%; + margin-bottom: 5px; + font-weight: bold; +} +input[type="search"] { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} +input[type="radio"], +input[type="checkbox"] { + margin: 4px 0 0; + margin-top: 1px \9; + line-height: normal; +} +input[type="file"] { + display: block; +} +input[type="range"] { + display: block; + width: 100%; +} +select[multiple], +select[size] { + height: auto; +} +input[type="file"]:focus, +input[type="radio"]:focus, +input[type="checkbox"]:focus { + outline: thin dotted; + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; +} +output { + display: block; + padding-top: 7px; + font-size: 14px; + line-height: 1.42857143; + color: #555; +} +.form-control { + display: block; + width: 100%; + height: 34px; + padding: 6px 12px; + font-size: 14px; + line-height: 1.42857143; + color: #555; + background-color: #fff; + background-image: none; + border: 1px solid #ccc; + border-radius: 4px; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + -webkit-transition: border-color ease-in-out 0.15s, + -webkit-box-shadow ease-in-out 0.15s; + -o-transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s; + transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s; +} +.form-control:focus { + border-color: #66afe9; + outline: 0; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), + 0 0 8px rgba(102, 175, 233, 0.6); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), + 0 0 8px rgba(102, 175, 233, 0.6); +} +.form-control::-moz-placeholder { + color: #999; + opacity: 1; +} +.form-control:-ms-input-placeholder { + color: #999; +} +.form-control::-webkit-input-placeholder { + color: #999; +} +.form-control::-ms-expand { + border: 0; + background-color: transparent; +} +.form-control[disabled], +.form-control[readonly], +fieldset[disabled] .form-control { + background-color: #eee; + opacity: 1; +} +.form-control[disabled], +fieldset[disabled] .form-control { + cursor: not-allowed; +} +textarea.form-control { + height: auto; +} +input[type="search"] { + -webkit-appearance: none; +} +@media screen and (-webkit-min-device-pixel-ratio: 0) { + input[type="date"].form-control, + input[type="time"].form-control, + input[type="datetime-local"].form-control, + input[type="month"].form-control { + line-height: 34px; + } + input[type="date"].input-sm, + input[type="time"].input-sm, + input[type="datetime-local"].input-sm, + input[type="month"].input-sm, + .input-group-sm input[type="date"], + .input-group-sm input[type="time"], + .input-group-sm input[type="datetime-local"], + .input-group-sm input[type="month"] { + line-height: 30px; + } + input[type="date"].input-lg, + input[type="time"].input-lg, + input[type="datetime-local"].input-lg, + input[type="month"].input-lg, + .input-group-lg input[type="date"], + .input-group-lg input[type="time"], + .input-group-lg input[type="datetime-local"], + .input-group-lg input[type="month"] { + line-height: 46px; + } +} +.form-group { + margin-bottom: 15px; +} +.radio, +.checkbox { + position: relative; + display: block; + margin-top: 10px; + margin-bottom: 10px; +} +.radio label, +.checkbox label { + min-height: 20px; + padding-left: 20px; + margin-bottom: 0; + font-weight: normal; + cursor: pointer; +} +.radio input[type="radio"], +.radio-inline input[type="radio"], +.checkbox input[type="checkbox"], +.checkbox-inline input[type="checkbox"] { + position: absolute; + margin-left: -20px; + margin-top: 4px \9; +} +.radio + .radio, +.checkbox + .checkbox { + margin-top: -5px; +} +.radio-inline, +.checkbox-inline { + position: relative; + display: inline-block; + padding-left: 20px; + margin-bottom: 0; + vertical-align: middle; + font-weight: normal; + cursor: pointer; +} +.radio-inline + .radio-inline, +.checkbox-inline + .checkbox-inline { + margin-top: 0; + margin-left: 10px; +} +input[type="radio"][disabled], +input[type="checkbox"][disabled], +input[type="radio"].disabled, +input[type="checkbox"].disabled, +fieldset[disabled] input[type="radio"], +fieldset[disabled] input[type="checkbox"] { + cursor: not-allowed; +} +.radio-inline.disabled, +.checkbox-inline.disabled, +fieldset[disabled] .radio-inline, +fieldset[disabled] .checkbox-inline { + cursor: not-allowed; +} +.radio.disabled label, +.checkbox.disabled label, +fieldset[disabled] .radio label, +fieldset[disabled] .checkbox label { + cursor: not-allowed; +} +.form-control-static { + padding-top: 7px; + padding-bottom: 7px; + margin-bottom: 0; + min-height: 34px; +} +.form-control-static.input-lg, +.form-control-static.input-sm { + padding-left: 0; + padding-right: 0; +} +.input-sm { + height: 30px; + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; +} +select.input-sm { + height: 30px; + line-height: 30px; +} +textarea.input-sm, +select[multiple].input-sm { + height: auto; +} +.form-group-sm .form-control { + height: 30px; + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; +} +.form-group-sm select.form-control { + height: 30px; + line-height: 30px; +} +.form-group-sm textarea.form-control, +.form-group-sm select[multiple].form-control { + height: auto; +} +.form-group-sm .form-control-static { + height: 30px; + min-height: 32px; + padding: 6px 10px; + font-size: 12px; + line-height: 1.5; +} +.input-lg { + height: 46px; + padding: 10px 16px; + font-size: 18px; + line-height: 1.3333333; + border-radius: 6px; +} +select.input-lg { + height: 46px; + line-height: 46px; +} +textarea.input-lg, +select[multiple].input-lg { + height: auto; +} +.form-group-lg .form-control { + height: 46px; + padding: 10px 16px; + font-size: 18px; + line-height: 1.3333333; + border-radius: 6px; +} +.form-group-lg select.form-control { + height: 46px; + line-height: 46px; +} +.form-group-lg textarea.form-control, +.form-group-lg select[multiple].form-control { + height: auto; +} +.form-group-lg .form-control-static { + height: 46px; + min-height: 38px; + padding: 11px 16px; + font-size: 18px; + line-height: 1.3333333; +} +.has-feedback { + position: relative; +} +.has-feedback .form-control { + padding-right: 42.5px; +} +.form-control-feedback { + position: absolute; + top: 0; + right: 0; + z-index: 2; + display: block; + width: 34px; + height: 34px; + line-height: 34px; + text-align: center; + pointer-events: none; +} +.input-lg + .form-control-feedback, +.input-group-lg + .form-control-feedback, +.form-group-lg .form-control + .form-control-feedback { + width: 46px; + height: 46px; + line-height: 46px; +} +.input-sm + .form-control-feedback, +.input-group-sm + .form-control-feedback, +.form-group-sm .form-control + .form-control-feedback { + width: 30px; + height: 30px; + line-height: 30px; +} +.has-success .help-block, +.has-success .control-label, +.has-success .radio, +.has-success .checkbox, +.has-success .radio-inline, +.has-success .checkbox-inline, +.has-success.radio label, +.has-success.checkbox label, +.has-success.radio-inline label, +.has-success.checkbox-inline label { + color: #3c763d; +} +.has-success .form-control { + border-color: #3c763d; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); +} +.has-success .form-control:focus { + border-color: #2b542c; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #67b168; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #67b168; +} +.has-success .input-group-addon { + color: #3c763d; + border-color: #3c763d; + background-color: #dff0d8; +} +.has-success .form-control-feedback { + color: #3c763d; +} +.has-warning .help-block, +.has-warning .control-label, +.has-warning .radio, +.has-warning .checkbox, +.has-warning .radio-inline, +.has-warning .checkbox-inline, +.has-warning.radio label, +.has-warning.checkbox label, +.has-warning.radio-inline label, +.has-warning.checkbox-inline label { + color: #8a6d3b; +} +.has-warning .form-control { + border-color: #8a6d3b; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); +} +.has-warning .form-control:focus { + border-color: #66512c; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #c0a16b; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #c0a16b; +} +.has-warning .input-group-addon { + color: #8a6d3b; + border-color: #8a6d3b; + background-color: #fcf8e3; +} +.has-warning .form-control-feedback { + color: #8a6d3b; +} +.has-error .help-block, +.has-error .control-label, +.has-error .radio, +.has-error .checkbox, +.has-error .radio-inline, +.has-error .checkbox-inline, +.has-error.radio label, +.has-error.checkbox label, +.has-error.radio-inline label, +.has-error.checkbox-inline label { + color: #a94442; +} +.has-error .form-control { + border-color: #a94442; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); +} +.has-error .form-control:focus { + border-color: #843534; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ce8483; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ce8483; +} +.has-error .input-group-addon { + color: #a94442; + border-color: #a94442; + background-color: #f2dede; +} +.has-error .form-control-feedback { + color: #a94442; +} +.has-feedback label ~ .form-control-feedback { + top: 25px; +} +.has-feedback label.sr-only ~ .form-control-feedback { + top: 0; +} +.help-block { + display: block; + margin-top: 5px; + margin-bottom: 10px; + color: #737373; +} +@media (min-width: 768px) { + .form-inline .form-group { + display: inline-block; + margin-bottom: 0; + vertical-align: middle; + } + .form-inline .form-control { + display: inline-block; + width: auto; + vertical-align: middle; + } + .form-inline .form-control-static { + display: inline-block; + } + .form-inline .input-group { + display: inline-table; + vertical-align: middle; + } + .form-inline .input-group .input-group-addon, + .form-inline .input-group .input-group-btn, + .form-inline .input-group .form-control { + width: auto; + } + .form-inline .input-group > .form-control { + width: 100%; + } + .form-inline .control-label { + margin-bottom: 0; + vertical-align: middle; + } + .form-inline .radio, + .form-inline .checkbox { + display: inline-block; + margin-top: 0; + margin-bottom: 0; + vertical-align: middle; + } + .form-inline .radio label, + .form-inline .checkbox label { + padding-left: 0; + } + .form-inline .radio input[type="radio"], + .form-inline .checkbox input[type="checkbox"] { + position: relative; + margin-left: 0; + } + .form-inline .has-feedback .form-control-feedback { + top: 0; + } +} +.form-horizontal .radio, +.form-horizontal .checkbox, +.form-horizontal .radio-inline, +.form-horizontal .checkbox-inline { + margin-top: 0; + margin-bottom: 0; + padding-top: 7px; +} +.form-horizontal .radio, +.form-horizontal .checkbox { + min-height: 27px; +} +.form-horizontal .form-group { + margin-left: -15px; + margin-right: -15px; +} +@media (min-width: 768px) { + .form-horizontal .control-label { + text-align: right; + margin-bottom: 0; + padding-top: 7px; + } +} +.form-horizontal .has-feedback .form-control-feedback { + right: 15px; +} +@media (min-width: 768px) { + .form-horizontal .form-group-lg .control-label { + padding-top: 11px; + font-size: 18px; + } +} +@media (min-width: 768px) { + .form-horizontal .form-group-sm .control-label { + padding-top: 6px; + font-size: 12px; + } +} +.btn { + display: inline-block; + margin-bottom: 0; + font-weight: normal; + text-align: center; + vertical-align: middle; + -ms-touch-action: manipulation; + touch-action: manipulation; + cursor: pointer; + background-image: none; + border: 1px solid transparent; + white-space: nowrap; + padding: 6px 12px; + font-size: 14px; + line-height: 1.42857143; + border-radius: 4px; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} +.btn:focus, +.btn:active:focus, +.btn.active:focus, +.btn.focus, +.btn:active.focus, +.btn.active.focus { + outline: thin dotted; + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; +} +.btn:hover, +.btn:focus, +.btn.focus { + color: #333; + text-decoration: none; +} +.btn:active, +.btn.active { + outline: 0; + background-image: none; + -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); + box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); +} +.btn.disabled, +.btn[disabled], +fieldset[disabled] .btn { + cursor: not-allowed; + opacity: 0.65; + filter: alpha(opacity=65); + -webkit-box-shadow: none; + box-shadow: none; +} +a.btn.disabled, +fieldset[disabled] a.btn { + pointer-events: none; +} +.btn-default { + color: #333; + background-color: #fff; + border-color: #ccc; +} +.btn-default:focus, +.btn-default.focus { + color: #333; + background-color: #e6e6e6; + border-color: #8c8c8c; +} +.btn-default:hover { + color: #333; + background-color: #e6e6e6; + border-color: #adadad; +} +.btn-default:active, +.btn-default.active, +.open > .dropdown-toggle.btn-default { + color: #333; + background-color: #e6e6e6; + border-color: #adadad; +} +.btn-default:active:hover, +.btn-default.active:hover, +.open > .dropdown-toggle.btn-default:hover, +.btn-default:active:focus, +.btn-default.active:focus, +.open > .dropdown-toggle.btn-default:focus, +.btn-default:active.focus, +.btn-default.active.focus, +.open > .dropdown-toggle.btn-default.focus { + color: #333; + background-color: #d4d4d4; + border-color: #8c8c8c; +} +.btn-default:active, +.btn-default.active, +.open > .dropdown-toggle.btn-default { + background-image: none; +} +.btn-default.disabled:hover, +.btn-default[disabled]:hover, +fieldset[disabled] .btn-default:hover, +.btn-default.disabled:focus, +.btn-default[disabled]:focus, +fieldset[disabled] .btn-default:focus, +.btn-default.disabled.focus, +.btn-default[disabled].focus, +fieldset[disabled] .btn-default.focus { + background-color: #fff; + border-color: #ccc; +} +.btn-default .badge { + color: #fff; + background-color: #333; +} +.btn-primary { + color: #fff; + background-color: #337ab7; + border-color: #2e6da4; +} +.btn-primary:focus, +.btn-primary.focus { + color: #fff; + background-color: #286090; + border-color: #122b40; +} +.btn-primary:hover { + color: #fff; + background-color: #286090; + border-color: #204d74; +} +.btn-primary:active, +.btn-primary.active, +.open > .dropdown-toggle.btn-primary { + color: #fff; + background-color: #286090; + border-color: #204d74; +} +.btn-primary:active:hover, +.btn-primary.active:hover, +.open > .dropdown-toggle.btn-primary:hover, +.btn-primary:active:focus, +.btn-primary.active:focus, +.open > .dropdown-toggle.btn-primary:focus, +.btn-primary:active.focus, +.btn-primary.active.focus, +.open > .dropdown-toggle.btn-primary.focus { + color: #fff; + background-color: #204d74; + border-color: #122b40; +} +.btn-primary:active, +.btn-primary.active, +.open > .dropdown-toggle.btn-primary { + background-image: none; +} +.btn-primary.disabled:hover, +.btn-primary[disabled]:hover, +fieldset[disabled] .btn-primary:hover, +.btn-primary.disabled:focus, +.btn-primary[disabled]:focus, +fieldset[disabled] .btn-primary:focus, +.btn-primary.disabled.focus, +.btn-primary[disabled].focus, +fieldset[disabled] .btn-primary.focus { + background-color: #337ab7; + border-color: #2e6da4; +} +.btn-primary .badge { + color: #337ab7; + background-color: #fff; +} +.btn-success { + color: #fff; + background-color: #5cb85c; + border-color: #4cae4c; +} +.btn-success:focus, +.btn-success.focus { + color: #fff; + background-color: #449d44; + border-color: #255625; +} +.btn-success:hover { + color: #fff; + background-color: #449d44; + border-color: #398439; +} +.btn-success:active, +.btn-success.active, +.open > .dropdown-toggle.btn-success { + color: #fff; + background-color: #449d44; + border-color: #398439; +} +.btn-success:active:hover, +.btn-success.active:hover, +.open > .dropdown-toggle.btn-success:hover, +.btn-success:active:focus, +.btn-success.active:focus, +.open > .dropdown-toggle.btn-success:focus, +.btn-success:active.focus, +.btn-success.active.focus, +.open > .dropdown-toggle.btn-success.focus { + color: #fff; + background-color: #398439; + border-color: #255625; +} +.btn-success:active, +.btn-success.active, +.open > .dropdown-toggle.btn-success { + background-image: none; +} +.btn-success.disabled:hover, +.btn-success[disabled]:hover, +fieldset[disabled] .btn-success:hover, +.btn-success.disabled:focus, +.btn-success[disabled]:focus, +fieldset[disabled] .btn-success:focus, +.btn-success.disabled.focus, +.btn-success[disabled].focus, +fieldset[disabled] .btn-success.focus { + background-color: #5cb85c; + border-color: #4cae4c; +} +.btn-success .badge { + color: #5cb85c; + background-color: #fff; +} +.btn-info { + color: #fff; + background-color: #5bc0de; + border-color: #46b8da; +} +.btn-info:focus, +.btn-info.focus { + color: #fff; + background-color: #31b0d5; + border-color: #1b6d85; +} +.btn-info:hover { + color: #fff; + background-color: #31b0d5; + border-color: #269abc; +} +.btn-info:active, +.btn-info.active, +.open > .dropdown-toggle.btn-info { + color: #fff; + background-color: #31b0d5; + border-color: #269abc; +} +.btn-info:active:hover, +.btn-info.active:hover, +.open > .dropdown-toggle.btn-info:hover, +.btn-info:active:focus, +.btn-info.active:focus, +.open > .dropdown-toggle.btn-info:focus, +.btn-info:active.focus, +.btn-info.active.focus, +.open > .dropdown-toggle.btn-info.focus { + color: #fff; + background-color: #269abc; + border-color: #1b6d85; +} +.btn-info:active, +.btn-info.active, +.open > .dropdown-toggle.btn-info { + background-image: none; +} +.btn-info.disabled:hover, +.btn-info[disabled]:hover, +fieldset[disabled] .btn-info:hover, +.btn-info.disabled:focus, +.btn-info[disabled]:focus, +fieldset[disabled] .btn-info:focus, +.btn-info.disabled.focus, +.btn-info[disabled].focus, +fieldset[disabled] .btn-info.focus { + background-color: #5bc0de; + border-color: #46b8da; +} +.btn-info .badge { + color: #5bc0de; + background-color: #fff; +} +.btn-warning { + color: #fff; + background-color: #f0ad4e; + border-color: #eea236; +} +.btn-warning:focus, +.btn-warning.focus { + color: #fff; + background-color: #ec971f; + border-color: #985f0d; +} +.btn-warning:hover { + color: #fff; + background-color: #ec971f; + border-color: #d58512; +} +.btn-warning:active, +.btn-warning.active, +.open > .dropdown-toggle.btn-warning { + color: #fff; + background-color: #ec971f; + border-color: #d58512; +} +.btn-warning:active:hover, +.btn-warning.active:hover, +.open > .dropdown-toggle.btn-warning:hover, +.btn-warning:active:focus, +.btn-warning.active:focus, +.open > .dropdown-toggle.btn-warning:focus, +.btn-warning:active.focus, +.btn-warning.active.focus, +.open > .dropdown-toggle.btn-warning.focus { + color: #fff; + background-color: #d58512; + border-color: #985f0d; +} +.btn-warning:active, +.btn-warning.active, +.open > .dropdown-toggle.btn-warning { + background-image: none; +} +.btn-warning.disabled:hover, +.btn-warning[disabled]:hover, +fieldset[disabled] .btn-warning:hover, +.btn-warning.disabled:focus, +.btn-warning[disabled]:focus, +fieldset[disabled] .btn-warning:focus, +.btn-warning.disabled.focus, +.btn-warning[disabled].focus, +fieldset[disabled] .btn-warning.focus { + background-color: #f0ad4e; + border-color: #eea236; +} +.btn-warning .badge { + color: #f0ad4e; + background-color: #fff; +} +.btn-danger { + color: #fff; + background-color: #d9534f; + border-color: #d43f3a; +} +.btn-danger:focus, +.btn-danger.focus { + color: #fff; + background-color: #c9302c; + border-color: #761c19; +} +.btn-danger:hover { + color: #fff; + background-color: #c9302c; + border-color: #ac2925; +} +.btn-danger:active, +.btn-danger.active, +.open > .dropdown-toggle.btn-danger { + color: #fff; + background-color: #c9302c; + border-color: #ac2925; +} +.btn-danger:active:hover, +.btn-danger.active:hover, +.open > .dropdown-toggle.btn-danger:hover, +.btn-danger:active:focus, +.btn-danger.active:focus, +.open > .dropdown-toggle.btn-danger:focus, +.btn-danger:active.focus, +.btn-danger.active.focus, +.open > .dropdown-toggle.btn-danger.focus { + color: #fff; + background-color: #ac2925; + border-color: #761c19; +} +.btn-danger:active, +.btn-danger.active, +.open > .dropdown-toggle.btn-danger { + background-image: none; +} +.btn-danger.disabled:hover, +.btn-danger[disabled]:hover, +fieldset[disabled] .btn-danger:hover, +.btn-danger.disabled:focus, +.btn-danger[disabled]:focus, +fieldset[disabled] .btn-danger:focus, +.btn-danger.disabled.focus, +.btn-danger[disabled].focus, +fieldset[disabled] .btn-danger.focus { + background-color: #d9534f; + border-color: #d43f3a; +} +.btn-danger .badge { + color: #d9534f; + background-color: #fff; +} +.btn-link { + color: #337ab7; + font-weight: normal; + border-radius: 0; +} +.btn-link, +.btn-link:active, +.btn-link.active, +.btn-link[disabled], +fieldset[disabled] .btn-link { + background-color: transparent; + -webkit-box-shadow: none; + box-shadow: none; +} +.btn-link, +.btn-link:hover, +.btn-link:focus, +.btn-link:active { + border-color: transparent; +} +.btn-link:hover, +.btn-link:focus { + color: #23527c; + text-decoration: underline; + background-color: transparent; +} +.btn-link[disabled]:hover, +fieldset[disabled] .btn-link:hover, +.btn-link[disabled]:focus, +fieldset[disabled] .btn-link:focus { + color: #777; + text-decoration: none; +} +.btn-lg, +.btn-group-lg > .btn { + padding: 10px 16px; + font-size: 18px; + line-height: 1.3333333; + border-radius: 6px; +} +.btn-sm, +.btn-group-sm > .btn { + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; +} +.btn-xs, +.btn-group-xs > .btn { + padding: 1px 5px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; +} +.btn-block { + display: block; + width: 100%; +} +.btn-block + .btn-block { + margin-top: 5px; +} +input[type="submit"].btn-block, +input[type="reset"].btn-block, +input[type="button"].btn-block { + width: 100%; +} +.fade { + opacity: 0; + -webkit-transition: opacity 0.15s linear; + -o-transition: opacity 0.15s linear; + transition: opacity 0.15s linear; +} +.fade.in { + opacity: 1; +} +.collapse { + display: none; +} +.collapse.in { + display: block; +} +tr.collapse.in { + display: table-row; +} +tbody.collapse.in { + display: table-row-group; +} +.collapsing { + position: relative; + height: 0; + overflow: hidden; + -webkit-transition-property: height, visibility; + -o-transition-property: height, visibility; + transition-property: height, visibility; + -webkit-transition-duration: 0.35s; + -o-transition-duration: 0.35s; + transition-duration: 0.35s; + -webkit-transition-timing-function: ease; + -o-transition-timing-function: ease; + transition-timing-function: ease; +} +.caret { + display: inline-block; + width: 0; + height: 0; + margin-left: 2px; + vertical-align: middle; + border-top: 4px dashed; + border-top: 4px solid \9; + border-right: 4px solid transparent; + border-left: 4px solid transparent; +} +.dropup, +.dropdown { + position: relative; +} +.dropdown-toggle:focus { + outline: 0; +} +.dropdown-menu { + position: absolute; + top: 100%; + left: 0; + z-index: 1000; + display: none; + float: left; + min-width: 160px; + padding: 5px 0; + margin: 2px 0 0; + list-style: none; + font-size: 14px; + text-align: left; + background-color: #fff; + border: 1px solid #ccc; + border: 1px solid rgba(0, 0, 0, 0.15); + border-radius: 4px; + -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175); + box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175); + -webkit-background-clip: padding-box; + background-clip: padding-box; +} +.dropdown-menu.pull-right { + right: 0; + left: auto; +} +.dropdown-menu .divider { + height: 1px; + margin: 9px 0; + overflow: hidden; + background-color: #e5e5e5; +} +.dropdown-menu > li > a { + display: block; + padding: 3px 20px; + clear: both; + font-weight: normal; + line-height: 1.42857143; + color: #333; + white-space: nowrap; +} +.dropdown-menu > li > a:hover, +.dropdown-menu > li > a:focus { + text-decoration: none; + color: #262626; + background-color: #f5f7f8; +} +.dropdown-menu > .active > a, +.dropdown-menu > .active > a:hover, +.dropdown-menu > .active > a:focus { + color: #fff; + text-decoration: none; + outline: 0; + background-color: #337ab7; +} +.dropdown-menu > .disabled > a, +.dropdown-menu > .disabled > a:hover, +.dropdown-menu > .disabled > a:focus { + color: #777; +} +.dropdown-menu > .disabled > a:hover, +.dropdown-menu > .disabled > a:focus { + text-decoration: none; + background-color: transparent; + background-image: none; + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); + cursor: not-allowed; +} +.open > .dropdown-menu { + display: block; +} +.open > a { + outline: 0; +} +.dropdown-menu-right { + left: auto; + right: 0; +} +.dropdown-menu-left { + left: 0; + right: auto; +} +.dropdown-header { + display: block; + padding: 3px 20px; + font-size: 12px; + line-height: 1.42857143; + color: #777; + white-space: nowrap; +} +.dropdown-backdrop { + position: fixed; + left: 0; + right: 0; + bottom: 0; + top: 0; + z-index: 990; +} +.pull-right > .dropdown-menu { + right: 0; + left: auto; +} +.dropup .caret, +.navbar-fixed-bottom .dropdown .caret { + border-top: 0; + border-bottom: 4px dashed; + border-bottom: 4px solid \9; + content: ""; +} +.dropup .dropdown-menu, +.navbar-fixed-bottom .dropdown .dropdown-menu { + top: auto; + bottom: 100%; + margin-bottom: 2px; +} +@media (min-width: 768px) { + .navbar-right .dropdown-menu { + left: auto; + right: 0; + } + .navbar-right .dropdown-menu-left { + left: 0; + right: auto; + } +} +.btn-group, +.btn-group-vertical { + position: relative; + display: inline-block; + vertical-align: middle; +} +.btn-group > .btn, +.btn-group-vertical > .btn { + position: relative; + float: left; +} +.btn-group > .btn:hover, +.btn-group-vertical > .btn:hover, +.btn-group > .btn:focus, +.btn-group-vertical > .btn:focus, +.btn-group > .btn:active, +.btn-group-vertical > .btn:active, +.btn-group > .btn.active, +.btn-group-vertical > .btn.active { + z-index: 2; +} +.btn-group .btn + .btn, +.btn-group .btn + .btn-group, +.btn-group .btn-group + .btn, +.btn-group .btn-group + .btn-group { + margin-left: -1px; +} +.btn-toolbar { + margin-left: -5px; +} +.btn-toolbar .btn, +.btn-toolbar .btn-group, +.btn-toolbar .input-group { + float: left; +} +.btn-toolbar > .btn, +.btn-toolbar > .btn-group, +.btn-toolbar > .input-group { + margin-left: 5px; +} +.btn-group > .btn:not(:first-child):not(:last-child):not(.dropdown-toggle) { + border-radius: 0; +} +.btn-group > .btn:first-child { + margin-left: 0; +} +.btn-group > .btn:first-child:not(:last-child):not(.dropdown-toggle) { + border-bottom-right-radius: 0; + border-top-right-radius: 0; +} +.btn-group > .btn:last-child:not(:first-child), +.btn-group > .dropdown-toggle:not(:first-child) { + border-bottom-left-radius: 0; + border-top-left-radius: 0; +} +.btn-group > .btn-group { + float: left; +} +.btn-group > .btn-group:not(:first-child):not(:last-child) > .btn { + border-radius: 0; +} +.btn-group > .btn-group:first-child:not(:last-child) > .btn:last-child, +.btn-group > .btn-group:first-child:not(:last-child) > .dropdown-toggle { + border-bottom-right-radius: 0; + border-top-right-radius: 0; +} +.btn-group > .btn-group:last-child:not(:first-child) > .btn:first-child { + border-bottom-left-radius: 0; + border-top-left-radius: 0; +} +.btn-group .dropdown-toggle:active, +.btn-group.open .dropdown-toggle { + outline: 0; +} +.btn-group > .btn + .dropdown-toggle { + padding-left: 8px; + padding-right: 8px; +} +.btn-group > .btn-lg + .dropdown-toggle { + padding-left: 12px; + padding-right: 12px; +} +.btn-group.open .dropdown-toggle { + -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); + box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); +} +.btn-group.open .dropdown-toggle.btn-link { + -webkit-box-shadow: none; + box-shadow: none; +} +.btn .caret { + margin-left: 0; +} +.btn-lg .caret { + border-width: 5px 5px 0; + border-bottom-width: 0; +} +.dropup .btn-lg .caret { + border-width: 0 5px 5px; +} +.btn-group-vertical > .btn, +.btn-group-vertical > .btn-group, +.btn-group-vertical > .btn-group > .btn { + display: block; + float: none; + width: 100%; + max-width: 100%; +} +.btn-group-vertical > .btn-group > .btn { + float: none; +} +.btn-group-vertical > .btn + .btn, +.btn-group-vertical > .btn + .btn-group, +.btn-group-vertical > .btn-group + .btn, +.btn-group-vertical > .btn-group + .btn-group { + margin-top: -1px; + margin-left: 0; +} +.btn-group-vertical > .btn:not(:first-child):not(:last-child) { + border-radius: 0; +} +.btn-group-vertical > .btn:first-child:not(:last-child) { + border-top-right-radius: 4px; + border-top-left-radius: 4px; + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; +} +.btn-group-vertical > .btn:last-child:not(:first-child) { + border-top-right-radius: 0; + border-top-left-radius: 0; + border-bottom-right-radius: 4px; + border-bottom-left-radius: 4px; +} +.btn-group-vertical > .btn-group:not(:first-child):not(:last-child) > .btn { + border-radius: 0; +} +.btn-group-vertical > .btn-group:first-child:not(:last-child) > .btn:last-child, +.btn-group-vertical + > .btn-group:first-child:not(:last-child) + > .dropdown-toggle { + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; +} +.btn-group-vertical + > .btn-group:last-child:not(:first-child) + > .btn:first-child { + border-top-right-radius: 0; + border-top-left-radius: 0; +} +.btn-group-justified { + display: table; + width: 100%; + table-layout: fixed; + border-collapse: separate; +} +.btn-group-justified > .btn, +.btn-group-justified > .btn-group { + float: none; + display: table-cell; + width: 1%; +} +.btn-group-justified > .btn-group .btn { + width: 100%; +} +.btn-group-justified > .btn-group .dropdown-menu { + left: auto; +} +[data-toggle="buttons"] > .btn input[type="radio"], +[data-toggle="buttons"] > .btn-group > .btn input[type="radio"], +[data-toggle="buttons"] > .btn input[type="checkbox"], +[data-toggle="buttons"] > .btn-group > .btn input[type="checkbox"] { + position: absolute; + clip: rect(0, 0, 0, 0); + pointer-events: none; +} +.input-group { + position: relative; + display: table; + border-collapse: separate; +} +.input-group[class*="col-"] { + float: none; + padding-left: 0; + padding-right: 0; +} +.input-group .form-control { + position: relative; + z-index: 2; + float: left; + width: 100%; + margin-bottom: 0; +} +.input-group .form-control:focus { + z-index: 3; +} +.input-group-lg > .form-control, +.input-group-lg > .input-group-addon, +.input-group-lg > .input-group-btn > .btn { + height: 46px; + padding: 10px 16px; + font-size: 18px; + line-height: 1.3333333; + border-radius: 6px; +} +select.input-group-lg > .form-control, +select.input-group-lg > .input-group-addon, +select.input-group-lg > .input-group-btn > .btn { + height: 46px; + line-height: 46px; +} +textarea.input-group-lg > .form-control, +textarea.input-group-lg > .input-group-addon, +textarea.input-group-lg > .input-group-btn > .btn, +select[multiple].input-group-lg > .form-control, +select[multiple].input-group-lg > .input-group-addon, +select[multiple].input-group-lg > .input-group-btn > .btn { + height: auto; +} +.input-group-sm > .form-control, +.input-group-sm > .input-group-addon, +.input-group-sm > .input-group-btn > .btn { + height: 30px; + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; +} +select.input-group-sm > .form-control, +select.input-group-sm > .input-group-addon, +select.input-group-sm > .input-group-btn > .btn { + height: 30px; + line-height: 30px; +} +textarea.input-group-sm > .form-control, +textarea.input-group-sm > .input-group-addon, +textarea.input-group-sm > .input-group-btn > .btn, +select[multiple].input-group-sm > .form-control, +select[multiple].input-group-sm > .input-group-addon, +select[multiple].input-group-sm > .input-group-btn > .btn { + height: auto; +} +.input-group-addon, +.input-group-btn, +.input-group .form-control { + display: table-cell; +} +.input-group-addon:not(:first-child):not(:last-child), +.input-group-btn:not(:first-child):not(:last-child), +.input-group .form-control:not(:first-child):not(:last-child) { + border-radius: 0; +} +.input-group-addon, +.input-group-btn { + width: 1%; + white-space: nowrap; + vertical-align: middle; +} +.input-group-addon { + padding: 6px 12px; + font-size: 14px; + font-weight: normal; + line-height: 1; + color: #555; + text-align: center; + background-color: #eee; + border: 1px solid #ccc; + border-radius: 4px; +} +.input-group-addon.input-sm { + padding: 5px 10px; + font-size: 12px; + border-radius: 3px; +} +.input-group-addon.input-lg { + padding: 10px 16px; + font-size: 18px; + border-radius: 6px; +} +.input-group-addon input[type="radio"], +.input-group-addon input[type="checkbox"] { + margin-top: 0; +} +.input-group .form-control:first-child, +.input-group-addon:first-child, +.input-group-btn:first-child > .btn, +.input-group-btn:first-child > .btn-group > .btn, +.input-group-btn:first-child > .dropdown-toggle, +.input-group-btn:last-child > .btn:not(:last-child):not(.dropdown-toggle), +.input-group-btn:last-child > .btn-group:not(:last-child) > .btn { + border-bottom-right-radius: 0; + border-top-right-radius: 0; +} +.input-group-addon:first-child { + border-right: 0; +} +.input-group .form-control:last-child, +.input-group-addon:last-child, +.input-group-btn:last-child > .btn, +.input-group-btn:last-child > .btn-group > .btn, +.input-group-btn:last-child > .dropdown-toggle, +.input-group-btn:first-child > .btn:not(:first-child), +.input-group-btn:first-child > .btn-group:not(:first-child) > .btn { + border-bottom-left-radius: 0; + border-top-left-radius: 0; +} +.input-group-addon:last-child { + border-left: 0; +} +.input-group-btn { + position: relative; + font-size: 0; + white-space: nowrap; +} +.input-group-btn > .btn { + position: relative; +} +.input-group-btn > .btn + .btn { + margin-left: -1px; +} +.input-group-btn > .btn:hover, +.input-group-btn > .btn:focus, +.input-group-btn > .btn:active { + z-index: 2; +} +.input-group-btn:first-child > .btn, +.input-group-btn:first-child > .btn-group { + margin-right: -1px; +} +.input-group-btn:last-child > .btn, +.input-group-btn:last-child > .btn-group { + z-index: 2; + margin-left: -1px; +} +.nav { + margin-bottom: 0; + padding-left: 0; + list-style: none; +} +.nav > li { + position: relative; + display: block; +} +.nav > li > a { + position: relative; + display: block; + padding: 10px 15px; +} +.nav > li > a:hover, +.nav > li > a:focus { + text-decoration: none; + background-color: #eee; +} +.nav > li.disabled > a { + color: #777; +} +.nav > li.disabled > a:hover, +.nav > li.disabled > a:focus { + color: #777; + text-decoration: none; + background-color: transparent; + cursor: not-allowed; +} +.nav .open > a, +.nav .open > a:hover, +.nav .open > a:focus { + background-color: #eee; + border-color: #337ab7; +} +.nav .nav-divider { + height: 1px; + margin: 9px 0; + overflow: hidden; + background-color: #e5e5e5; +} +.nav > li > a > img { + max-width: none; +} +.nav-tabs { + border-bottom: 1px solid #ddd; +} +.nav-tabs > li { + float: left; + margin-bottom: -1px; +} +.nav-tabs > li > a { + margin-right: 2px; + line-height: 1.42857143; + border: 1px solid transparent; + border-radius: 4px 4px 0 0; +} +.nav-tabs > li > a:hover { + border-color: #eee #eee #ddd; +} +.nav-tabs > li.active > a, +.nav-tabs > li.active > a:hover, +.nav-tabs > li.active > a:focus { + color: #555; + background-color: #fff; + border: 1px solid #ddd; + border-bottom-color: transparent; + cursor: default; +} +.nav-tabs.nav-justified { + width: 100%; + border-bottom: 0; +} +.nav-tabs.nav-justified > li { + float: none; +} +.nav-tabs.nav-justified > li > a { + text-align: center; + margin-bottom: 5px; +} +.nav-tabs.nav-justified > .dropdown .dropdown-menu { + top: auto; + left: auto; +} +@media (min-width: 768px) { + .nav-tabs.nav-justified > li { + display: table-cell; + width: 1%; + } + .nav-tabs.nav-justified > li > a { + margin-bottom: 0; + } +} +.nav-tabs.nav-justified > li > a { + margin-right: 0; + border-radius: 4px; +} +.nav-tabs.nav-justified > .active > a, +.nav-tabs.nav-justified > .active > a:hover, +.nav-tabs.nav-justified > .active > a:focus { + border: 1px solid #ddd; +} +@media (min-width: 768px) { + .nav-tabs.nav-justified > li > a { + border-bottom: 1px solid #ddd; + border-radius: 4px 4px 0 0; + } + .nav-tabs.nav-justified > .active > a, + .nav-tabs.nav-justified > .active > a:hover, + .nav-tabs.nav-justified > .active > a:focus { + border-bottom-color: #fff; + } +} +.nav-pills > li { + float: left; +} +.nav-pills > li > a { + border-radius: 4px; +} +.nav-pills > li + li { + margin-left: 2px; +} +.nav-pills > li.active > a, +.nav-pills > li.active > a:hover, +.nav-pills > li.active > a:focus { + color: #fff; + background-color: #337ab7; +} +.nav-stacked > li { + float: none; +} +.nav-stacked > li + li { + margin-top: 2px; + margin-left: 0; +} +.nav-justified { + width: 100%; +} +.nav-justified > li { + float: none; +} +.nav-justified > li > a { + text-align: center; + margin-bottom: 5px; +} +.nav-justified > .dropdown .dropdown-menu { + top: auto; + left: auto; +} +@media (min-width: 768px) { + .nav-justified > li { + display: table-cell; + width: 1%; + } + .nav-justified > li > a { + margin-bottom: 0; + } +} +.nav-tabs-justified { + border-bottom: 0; +} +.nav-tabs-justified > li > a { + margin-right: 0; + border-radius: 4px; +} +.nav-tabs-justified > .active > a, +.nav-tabs-justified > .active > a:hover, +.nav-tabs-justified > .active > a:focus { + border: 1px solid #ddd; +} +@media (min-width: 768px) { + .nav-tabs-justified > li > a { + border-bottom: 1px solid #ddd; + border-radius: 4px 4px 0 0; + } + .nav-tabs-justified > .active > a, + .nav-tabs-justified > .active > a:hover, + .nav-tabs-justified > .active > a:focus { + border-bottom-color: #fff; + } +} +.tab-content > .tab-pane { + display: none; +} +.tab-content > .active { + display: block; +} +.nav-tabs .dropdown-menu { + margin-top: -1px; + border-top-right-radius: 0; + border-top-left-radius: 0; +} +.navbar { + position: relative; + min-height: 50px; + margin-bottom: 20px; + border: 1px solid transparent; +} +@media (min-width: 768px) { + .navbar { + border-radius: 4px; + } +} +@media (min-width: 768px) { + .navbar-header { + float: left; + } +} +.navbar-collapse { + overflow-x: visible; + padding-right: 15px; + padding-left: 15px; + border-top: 1px solid transparent; + -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1); + -webkit-overflow-scrolling: touch; +} +.navbar-collapse.in { + overflow-y: auto; +} +@media (min-width: 768px) { + .navbar-collapse { + width: auto; + border-top: 0; + -webkit-box-shadow: none; + box-shadow: none; + } + .navbar-collapse.collapse { + display: block !important; + height: auto !important; + padding-bottom: 0; + overflow: visible !important; + } + .navbar-collapse.in { + overflow-y: visible; + } + .navbar-fixed-top .navbar-collapse, + .navbar-static-top .navbar-collapse, + .navbar-fixed-bottom .navbar-collapse { + padding-left: 0; + padding-right: 0; + } +} +.navbar-fixed-top .navbar-collapse, +.navbar-fixed-bottom .navbar-collapse { + max-height: 340px; +} +@media (max-device-width: 480px) and (orientation: landscape) { + .navbar-fixed-top .navbar-collapse, + .navbar-fixed-bottom .navbar-collapse { + max-height: 200px; + } +} +.container > .navbar-header, +.container-fluid > .navbar-header, +.container > .navbar-collapse, +.container-fluid > .navbar-collapse { + margin-right: -15px; + margin-left: -15px; +} +@media (min-width: 768px) { + .container > .navbar-header, + .container-fluid > .navbar-header, + .container > .navbar-collapse, + .container-fluid > .navbar-collapse { + margin-right: 0; + margin-left: 0; + } +} +.navbar-static-top { + z-index: 1000; + border-width: 0 0 1px; +} +@media (min-width: 768px) { + .navbar-static-top { + border-radius: 0; + } +} +.navbar-fixed-top, +.navbar-fixed-bottom { + position: fixed; + right: 0; + left: 0; + z-index: 1030; +} +@media (min-width: 768px) { + .navbar-fixed-top, + .navbar-fixed-bottom { + border-radius: 0; + } +} +.navbar-fixed-top { + top: 0; + border-width: 0 0 1px; +} +.navbar-fixed-bottom { + bottom: 0; + margin-bottom: 0; + border-width: 1px 0 0; +} +.navbar-brand { + float: left; + padding: 15px 15px; + font-size: 18px; + line-height: 20px; + height: 50px; +} +.navbar-brand:hover, +.navbar-brand:focus { + text-decoration: none; +} +.navbar-brand > img { + display: block; +} +@media (min-width: 768px) { + .navbar > .container .navbar-brand, + .navbar > .container-fluid .navbar-brand { + margin-left: -15px; + } +} +.navbar-toggle { + position: relative; + float: right; + margin-right: 15px; + padding: 9px 10px; + margin-top: 8px; + margin-bottom: 8px; + background-color: transparent; + background-image: none; + border: 1px solid transparent; + border-radius: 4px; +} +.navbar-toggle:focus { + outline: 0; +} +.navbar-toggle .icon-bar { + display: block; + width: 22px; + height: 2px; + border-radius: 1px; +} +.navbar-toggle .icon-bar + .icon-bar { + margin-top: 4px; +} +@media (min-width: 768px) { + .navbar-toggle { + display: none; + } +} +.navbar-nav { + margin: 7.5px -15px; +} +.navbar-nav > li > a { + padding-top: 10px; + padding-bottom: 10px; + line-height: 20px; +} +@media (max-width: 767px) { + .navbar-nav .open .dropdown-menu { + position: static; + float: none; + width: auto; + margin-top: 0; + background-color: transparent; + border: 0; + -webkit-box-shadow: none; + box-shadow: none; + } + .navbar-nav .open .dropdown-menu > li > a, + .navbar-nav .open .dropdown-menu .dropdown-header { + padding: 5px 15px 5px 25px; + } + .navbar-nav .open .dropdown-menu > li > a { + line-height: 20px; + } + .navbar-nav .open .dropdown-menu > li > a:hover, + .navbar-nav .open .dropdown-menu > li > a:focus { + background-image: none; + } +} +@media (min-width: 768px) { + .navbar-nav { + float: left; + margin: 0; + } + .navbar-nav > li { + float: left; + } + .navbar-nav > li > a { + padding-top: 15px; + padding-bottom: 15px; + } +} +.navbar-form { + margin-left: -15px; + margin-right: -15px; + padding: 10px 15px; + border-top: 1px solid transparent; + border-bottom: 1px solid transparent; + -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), + 0 1px 0 rgba(255, 255, 255, 0.1); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), + 0 1px 0 rgba(255, 255, 255, 0.1); + margin-top: 8px; + margin-bottom: 8px; +} +@media (min-width: 768px) { + .navbar-form .form-group { + display: inline-block; + margin-bottom: 0; + vertical-align: middle; + } + .navbar-form .form-control { + display: inline-block; + width: auto; + vertical-align: middle; + } + .navbar-form .form-control-static { + display: inline-block; + } + .navbar-form .input-group { + display: inline-table; + vertical-align: middle; + } + .navbar-form .input-group .input-group-addon, + .navbar-form .input-group .input-group-btn, + .navbar-form .input-group .form-control { + width: auto; + } + .navbar-form .input-group > .form-control { + width: 100%; + } + .navbar-form .control-label { + margin-bottom: 0; + vertical-align: middle; + } + .navbar-form .radio, + .navbar-form .checkbox { + display: inline-block; + margin-top: 0; + margin-bottom: 0; + vertical-align: middle; + } + .navbar-form .radio label, + .navbar-form .checkbox label { + padding-left: 0; + } + .navbar-form .radio input[type="radio"], + .navbar-form .checkbox input[type="checkbox"] { + position: relative; + margin-left: 0; + } + .navbar-form .has-feedback .form-control-feedback { + top: 0; + } +} +@media (max-width: 767px) { + .navbar-form .form-group { + margin-bottom: 5px; + } + .navbar-form .form-group:last-child { + margin-bottom: 0; + } +} +@media (min-width: 768px) { + .navbar-form { + width: auto; + border: 0; + margin-left: 0; + margin-right: 0; + padding-top: 0; + padding-bottom: 0; + -webkit-box-shadow: none; + box-shadow: none; + } +} +.navbar-nav > li > .dropdown-menu { + margin-top: 0; + border-top-right-radius: 0; + border-top-left-radius: 0; +} +.navbar-fixed-bottom .navbar-nav > li > .dropdown-menu { + margin-bottom: 0; + border-top-right-radius: 4px; + border-top-left-radius: 4px; + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; +} +.navbar-btn { + margin-top: 8px; + margin-bottom: 8px; +} +.navbar-btn.btn-sm { + margin-top: 10px; + margin-bottom: 10px; +} +.navbar-btn.btn-xs { + margin-top: 14px; + margin-bottom: 14px; +} +.navbar-text { + margin-top: 15px; + margin-bottom: 15px; +} +@media (min-width: 768px) { + .navbar-text { + float: left; + margin-left: 15px; + margin-right: 15px; + } +} +@media (min-width: 768px) { + .navbar-left { + float: left !important; + } + .navbar-right { + float: right !important; + margin-right: -15px; + } + .navbar-right ~ .navbar-right { + margin-right: 0; + } +} +.navbar-default { + background-color: #f5f7f8; + border-color: #e2e7ea; +} +.navbar-default .navbar-brand { + color: #777; +} +.navbar-default .navbar-brand:hover, +.navbar-default .navbar-brand:focus { + color: #5e5e5e; + background-color: transparent; +} +.navbar-default .navbar-text { + color: #777; +} +.navbar-default .navbar-nav > li > a { + color: #777; +} +.navbar-default .navbar-nav > li > a:hover, +.navbar-default .navbar-nav > li > a:focus { + color: #333; + background-color: transparent; +} +.navbar-default .navbar-nav > .active > a, +.navbar-default .navbar-nav > .active > a:hover, +.navbar-default .navbar-nav > .active > a:focus { + color: #555; + background-color: #e2e7ea; +} +.navbar-default .navbar-nav > .disabled > a, +.navbar-default .navbar-nav > .disabled > a:hover, +.navbar-default .navbar-nav > .disabled > a:focus { + color: #ccc; + background-color: transparent; +} +.navbar-default .navbar-toggle { + border-color: #ddd; +} +.navbar-default .navbar-toggle:hover, +.navbar-default .navbar-toggle:focus { + background-color: #ddd; +} +.navbar-default .navbar-toggle .icon-bar { + background-color: #888; +} +.navbar-default .navbar-collapse, +.navbar-default .navbar-form { + border-color: #e2e7ea; +} +.navbar-default .navbar-nav > .open > a, +.navbar-default .navbar-nav > .open > a:hover, +.navbar-default .navbar-nav > .open > a:focus { + background-color: #e2e7ea; + color: #555; +} +@media (max-width: 767px) { + .navbar-default .navbar-nav .open .dropdown-menu > li > a { + color: #777; + } + .navbar-default .navbar-nav .open .dropdown-menu > li > a:hover, + .navbar-default .navbar-nav .open .dropdown-menu > li > a:focus { + color: #333; + background-color: transparent; + } + .navbar-default .navbar-nav .open .dropdown-menu > .active > a, + .navbar-default .navbar-nav .open .dropdown-menu > .active > a:hover, + .navbar-default .navbar-nav .open .dropdown-menu > .active > a:focus { + color: #555; + background-color: #e2e7ea; + } + .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a, + .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:hover, + .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:focus { + color: #ccc; + background-color: transparent; + } +} +.navbar-default .navbar-link { + color: #777; +} +.navbar-default .navbar-link:hover { + color: #333; +} +.navbar-default .btn-link { + color: #777; +} +.navbar-default .btn-link:hover, +.navbar-default .btn-link:focus { + color: #333; +} +.navbar-default .btn-link[disabled]:hover, +fieldset[disabled] .navbar-default .btn-link:hover, +.navbar-default .btn-link[disabled]:focus, +fieldset[disabled] .navbar-default .btn-link:focus { + color: #ccc; +} +.navbar-inverse { + background-color: #222; + border-color: #080808; +} +.navbar-inverse .navbar-brand { + color: #9d9d9d; +} +.navbar-inverse .navbar-brand:hover, +.navbar-inverse .navbar-brand:focus { + color: #fff; + background-color: transparent; +} +.navbar-inverse .navbar-text { + color: #9d9d9d; +} +.navbar-inverse .navbar-nav > li > a { + color: #9d9d9d; +} +.navbar-inverse .navbar-nav > li > a:hover, +.navbar-inverse .navbar-nav > li > a:focus { + color: #fff; + background-color: transparent; +} +.navbar-inverse .navbar-nav > .active > a, +.navbar-inverse .navbar-nav > .active > a:hover, +.navbar-inverse .navbar-nav > .active > a:focus { + color: #fff; + background-color: #080808; +} +.navbar-inverse .navbar-nav > .disabled > a, +.navbar-inverse .navbar-nav > .disabled > a:hover, +.navbar-inverse .navbar-nav > .disabled > a:focus { + color: #444; + background-color: transparent; +} +.navbar-inverse .navbar-toggle { + border-color: #333; +} +.navbar-inverse .navbar-toggle:hover, +.navbar-inverse .navbar-toggle:focus { + background-color: #333; +} +.navbar-inverse .navbar-toggle .icon-bar { + background-color: #fff; +} +.navbar-inverse .navbar-collapse, +.navbar-inverse .navbar-form { + border-color: #101010; +} +.navbar-inverse .navbar-nav > .open > a, +.navbar-inverse .navbar-nav > .open > a:hover, +.navbar-inverse .navbar-nav > .open > a:focus { + background-color: #080808; + color: #fff; +} +@media (max-width: 767px) { + .navbar-inverse .navbar-nav .open .dropdown-menu > .dropdown-header { + border-color: #080808; + } + .navbar-inverse .navbar-nav .open .dropdown-menu .divider { + background-color: #080808; + } + .navbar-inverse .navbar-nav .open .dropdown-menu > li > a { + color: #9d9d9d; + } + .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:hover, + .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:focus { + color: #fff; + background-color: transparent; + } + .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a, + .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:hover, + .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:focus { + color: #fff; + background-color: #080808; + } + .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a, + .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:hover, + .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:focus { + color: #444; + background-color: transparent; + } +} +.navbar-inverse .navbar-link { + color: #9d9d9d; +} +.navbar-inverse .navbar-link:hover { + color: #fff; +} +.navbar-inverse .btn-link { + color: #9d9d9d; +} +.navbar-inverse .btn-link:hover, +.navbar-inverse .btn-link:focus { + color: #fff; +} +.navbar-inverse .btn-link[disabled]:hover, +fieldset[disabled] .navbar-inverse .btn-link:hover, +.navbar-inverse .btn-link[disabled]:focus, +fieldset[disabled] .navbar-inverse .btn-link:focus { + color: #444; +} +.breadcrumb { + padding: 8px 15px; + margin-bottom: 20px; + list-style: none; + background-color: #f5f7f8; + border-radius: 4px; +} +.breadcrumb > li { + display: inline-block; +} +.breadcrumb > li + li:before { + content: "/\00a0"; + padding: 0 5px; + color: #ccc; +} +.breadcrumb > .active { + color: #777; +} +.pagination { + display: inline-block; + padding-left: 0; + margin: 20px 0; + border-radius: 4px; +} +.pagination > li { + display: inline; +} +.pagination > li > a, +.pagination > li > span { + position: relative; + float: left; + padding: 6px 12px; + line-height: 1.42857143; + text-decoration: none; + color: #337ab7; + background-color: #fff; + border: 1px solid #ddd; + margin-left: -1px; +} +.pagination > li:first-child > a, +.pagination > li:first-child > span { + margin-left: 0; + border-bottom-left-radius: 4px; + border-top-left-radius: 4px; +} +.pagination > li:last-child > a, +.pagination > li:last-child > span { + border-bottom-right-radius: 4px; + border-top-right-radius: 4px; +} +.pagination > li > a:hover, +.pagination > li > span:hover, +.pagination > li > a:focus, +.pagination > li > span:focus { + z-index: 2; + color: #23527c; + background-color: #eee; + border-color: #ddd; +} +.pagination > .active > a, +.pagination > .active > span, +.pagination > .active > a:hover, +.pagination > .active > span:hover, +.pagination > .active > a:focus, +.pagination > .active > span:focus { + z-index: 3; + color: #fff; + background-color: #337ab7; + border-color: #337ab7; + cursor: default; +} +.pagination > .disabled > span, +.pagination > .disabled > span:hover, +.pagination > .disabled > span:focus, +.pagination > .disabled > a, +.pagination > .disabled > a:hover, +.pagination > .disabled > a:focus { + color: #777; + background-color: #fff; + border-color: #ddd; + cursor: not-allowed; +} +.pagination-lg > li > a, +.pagination-lg > li > span { + padding: 10px 16px; + font-size: 18px; + line-height: 1.3333333; +} +.pagination-lg > li:first-child > a, +.pagination-lg > li:first-child > span { + border-bottom-left-radius: 6px; + border-top-left-radius: 6px; +} +.pagination-lg > li:last-child > a, +.pagination-lg > li:last-child > span { + border-bottom-right-radius: 6px; + border-top-right-radius: 6px; +} +.pagination-sm > li > a, +.pagination-sm > li > span { + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; +} +.pagination-sm > li:first-child > a, +.pagination-sm > li:first-child > span { + border-bottom-left-radius: 3px; + border-top-left-radius: 3px; +} +.pagination-sm > li:last-child > a, +.pagination-sm > li:last-child > span { + border-bottom-right-radius: 3px; + border-top-right-radius: 3px; +} +.pager { + padding-left: 0; + margin: 20px 0; + list-style: none; + text-align: center; +} +.pager li { + display: inline; +} +.pager li > a, +.pager li > span { + display: inline-block; + padding: 5px 14px; + background-color: #fff; + border: 1px solid #ddd; + border-radius: 15px; +} +.pager li > a:hover, +.pager li > a:focus { + text-decoration: none; + background-color: #eee; +} +.pager .next > a, +.pager .next > span { + float: right; +} +.pager .previous > a, +.pager .previous > span { + float: left; +} +.pager .disabled > a, +.pager .disabled > a:hover, +.pager .disabled > a:focus, +.pager .disabled > span { + color: #777; + background-color: #fff; + cursor: not-allowed; +} +.label { + display: inline; + padding: 0.2em 0.6em 0.3em; + font-size: 75%; + font-weight: bold; + line-height: 1; + color: #fff; + text-align: center; + white-space: nowrap; + vertical-align: baseline; + border-radius: 0.25em; +} +a.label:hover, +a.label:focus { + color: #fff; + text-decoration: none; + cursor: pointer; +} +.label:empty { + display: none; +} +.btn .label { + position: relative; + top: -1px; +} +.label-default { + background-color: #777; +} +.label-default[href]:hover, +.label-default[href]:focus { + background-color: #5e5e5e; +} +.label-primary { + background-color: #337ab7; +} +.label-primary[href]:hover, +.label-primary[href]:focus { + background-color: #286090; +} +.label-success { + background-color: #5cb85c; +} +.label-success[href]:hover, +.label-success[href]:focus { + background-color: #449d44; +} +.label-info { + background-color: #5bc0de; +} +.label-info[href]:hover, +.label-info[href]:focus { + background-color: #31b0d5; +} +.label-warning { + background-color: #f0ad4e; +} +.label-warning[href]:hover, +.label-warning[href]:focus { + background-color: #ec971f; +} +.label-danger { + background-color: #d9534f; +} +.label-danger[href]:hover, +.label-danger[href]:focus { + background-color: #c9302c; +} +.badge { + display: inline-block; + min-width: 10px; + padding: 3px 7px; + font-size: 12px; + font-weight: bold; + color: #fff; + line-height: 1; + vertical-align: middle; + white-space: nowrap; + text-align: center; + background-color: #777; + border-radius: 10px; +} +.badge:empty { + display: none; +} +.btn .badge { + position: relative; + top: -1px; +} +.btn-xs .badge, +.btn-group-xs > .btn .badge { + top: 0; + padding: 1px 5px; +} +a.badge:hover, +a.badge:focus { + color: #fff; + text-decoration: none; + cursor: pointer; +} +.list-group-item.active > .badge, +.nav-pills > .active > a > .badge { + color: #337ab7; + background-color: #fff; +} +.list-group-item > .badge { + float: right; +} +.list-group-item > .badge + .badge { + margin-right: 5px; +} +.nav-pills > li > a > .badge { + margin-left: 3px; +} +.jumbotron { + padding-top: 30px; + padding-bottom: 30px; + margin-bottom: 30px; + color: inherit; + background-color: #eee; +} +.jumbotron h1, +.jumbotron .h1 { + color: inherit; +} +.jumbotron p { + margin-bottom: 15px; + font-size: 21px; + font-weight: 200; +} +.jumbotron > hr { + border-top-color: #d5d5d5; +} +.container .jumbotron, +.container-fluid .jumbotron { + border-radius: 6px; + padding-left: 15px; + padding-right: 15px; +} +.jumbotron .container { + max-width: 100%; +} +@media screen and (min-width: 768px) { + .jumbotron { + padding-top: 48px; + padding-bottom: 48px; + } + .container .jumbotron, + .container-fluid .jumbotron { + padding-left: 60px; + padding-right: 60px; + } + .jumbotron h1, + .jumbotron .h1 { + font-size: 63px; + } +} +.thumbnail { + display: block; + padding: 4px; + margin-bottom: 20px; + line-height: 1.42857143; + background-color: #fff; + border: 1px solid #ddd; + border-radius: 4px; + -webkit-transition: border 0.2s ease-in-out; + -o-transition: border 0.2s ease-in-out; + transition: border 0.2s ease-in-out; +} +.thumbnail > img, +.thumbnail a > img { + margin-left: auto; + margin-right: auto; +} +a.thumbnail:hover, +a.thumbnail:focus, +a.thumbnail.active { + border-color: #337ab7; +} +.thumbnail .caption { + padding: 9px; + color: #333; +} +.alert { + padding: 15px; + margin-bottom: 20px; + border: 1px solid transparent; + border-radius: 4px; +} +.alert h4 { + margin-top: 0; + color: inherit; +} +.alert .alert-link { + font-weight: bold; +} +.alert > p, +.alert > ul { + margin-bottom: 0; +} +.alert > p + p { + margin-top: 5px; +} +.alert-dismissable, +.alert-dismissible { + padding-right: 35px; +} +.alert-dismissable .close, +.alert-dismissible .close { + position: relative; + top: -2px; + right: -21px; + color: inherit; +} +.alert-success { + background-color: #dff0d8; + border-color: #d6e9c6; + color: #3c763d; +} +.alert-success hr { + border-top-color: #c9e2b3; +} +.alert-success .alert-link { + color: #2b542c; +} +.alert-info { + background-color: #d9edf7; + border-color: #bce8f1; + color: #31708f; +} +.alert-info hr { + border-top-color: #a6e1ec; +} +.alert-info .alert-link { + color: #245269; +} +.alert-warning { + background-color: #fcf8e3; + border-color: #faebcc; + color: #8a6d3b; +} +.alert-warning hr { + border-top-color: #f7e1b5; +} +.alert-warning .alert-link { + color: #66512c; +} +.alert-danger { + background-color: #f2dede; + border-color: #ebccd1; + color: #a94442; +} +.alert-danger hr { + border-top-color: #e4b9c0; +} +.alert-danger .alert-link { + color: #843534; +} +@-webkit-keyframes progress-bar-stripes { + from { + background-position: 40px 0; + } + to { + background-position: 0 0; + } +} +@-o-keyframes progress-bar-stripes { + from { + background-position: 40px 0; + } + to { + background-position: 0 0; + } +} +@keyframes progress-bar-stripes { + from { + background-position: 40px 0; + } + to { + background-position: 0 0; + } +} +.progress { + overflow: hidden; + height: 20px; + margin-bottom: 20px; + background-color: #f5f7f8; + border-radius: 4px; + -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); + box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); +} +.progress-bar { + float: left; + width: 0%; + height: 100%; + font-size: 12px; + line-height: 20px; + color: #fff; + text-align: center; + background-color: #337ab7; + -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); + box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); + -webkit-transition: width 0.6s ease; + -o-transition: width 0.6s ease; + transition: width 0.6s ease; +} +.progress-striped .progress-bar, +.progress-bar-striped { + background-image: -webkit-linear-gradient( + 45deg, + rgba(255, 255, 255, 0.15) 25%, + transparent 25%, + transparent 50%, + rgba(255, 255, 255, 0.15) 50%, + rgba(255, 255, 255, 0.15) 75%, + transparent 75%, + transparent + ); + background-image: -o-linear-gradient( + 45deg, + rgba(255, 255, 255, 0.15) 25%, + transparent 25%, + transparent 50%, + rgba(255, 255, 255, 0.15) 50%, + rgba(255, 255, 255, 0.15) 75%, + transparent 75%, + transparent + ); + background-image: linear-gradient( + 45deg, + rgba(255, 255, 255, 0.15) 25%, + transparent 25%, + transparent 50%, + rgba(255, 255, 255, 0.15) 50%, + rgba(255, 255, 255, 0.15) 75%, + transparent 75%, + transparent + ); + -webkit-background-size: 40px 40px; + background-size: 40px 40px; +} +.progress.active .progress-bar, +.progress-bar.active { + -webkit-animation: progress-bar-stripes 2s linear infinite; + -o-animation: progress-bar-stripes 2s linear infinite; + animation: progress-bar-stripes 2s linear infinite; +} +.progress-bar-success { + background-color: #5cb85c; +} +.progress-striped .progress-bar-success { + background-image: -webkit-linear-gradient( + 45deg, + rgba(255, 255, 255, 0.15) 25%, + transparent 25%, + transparent 50%, + rgba(255, 255, 255, 0.15) 50%, + rgba(255, 255, 255, 0.15) 75%, + transparent 75%, + transparent + ); + background-image: -o-linear-gradient( + 45deg, + rgba(255, 255, 255, 0.15) 25%, + transparent 25%, + transparent 50%, + rgba(255, 255, 255, 0.15) 50%, + rgba(255, 255, 255, 0.15) 75%, + transparent 75%, + transparent + ); + background-image: linear-gradient( + 45deg, + rgba(255, 255, 255, 0.15) 25%, + transparent 25%, + transparent 50%, + rgba(255, 255, 255, 0.15) 50%, + rgba(255, 255, 255, 0.15) 75%, + transparent 75%, + transparent + ); +} +.progress-bar-info { + background-color: #5bc0de; +} +.progress-striped .progress-bar-info { + background-image: -webkit-linear-gradient( + 45deg, + rgba(255, 255, 255, 0.15) 25%, + transparent 25%, + transparent 50%, + rgba(255, 255, 255, 0.15) 50%, + rgba(255, 255, 255, 0.15) 75%, + transparent 75%, + transparent + ); + background-image: -o-linear-gradient( + 45deg, + rgba(255, 255, 255, 0.15) 25%, + transparent 25%, + transparent 50%, + rgba(255, 255, 255, 0.15) 50%, + rgba(255, 255, 255, 0.15) 75%, + transparent 75%, + transparent + ); + background-image: linear-gradient( + 45deg, + rgba(255, 255, 255, 0.15) 25%, + transparent 25%, + transparent 50%, + rgba(255, 255, 255, 0.15) 50%, + rgba(255, 255, 255, 0.15) 75%, + transparent 75%, + transparent + ); +} +.progress-bar-warning { + background-color: #f0ad4e; +} +.progress-striped .progress-bar-warning { + background-image: -webkit-linear-gradient( + 45deg, + rgba(255, 255, 255, 0.15) 25%, + transparent 25%, + transparent 50%, + rgba(255, 255, 255, 0.15) 50%, + rgba(255, 255, 255, 0.15) 75%, + transparent 75%, + transparent + ); + background-image: -o-linear-gradient( + 45deg, + rgba(255, 255, 255, 0.15) 25%, + transparent 25%, + transparent 50%, + rgba(255, 255, 255, 0.15) 50%, + rgba(255, 255, 255, 0.15) 75%, + transparent 75%, + transparent + ); + background-image: linear-gradient( + 45deg, + rgba(255, 255, 255, 0.15) 25%, + transparent 25%, + transparent 50%, + rgba(255, 255, 255, 0.15) 50%, + rgba(255, 255, 255, 0.15) 75%, + transparent 75%, + transparent + ); +} +.progress-bar-danger { + background-color: #d9534f; +} +.progress-striped .progress-bar-danger { + background-image: -webkit-linear-gradient( + 45deg, + rgba(255, 255, 255, 0.15) 25%, + transparent 25%, + transparent 50%, + rgba(255, 255, 255, 0.15) 50%, + rgba(255, 255, 255, 0.15) 75%, + transparent 75%, + transparent + ); + background-image: -o-linear-gradient( + 45deg, + rgba(255, 255, 255, 0.15) 25%, + transparent 25%, + transparent 50%, + rgba(255, 255, 255, 0.15) 50%, + rgba(255, 255, 255, 0.15) 75%, + transparent 75%, + transparent + ); + background-image: linear-gradient( + 45deg, + rgba(255, 255, 255, 0.15) 25%, + transparent 25%, + transparent 50%, + rgba(255, 255, 255, 0.15) 50%, + rgba(255, 255, 255, 0.15) 75%, + transparent 75%, + transparent + ); +} +.media { + margin-top: 15px; +} +.media:first-child { + margin-top: 0; +} +.media, +.media-body { + zoom: 1; + overflow: hidden; +} +.media-body { + width: 10000px; +} +.media-object { + display: block; +} +.media-object.img-thumbnail { + max-width: none; +} +.media-right, +.media > .pull-right { + padding-left: 10px; +} +.media-left, +.media > .pull-left { + padding-right: 10px; +} +.media-left, +.media-right, +.media-body { + display: table-cell; + vertical-align: top; +} +.media-middle { + vertical-align: middle; +} +.media-bottom { + vertical-align: bottom; +} +.media-heading { + margin-top: 0; + margin-bottom: 5px; +} +.media-list { + padding-left: 0; + list-style: none; +} +.list-group { + margin-bottom: 20px; + padding-left: 0; +} +.list-group-item { + position: relative; + display: block; + padding: 10px 15px; + margin-bottom: -1px; + background-color: #fff; + border: 1px solid #ddd; +} +.list-group-item:first-child { + border-top-right-radius: 4px; + border-top-left-radius: 4px; +} +.list-group-item:last-child { + margin-bottom: 0; + border-bottom-right-radius: 4px; + border-bottom-left-radius: 4px; +} +a.list-group-item, +button.list-group-item { + color: #555; +} +a.list-group-item .list-group-item-heading, +button.list-group-item .list-group-item-heading { + color: #333; +} +a.list-group-item:hover, +button.list-group-item:hover, +a.list-group-item:focus, +button.list-group-item:focus { + text-decoration: none; + color: #555; + background-color: #f5f7f8; +} +button.list-group-item { + width: 100%; + text-align: left; +} +.list-group-item.disabled, +.list-group-item.disabled:hover, +.list-group-item.disabled:focus { + background-color: #eee; + color: #777; + cursor: not-allowed; +} +.list-group-item.disabled .list-group-item-heading, +.list-group-item.disabled:hover .list-group-item-heading, +.list-group-item.disabled:focus .list-group-item-heading { + color: inherit; +} +.list-group-item.disabled .list-group-item-text, +.list-group-item.disabled:hover .list-group-item-text, +.list-group-item.disabled:focus .list-group-item-text { + color: #777; +} +.list-group-item.active, +.list-group-item.active:hover, +.list-group-item.active:focus { + z-index: 2; + color: #fff; + background-color: #337ab7; + border-color: #337ab7; +} +.list-group-item.active .list-group-item-heading, +.list-group-item.active:hover .list-group-item-heading, +.list-group-item.active:focus .list-group-item-heading, +.list-group-item.active .list-group-item-heading > small, +.list-group-item.active:hover .list-group-item-heading > small, +.list-group-item.active:focus .list-group-item-heading > small, +.list-group-item.active .list-group-item-heading > .small, +.list-group-item.active:hover .list-group-item-heading > .small, +.list-group-item.active:focus .list-group-item-heading > .small { + color: inherit; +} +.list-group-item.active .list-group-item-text, +.list-group-item.active:hover .list-group-item-text, +.list-group-item.active:focus .list-group-item-text { + color: #c7ddef; +} +.list-group-item-success { + color: #3c763d; + background-color: #dff0d8; +} +a.list-group-item-success, +button.list-group-item-success { + color: #3c763d; +} +a.list-group-item-success .list-group-item-heading, +button.list-group-item-success .list-group-item-heading { + color: inherit; +} +a.list-group-item-success:hover, +button.list-group-item-success:hover, +a.list-group-item-success:focus, +button.list-group-item-success:focus { + color: #3c763d; + background-color: #d0e9c6; +} +a.list-group-item-success.active, +button.list-group-item-success.active, +a.list-group-item-success.active:hover, +button.list-group-item-success.active:hover, +a.list-group-item-success.active:focus, +button.list-group-item-success.active:focus { + color: #fff; + background-color: #3c763d; + border-color: #3c763d; +} +.list-group-item-info { + color: #31708f; + background-color: #d9edf7; +} +a.list-group-item-info, +button.list-group-item-info { + color: #31708f; +} +a.list-group-item-info .list-group-item-heading, +button.list-group-item-info .list-group-item-heading { + color: inherit; +} +a.list-group-item-info:hover, +button.list-group-item-info:hover, +a.list-group-item-info:focus, +button.list-group-item-info:focus { + color: #31708f; + background-color: #c4e3f3; +} +a.list-group-item-info.active, +button.list-group-item-info.active, +a.list-group-item-info.active:hover, +button.list-group-item-info.active:hover, +a.list-group-item-info.active:focus, +button.list-group-item-info.active:focus { + color: #fff; + background-color: #31708f; + border-color: #31708f; +} +.list-group-item-warning { + color: #8a6d3b; + background-color: #fcf8e3; +} +a.list-group-item-warning, +button.list-group-item-warning { + color: #8a6d3b; +} +a.list-group-item-warning .list-group-item-heading, +button.list-group-item-warning .list-group-item-heading { + color: inherit; +} +a.list-group-item-warning:hover, +button.list-group-item-warning:hover, +a.list-group-item-warning:focus, +button.list-group-item-warning:focus { + color: #8a6d3b; + background-color: #faf2cc; +} +a.list-group-item-warning.active, +button.list-group-item-warning.active, +a.list-group-item-warning.active:hover, +button.list-group-item-warning.active:hover, +a.list-group-item-warning.active:focus, +button.list-group-item-warning.active:focus { + color: #fff; + background-color: #8a6d3b; + border-color: #8a6d3b; +} +.list-group-item-danger { + color: #a94442; + background-color: #f2dede; +} +a.list-group-item-danger, +button.list-group-item-danger { + color: #a94442; +} +a.list-group-item-danger .list-group-item-heading, +button.list-group-item-danger .list-group-item-heading { + color: inherit; +} +a.list-group-item-danger:hover, +button.list-group-item-danger:hover, +a.list-group-item-danger:focus, +button.list-group-item-danger:focus { + color: #a94442; + background-color: #ebcccc; +} +a.list-group-item-danger.active, +button.list-group-item-danger.active, +a.list-group-item-danger.active:hover, +button.list-group-item-danger.active:hover, +a.list-group-item-danger.active:focus, +button.list-group-item-danger.active:focus { + color: #fff; + background-color: #a94442; + border-color: #a94442; +} +.list-group-item-heading { + margin-top: 0; + margin-bottom: 5px; +} +.list-group-item-text { + margin-bottom: 0; + line-height: 1.3; +} +.panel { + margin-bottom: 20px; + background-color: #fff; + border: 1px solid transparent; + border-radius: 4px; + -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05); + box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05); +} +.panel-body { + padding: 15px; +} +.panel-heading { + padding: 10px 15px; + border-bottom: 1px solid transparent; + border-top-right-radius: 3px; + border-top-left-radius: 3px; +} +.panel-heading > .dropdown .dropdown-toggle { + color: inherit; +} +.panel-title { + margin-top: 0; + margin-bottom: 0; + font-size: 16px; + color: inherit; +} +.panel-title > a, +.panel-title > small, +.panel-title > .small, +.panel-title > small > a, +.panel-title > .small > a { + color: inherit; +} +.panel-footer { + padding: 10px 15px; + background-color: #f5f7f8; + border-top: 1px solid #ddd; + border-bottom-right-radius: 3px; + border-bottom-left-radius: 3px; +} +.panel > .list-group, +.panel > .panel-collapse > .list-group { + margin-bottom: 0; +} +.panel > .list-group .list-group-item, +.panel > .panel-collapse > .list-group .list-group-item { + border-width: 1px 0; + border-radius: 0; +} +.panel > .list-group:first-child .list-group-item:first-child, +.panel + > .panel-collapse + > .list-group:first-child + .list-group-item:first-child { + border-top: 0; + border-top-right-radius: 3px; + border-top-left-radius: 3px; +} +.panel > .list-group:last-child .list-group-item:last-child, +.panel > .panel-collapse > .list-group:last-child .list-group-item:last-child { + border-bottom: 0; + border-bottom-right-radius: 3px; + border-bottom-left-radius: 3px; +} +.panel + > .panel-heading + + .panel-collapse + > .list-group + .list-group-item:first-child { + border-top-right-radius: 0; + border-top-left-radius: 0; +} +.panel-heading + .list-group .list-group-item:first-child { + border-top-width: 0; +} +.list-group + .panel-footer { + border-top-width: 0; +} +.panel > .table, +.panel > .table-responsive > .table, +.panel > .panel-collapse > .table { + margin-bottom: 0; +} +.panel > .table caption, +.panel > .table-responsive > .table caption, +.panel > .panel-collapse > .table caption { + padding-left: 15px; + padding-right: 15px; +} +.panel > .table:first-child, +.panel > .table-responsive:first-child > .table:first-child { + border-top-right-radius: 3px; + border-top-left-radius: 3px; +} +.panel > .table:first-child > thead:first-child > tr:first-child, +.panel + > .table-responsive:first-child + > .table:first-child + > thead:first-child + > tr:first-child, +.panel > .table:first-child > tbody:first-child > tr:first-child, +.panel + > .table-responsive:first-child + > .table:first-child + > tbody:first-child + > tr:first-child { + border-top-left-radius: 3px; + border-top-right-radius: 3px; +} +.panel > .table:first-child > thead:first-child > tr:first-child td:first-child, +.panel + > .table-responsive:first-child + > .table:first-child + > thead:first-child + > tr:first-child + td:first-child, +.panel > .table:first-child > tbody:first-child > tr:first-child td:first-child, +.panel + > .table-responsive:first-child + > .table:first-child + > tbody:first-child + > tr:first-child + td:first-child, +.panel > .table:first-child > thead:first-child > tr:first-child th:first-child, +.panel + > .table-responsive:first-child + > .table:first-child + > thead:first-child + > tr:first-child + th:first-child, +.panel > .table:first-child > tbody:first-child > tr:first-child th:first-child, +.panel + > .table-responsive:first-child + > .table:first-child + > tbody:first-child + > tr:first-child + th:first-child { + border-top-left-radius: 3px; +} +.panel > .table:first-child > thead:first-child > tr:first-child td:last-child, +.panel + > .table-responsive:first-child + > .table:first-child + > thead:first-child + > tr:first-child + td:last-child, +.panel > .table:first-child > tbody:first-child > tr:first-child td:last-child, +.panel + > .table-responsive:first-child + > .table:first-child + > tbody:first-child + > tr:first-child + td:last-child, +.panel > .table:first-child > thead:first-child > tr:first-child th:last-child, +.panel + > .table-responsive:first-child + > .table:first-child + > thead:first-child + > tr:first-child + th:last-child, +.panel > .table:first-child > tbody:first-child > tr:first-child th:last-child, +.panel + > .table-responsive:first-child + > .table:first-child + > tbody:first-child + > tr:first-child + th:last-child { + border-top-right-radius: 3px; +} +.panel > .table:last-child, +.panel > .table-responsive:last-child > .table:last-child { + border-bottom-right-radius: 3px; + border-bottom-left-radius: 3px; +} +.panel > .table:last-child > tbody:last-child > tr:last-child, +.panel + > .table-responsive:last-child + > .table:last-child + > tbody:last-child + > tr:last-child, +.panel > .table:last-child > tfoot:last-child > tr:last-child, +.panel + > .table-responsive:last-child + > .table:last-child + > tfoot:last-child + > tr:last-child { + border-bottom-left-radius: 3px; + border-bottom-right-radius: 3px; +} +.panel > .table:last-child > tbody:last-child > tr:last-child td:first-child, +.panel + > .table-responsive:last-child + > .table:last-child + > tbody:last-child + > tr:last-child + td:first-child, +.panel > .table:last-child > tfoot:last-child > tr:last-child td:first-child, +.panel + > .table-responsive:last-child + > .table:last-child + > tfoot:last-child + > tr:last-child + td:first-child, +.panel > .table:last-child > tbody:last-child > tr:last-child th:first-child, +.panel + > .table-responsive:last-child + > .table:last-child + > tbody:last-child + > tr:last-child + th:first-child, +.panel > .table:last-child > tfoot:last-child > tr:last-child th:first-child, +.panel + > .table-responsive:last-child + > .table:last-child + > tfoot:last-child + > tr:last-child + th:first-child { + border-bottom-left-radius: 3px; +} +.panel > .table:last-child > tbody:last-child > tr:last-child td:last-child, +.panel + > .table-responsive:last-child + > .table:last-child + > tbody:last-child + > tr:last-child + td:last-child, +.panel > .table:last-child > tfoot:last-child > tr:last-child td:last-child, +.panel + > .table-responsive:last-child + > .table:last-child + > tfoot:last-child + > tr:last-child + td:last-child, +.panel > .table:last-child > tbody:last-child > tr:last-child th:last-child, +.panel + > .table-responsive:last-child + > .table:last-child + > tbody:last-child + > tr:last-child + th:last-child, +.panel > .table:last-child > tfoot:last-child > tr:last-child th:last-child, +.panel + > .table-responsive:last-child + > .table:last-child + > tfoot:last-child + > tr:last-child + th:last-child { + border-bottom-right-radius: 3px; +} +.panel > .panel-body + .table, +.panel > .panel-body + .table-responsive, +.panel > .table + .panel-body, +.panel > .table-responsive + .panel-body { + border-top: 1px solid #ddd; +} +.panel > .table > tbody:first-child > tr:first-child th, +.panel > .table > tbody:first-child > tr:first-child td { + border-top: 0; +} +.panel > .table-bordered, +.panel > .table-responsive > .table-bordered { + border: 0; +} +.panel > .table-bordered > thead > tr > th:first-child, +.panel > .table-responsive > .table-bordered > thead > tr > th:first-child, +.panel > .table-bordered > tbody > tr > th:first-child, +.panel > .table-responsive > .table-bordered > tbody > tr > th:first-child, +.panel > .table-bordered > tfoot > tr > th:first-child, +.panel > .table-responsive > .table-bordered > tfoot > tr > th:first-child, +.panel > .table-bordered > thead > tr > td:first-child, +.panel > .table-responsive > .table-bordered > thead > tr > td:first-child, +.panel > .table-bordered > tbody > tr > td:first-child, +.panel > .table-responsive > .table-bordered > tbody > tr > td:first-child, +.panel > .table-bordered > tfoot > tr > td:first-child, +.panel > .table-responsive > .table-bordered > tfoot > tr > td:first-child { + border-left: 0; +} +.panel > .table-bordered > thead > tr > th:last-child, +.panel > .table-responsive > .table-bordered > thead > tr > th:last-child, +.panel > .table-bordered > tbody > tr > th:last-child, +.panel > .table-responsive > .table-bordered > tbody > tr > th:last-child, +.panel > .table-bordered > tfoot > tr > th:last-child, +.panel > .table-responsive > .table-bordered > tfoot > tr > th:last-child, +.panel > .table-bordered > thead > tr > td:last-child, +.panel > .table-responsive > .table-bordered > thead > tr > td:last-child, +.panel > .table-bordered > tbody > tr > td:last-child, +.panel > .table-responsive > .table-bordered > tbody > tr > td:last-child, +.panel > .table-bordered > tfoot > tr > td:last-child, +.panel > .table-responsive > .table-bordered > tfoot > tr > td:last-child { + border-right: 0; +} +.panel > .table-bordered > thead > tr:first-child > td, +.panel > .table-responsive > .table-bordered > thead > tr:first-child > td, +.panel > .table-bordered > tbody > tr:first-child > td, +.panel > .table-responsive > .table-bordered > tbody > tr:first-child > td, +.panel > .table-bordered > thead > tr:first-child > th, +.panel > .table-responsive > .table-bordered > thead > tr:first-child > th, +.panel > .table-bordered > tbody > tr:first-child > th, +.panel > .table-responsive > .table-bordered > tbody > tr:first-child > th { + border-bottom: 0; +} +.panel > .table-bordered > tbody > tr:last-child > td, +.panel > .table-responsive > .table-bordered > tbody > tr:last-child > td, +.panel > .table-bordered > tfoot > tr:last-child > td, +.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > td, +.panel > .table-bordered > tbody > tr:last-child > th, +.panel > .table-responsive > .table-bordered > tbody > tr:last-child > th, +.panel > .table-bordered > tfoot > tr:last-child > th, +.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > th { + border-bottom: 0; +} +.panel > .table-responsive { + border: 0; + margin-bottom: 0; +} +.panel-group { + margin-bottom: 20px; +} +.panel-group .panel { + margin-bottom: 0; + border-radius: 4px; +} +.panel-group .panel + .panel { + margin-top: 5px; +} +.panel-group .panel-heading { + border-bottom: 0; +} +.panel-group .panel-heading + .panel-collapse > .panel-body, +.panel-group .panel-heading + .panel-collapse > .list-group { + border-top: 1px solid #ddd; +} +.panel-group .panel-footer { + border-top: 0; +} +.panel-group .panel-footer + .panel-collapse .panel-body { + border-bottom: 1px solid #ddd; +} +.panel-default { + border-color: #ddd; +} +.panel-default > .panel-heading { + color: #333; + background-color: #f5f7f8; + border-color: #ddd; +} +.panel-default > .panel-heading + .panel-collapse > .panel-body { + border-top-color: #ddd; +} +.panel-default > .panel-heading .badge { + color: #f5f7f8; + background-color: #333; +} +.panel-default > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: #ddd; +} +.panel-primary { + border-color: #337ab7; +} +.panel-primary > .panel-heading { + color: #fff; + background-color: #337ab7; + border-color: #337ab7; +} +.panel-primary > .panel-heading + .panel-collapse > .panel-body { + border-top-color: #337ab7; +} +.panel-primary > .panel-heading .badge { + color: #337ab7; + background-color: #fff; +} +.panel-primary > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: #337ab7; +} +.panel-success { + border-color: #d6e9c6; +} +.panel-success > .panel-heading { + color: #3c763d; + background-color: #dff0d8; + border-color: #d6e9c6; +} +.panel-success > .panel-heading + .panel-collapse > .panel-body { + border-top-color: #d6e9c6; +} +.panel-success > .panel-heading .badge { + color: #dff0d8; + background-color: #3c763d; +} +.panel-success > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: #d6e9c6; +} +.panel-info { + border-color: #bce8f1; +} +.panel-info > .panel-heading { + color: #31708f; + background-color: #d9edf7; + border-color: #bce8f1; +} +.panel-info > .panel-heading + .panel-collapse > .panel-body { + border-top-color: #bce8f1; +} +.panel-info > .panel-heading .badge { + color: #d9edf7; + background-color: #31708f; +} +.panel-info > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: #bce8f1; +} +.panel-warning { + border-color: #faebcc; +} +.panel-warning > .panel-heading { + color: #8a6d3b; + background-color: #fcf8e3; + border-color: #faebcc; +} +.panel-warning > .panel-heading + .panel-collapse > .panel-body { + border-top-color: #faebcc; +} +.panel-warning > .panel-heading .badge { + color: #fcf8e3; + background-color: #8a6d3b; +} +.panel-warning > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: #faebcc; +} +.panel-danger { + border-color: #ebccd1; +} +.panel-danger > .panel-heading { + color: #a94442; + background-color: #f2dede; + border-color: #ebccd1; +} +.panel-danger > .panel-heading + .panel-collapse > .panel-body { + border-top-color: #ebccd1; +} +.panel-danger > .panel-heading .badge { + color: #f2dede; + background-color: #a94442; +} +.panel-danger > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: #ebccd1; +} +.embed-responsive { + position: relative; + display: block; + height: 0; + padding: 0; + overflow: hidden; +} +.embed-responsive .embed-responsive-item, +.embed-responsive iframe, +.embed-responsive embed, +.embed-responsive object, +.embed-responsive video { + position: absolute; + top: 0; + left: 0; + bottom: 0; + height: 100%; + width: 100%; + border: 0; +} +.embed-responsive-16by9 { + padding-bottom: 56.25%; +} +.embed-responsive-4by3 { + padding-bottom: 75%; +} +.well { + min-height: 20px; + padding: 19px; + margin-bottom: 20px; + background-color: #f5f7f8; + border: 1px solid #e0e6e9; + border-radius: 4px; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05); +} +.well blockquote { + border-color: #ddd; + border-color: rgba(0, 0, 0, 0.15); +} +.well-lg { + padding: 24px; + border-radius: 6px; +} +.well-sm { + padding: 9px; + border-radius: 3px; +} +.close { + float: right; + font-size: 21px; + font-weight: bold; + line-height: 1; + color: #000; + text-shadow: 0 1px 0 #fff; + opacity: 0.2; + filter: alpha(opacity=20); +} +.close:hover, +.close:focus { + color: #000; + text-decoration: none; + cursor: pointer; + opacity: 0.5; + filter: alpha(opacity=50); +} +button.close { + padding: 0; + cursor: pointer; + background: transparent; + border: 0; + -webkit-appearance: none; +} +.modal-open { + overflow: hidden; +} +.modal { + display: none; + overflow: hidden; + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 1050; + -webkit-overflow-scrolling: touch; + outline: 0; +} +.modal.fade .modal-dialog { + -webkit-transform: translate(0, -25%); + -ms-transform: translate(0, -25%); + -o-transform: translate(0, -25%); + transform: translate(0, -25%); + -webkit-transition: -webkit-transform 0.3s ease-out; + -o-transition: -o-transform 0.3s ease-out; + transition: transform 0.3s ease-out; +} +.modal.in .modal-dialog { + -webkit-transform: translate(0, 0); + -ms-transform: translate(0, 0); + -o-transform: translate(0, 0); + transform: translate(0, 0); +} +.modal-open .modal { + overflow-x: hidden; + overflow-y: auto; +} +.modal-dialog { + position: relative; + width: auto; + margin: 10px; +} +.modal-content { + position: relative; + background-color: #fff; + border: 1px solid #999; + border: 1px solid rgba(0, 0, 0, 0.2); + border-radius: 6px; + -webkit-box-shadow: 0 3px 9px rgba(0, 0, 0, 0.5); + box-shadow: 0 3px 9px rgba(0, 0, 0, 0.5); + -webkit-background-clip: padding-box; + background-clip: padding-box; + outline: 0; +} +.modal-backdrop { + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 1040; + background-color: #000; +} +.modal-backdrop.fade { + opacity: 0; + filter: alpha(opacity=0); +} +.modal-backdrop.in { + opacity: 0.5; + filter: alpha(opacity=50); +} +.modal-header { + padding: 15px; + border-bottom: 1px solid #e5e5e5; +} +.modal-header .close { + margin-top: -2px; +} +.modal-title { + margin: 0; + line-height: 1.42857143; +} +.modal-body { + position: relative; + padding: 15px; +} +.modal-footer { + padding: 15px; + text-align: right; + border-top: 1px solid #e5e5e5; +} +.modal-footer .btn + .btn { + margin-left: 5px; + margin-bottom: 0; +} +.modal-footer .btn-group .btn + .btn { + margin-left: -1px; +} +.modal-footer .btn-block + .btn-block { + margin-left: 0; +} +.modal-scrollbar-measure { + position: absolute; + top: -9999px; + width: 50px; + height: 50px; + overflow: scroll; +} +@media (min-width: 768px) { + .modal-dialog { + width: 600px; + margin: 30px auto; + } + .modal-content { + -webkit-box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5); + box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5); + } + .modal-sm { + width: 300px; + } +} +@media (min-width: 992px) { + .modal-lg { + width: 900px; + } +} +.tooltip { + position: absolute; + z-index: 1070; + display: block; + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-style: normal; + font-weight: normal; + letter-spacing: normal; + line-break: auto; + line-height: 1.42857143; + text-align: left; + text-align: start; + text-decoration: none; + text-shadow: none; + text-transform: none; + white-space: normal; + word-break: normal; + word-spacing: normal; + word-wrap: normal; + font-size: 12px; + opacity: 0; + filter: alpha(opacity=0); +} +.tooltip.in { + opacity: 0.9; + filter: alpha(opacity=90); +} +.tooltip.top { + margin-top: -3px; + padding: 5px 0; +} +.tooltip.right { + margin-left: 3px; + padding: 0 5px; +} +.tooltip.bottom { + margin-top: 3px; + padding: 5px 0; +} +.tooltip.left { + margin-left: -3px; + padding: 0 5px; +} +.tooltip-inner { + max-width: 200px; + padding: 3px 8px; + color: #fff; + text-align: center; + background-color: #000; + border-radius: 4px; +} +.tooltip-arrow { + position: absolute; + width: 0; + height: 0; + border-color: transparent; + border-style: solid; +} +.tooltip.top .tooltip-arrow { + bottom: 0; + left: 50%; + margin-left: -5px; + border-width: 5px 5px 0; + border-top-color: #000; +} +.tooltip.top-left .tooltip-arrow { + bottom: 0; + right: 5px; + margin-bottom: -5px; + border-width: 5px 5px 0; + border-top-color: #000; +} +.tooltip.top-right .tooltip-arrow { + bottom: 0; + left: 5px; + margin-bottom: -5px; + border-width: 5px 5px 0; + border-top-color: #000; +} +.tooltip.right .tooltip-arrow { + top: 50%; + left: 0; + margin-top: -5px; + border-width: 5px 5px 5px 0; + border-right-color: #000; +} +.tooltip.left .tooltip-arrow { + top: 50%; + right: 0; + margin-top: -5px; + border-width: 5px 0 5px 5px; + border-left-color: #000; +} +.tooltip.bottom .tooltip-arrow { + top: 0; + left: 50%; + margin-left: -5px; + border-width: 0 5px 5px; + border-bottom-color: #000; +} +.tooltip.bottom-left .tooltip-arrow { + top: 0; + right: 5px; + margin-top: -5px; + border-width: 0 5px 5px; + border-bottom-color: #000; +} +.tooltip.bottom-right .tooltip-arrow { + top: 0; + left: 5px; + margin-top: -5px; + border-width: 0 5px 5px; + border-bottom-color: #000; +} +.popover { + position: absolute; + top: 0; + left: 0; + z-index: 1060; + display: none; + max-width: 276px; + padding: 1px; + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-style: normal; + font-weight: normal; + letter-spacing: normal; + line-break: auto; + line-height: 1.42857143; + text-align: left; + text-align: start; + text-decoration: none; + text-shadow: none; + text-transform: none; + white-space: normal; + word-break: normal; + word-spacing: normal; + word-wrap: normal; + font-size: 14px; + background-color: #fff; + -webkit-background-clip: padding-box; + background-clip: padding-box; + border: 1px solid #ccc; + border: 1px solid rgba(0, 0, 0, 0.2); + border-radius: 6px; + -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); + box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); +} +.popover.top { + margin-top: -10px; +} +.popover.right { + margin-left: 10px; +} +.popover.bottom { + margin-top: 10px; +} +.popover.left { + margin-left: -10px; +} +.popover-title { + margin: 0; + padding: 8px 14px; + font-size: 14px; + background-color: #f7f7f7; + border-bottom: 1px solid #ebebeb; + border-radius: 5px 5px 0 0; +} +.popover-content { + padding: 9px 14px; +} +.popover > .arrow, +.popover > .arrow:after { + position: absolute; + display: block; + width: 0; + height: 0; + border-color: transparent; + border-style: solid; +} +.popover > .arrow { + border-width: 11px; +} +.popover > .arrow:after { + border-width: 10px; + content: ""; +} +.popover.top > .arrow { + left: 50%; + margin-left: -11px; + border-bottom-width: 0; + border-top-color: #999; + border-top-color: rgba(0, 0, 0, 0.25); + bottom: -11px; +} +.popover.top > .arrow:after { + content: " "; + bottom: 1px; + margin-left: -10px; + border-bottom-width: 0; + border-top-color: #fff; +} +.popover.right > .arrow { + top: 50%; + left: -11px; + margin-top: -11px; + border-left-width: 0; + border-right-color: #999; + border-right-color: rgba(0, 0, 0, 0.25); +} +.popover.right > .arrow:after { + content: " "; + left: 1px; + bottom: -10px; + border-left-width: 0; + border-right-color: #fff; +} +.popover.bottom > .arrow { + left: 50%; + margin-left: -11px; + border-top-width: 0; + border-bottom-color: #999; + border-bottom-color: rgba(0, 0, 0, 0.25); + top: -11px; +} +.popover.bottom > .arrow:after { + content: " "; + top: 1px; + margin-left: -10px; + border-top-width: 0; + border-bottom-color: #fff; +} +.popover.left > .arrow { + top: 50%; + right: -11px; + margin-top: -11px; + border-right-width: 0; + border-left-color: #999; + border-left-color: rgba(0, 0, 0, 0.25); +} +.popover.left > .arrow:after { + content: " "; + right: 1px; + border-right-width: 0; + border-left-color: #fff; + bottom: -10px; +} +.carousel { + position: relative; +} +.carousel-inner { + position: relative; + overflow: hidden; + width: 100%; +} +.carousel-inner > .item { + display: none; + position: relative; + -webkit-transition: 0.6s ease-in-out left; + -o-transition: 0.6s ease-in-out left; + transition: 0.6s ease-in-out left; +} +.carousel-inner > .item > img, +.carousel-inner > .item > a > img { + line-height: 1; +} +@media all and (transform-3d), (-webkit-transform-3d) { + .carousel-inner > .item { + -webkit-transition: -webkit-transform 0.6s ease-in-out; + -o-transition: -o-transform 0.6s ease-in-out; + transition: transform 0.6s ease-in-out; + -webkit-backface-visibility: hidden; + backface-visibility: hidden; + -webkit-perspective: 1000px; + perspective: 1000px; + } + .carousel-inner > .item.next, + .carousel-inner > .item.active.right { + -webkit-transform: translate3d(100%, 0, 0); + transform: translate3d(100%, 0, 0); + left: 0; + } + .carousel-inner > .item.prev, + .carousel-inner > .item.active.left { + -webkit-transform: translate3d(-100%, 0, 0); + transform: translate3d(-100%, 0, 0); + left: 0; + } + .carousel-inner > .item.next.left, + .carousel-inner > .item.prev.right, + .carousel-inner > .item.active { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + left: 0; + } +} +.carousel-inner > .active, +.carousel-inner > .next, +.carousel-inner > .prev { + display: block; +} +.carousel-inner > .active { + left: 0; +} +.carousel-inner > .next, +.carousel-inner > .prev { + position: absolute; + top: 0; + width: 100%; +} +.carousel-inner > .next { + left: 100%; +} +.carousel-inner > .prev { + left: -100%; +} +.carousel-inner > .next.left, +.carousel-inner > .prev.right { + left: 0; +} +.carousel-inner > .active.left { + left: -100%; +} +.carousel-inner > .active.right { + left: 100%; +} +.carousel-control { + position: absolute; + top: 0; + left: 0; + bottom: 0; + width: 15%; + opacity: 0.5; + filter: alpha(opacity=50); + font-size: 20px; + color: #fff; + text-align: center; + text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6); + background-color: rgba(0, 0, 0, 0); +} +.carousel-control.left { + background-image: -webkit-linear-gradient( + left, + rgba(0, 0, 0, 0.5) 0, + rgba(0, 0, 0, 0.0001) 100% + ); + background-image: -o-linear-gradient( + left, + rgba(0, 0, 0, 0.5) 0, + rgba(0, 0, 0, 0.0001) 100% + ); + background-image: -webkit-gradient( + linear, + left top, + right top, + color-stop(0, rgba(0, 0, 0, 0.5)), + to(rgba(0, 0, 0, 0.0001)) + ); + background-image: linear-gradient( + to right, + rgba(0, 0, 0, 0.5) 0, + rgba(0, 0, 0, 0.0001) 100% + ); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1); +} +.carousel-control.right { + left: auto; + right: 0; + background-image: -webkit-linear-gradient( + left, + rgba(0, 0, 0, 0.0001) 0, + rgba(0, 0, 0, 0.5) 100% + ); + background-image: -o-linear-gradient( + left, + rgba(0, 0, 0, 0.0001) 0, + rgba(0, 0, 0, 0.5) 100% + ); + background-image: -webkit-gradient( + linear, + left top, + right top, + color-stop(0, rgba(0, 0, 0, 0.0001)), + to(rgba(0, 0, 0, 0.5)) + ); + background-image: linear-gradient( + to right, + rgba(0, 0, 0, 0.0001) 0, + rgba(0, 0, 0, 0.5) 100% + ); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1); +} +.carousel-control:hover, +.carousel-control:focus { + outline: 0; + color: #fff; + text-decoration: none; + opacity: 0.9; + filter: alpha(opacity=90); +} +.carousel-control .icon-prev, +.carousel-control .icon-next, +.carousel-control .glyphicon-chevron-left, +.carousel-control .glyphicon-chevron-right { + position: absolute; + top: 50%; + margin-top: -10px; + z-index: 5; + display: inline-block; +} +.carousel-control .icon-prev, +.carousel-control .glyphicon-chevron-left { + left: 50%; + margin-left: -10px; +} +.carousel-control .icon-next, +.carousel-control .glyphicon-chevron-right { + right: 50%; + margin-right: -10px; +} +.carousel-control .icon-prev, +.carousel-control .icon-next { + width: 20px; + height: 20px; + line-height: 1; + font-family: serif; +} +.carousel-control .icon-prev:before { + content: "\2039"; +} +.carousel-control .icon-next:before { + content: "\203a"; +} +.carousel-indicators { + position: absolute; + bottom: 10px; + left: 50%; + z-index: 15; + width: 60%; + margin-left: -30%; + padding-left: 0; + list-style: none; + text-align: center; +} +.carousel-indicators li { + display: inline-block; + width: 10px; + height: 10px; + margin: 1px; + text-indent: -999px; + border: 1px solid #fff; + border-radius: 10px; + cursor: pointer; + background-color: #000 \9; + background-color: rgba(0, 0, 0, 0); +} +.carousel-indicators .active { + margin: 0; + width: 12px; + height: 12px; + background-color: #fff; +} +.carousel-caption { + position: absolute; + left: 15%; + right: 15%; + bottom: 20px; + z-index: 10; + padding-top: 20px; + padding-bottom: 20px; + color: #fff; + text-align: center; + text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6); +} +.carousel-caption .btn { + text-shadow: none; +} +@media screen and (min-width: 768px) { + .carousel-control .glyphicon-chevron-left, + .carousel-control .glyphicon-chevron-right, + .carousel-control .icon-prev, + .carousel-control .icon-next { + width: 30px; + height: 30px; + margin-top: -10px; + font-size: 30px; + } + .carousel-control .glyphicon-chevron-left, + .carousel-control .icon-prev { + margin-left: -10px; + } + .carousel-control .glyphicon-chevron-right, + .carousel-control .icon-next { + margin-right: -10px; + } + .carousel-caption { + left: 20%; + right: 20%; + padding-bottom: 30px; + } + .carousel-indicators { + bottom: 20px; + } +} +.clearfix:before, +.clearfix:after, +.dl-horizontal dd:before, +.dl-horizontal dd:after, +.container:before, +.container:after, +.container-fluid:before, +.container-fluid:after, +.row:before, +.row:after, +.form-horizontal .form-group:before, +.form-horizontal .form-group:after, +.btn-toolbar:before, +.btn-toolbar:after, +.btn-group-vertical > .btn-group:before, +.btn-group-vertical > .btn-group:after, +.nav:before, +.nav:after, +.navbar:before, +.navbar:after, +.navbar-header:before, +.navbar-header:after, +.navbar-collapse:before, +.navbar-collapse:after, +.pager:before, +.pager:after, +.panel-body:before, +.panel-body:after, +.modal-header:before, +.modal-header:after, +.modal-footer:before, +.modal-footer:after { + content: " "; + display: table; +} +.clearfix:after, +.dl-horizontal dd:after, +.container:after, +.container-fluid:after, +.row:after, +.form-horizontal .form-group:after, +.btn-toolbar:after, +.btn-group-vertical > .btn-group:after, +.nav:after, +.navbar:after, +.navbar-header:after, +.navbar-collapse:after, +.pager:after, +.panel-body:after, +.modal-header:after, +.modal-footer:after { + clear: both; +} +.center-block { + display: block; + margin-left: auto; + margin-right: auto; +} +.pull-right { + float: right !important; +} +.pull-left { + float: left !important; +} +.hide { + display: none !important; +} +.show { + display: block !important; +} +.invisible { + visibility: hidden; +} +.text-hide { + font: 0/0 a; + color: transparent; + text-shadow: none; + background-color: transparent; + border: 0; +} +.hidden { + display: none !important; +} +.affix { + position: fixed; +} +@-ms-viewport { + width: device-width; +} +.visible-xs, +.visible-sm, +.visible-md, +.visible-lg { + display: none !important; +} +.visible-xs-block, +.visible-xs-inline, +.visible-xs-inline-block, +.visible-sm-block, +.visible-sm-inline, +.visible-sm-inline-block, +.visible-md-block, +.visible-md-inline, +.visible-md-inline-block, +.visible-lg-block, +.visible-lg-inline, +.visible-lg-inline-block { + display: none !important; +} +@media (max-width: 767px) { + .visible-xs { + display: block !important; + } + table.visible-xs { + display: table !important; + } + tr.visible-xs { + display: table-row !important; + } + th.visible-xs, + td.visible-xs { + display: table-cell !important; + } +} +@media (max-width: 767px) { + .visible-xs-block { + display: block !important; + } +} +@media (max-width: 767px) { + .visible-xs-inline { + display: inline !important; + } +} +@media (max-width: 767px) { + .visible-xs-inline-block { + display: inline-block !important; + } +} +@media (min-width: 768px) and (max-width: 991px) { + .visible-sm { + display: block !important; + } + table.visible-sm { + display: table !important; + } + tr.visible-sm { + display: table-row !important; + } + th.visible-sm, + td.visible-sm { + display: table-cell !important; + } +} +@media (min-width: 768px) and (max-width: 991px) { + .visible-sm-block { + display: block !important; + } +} +@media (min-width: 768px) and (max-width: 991px) { + .visible-sm-inline { + display: inline !important; + } +} +@media (min-width: 768px) and (max-width: 991px) { + .visible-sm-inline-block { + display: inline-block !important; + } +} +@media (min-width: 992px) and (max-width: 1199px) { + .visible-md { + display: block !important; + } + table.visible-md { + display: table !important; + } + tr.visible-md { + display: table-row !important; + } + th.visible-md, + td.visible-md { + display: table-cell !important; + } +} +@media (min-width: 992px) and (max-width: 1199px) { + .visible-md-block { + display: block !important; + } +} +@media (min-width: 992px) and (max-width: 1199px) { + .visible-md-inline { + display: inline !important; + } +} +@media (min-width: 992px) and (max-width: 1199px) { + .visible-md-inline-block { + display: inline-block !important; + } +} +@media (min-width: 1200px) { + .visible-lg { + display: block !important; + } + table.visible-lg { + display: table !important; + } + tr.visible-lg { + display: table-row !important; + } + th.visible-lg, + td.visible-lg { + display: table-cell !important; + } +} +@media (min-width: 1200px) { + .visible-lg-block { + display: block !important; + } +} +@media (min-width: 1200px) { + .visible-lg-inline { + display: inline !important; + } +} +@media (min-width: 1200px) { + .visible-lg-inline-block { + display: inline-block !important; + } +} +@media (max-width: 767px) { + .hidden-xs { + display: none !important; + } +} +@media (min-width: 768px) and (max-width: 991px) { + .hidden-sm { + display: none !important; + } +} +@media (min-width: 992px) and (max-width: 1199px) { + .hidden-md { + display: none !important; + } +} +@media (min-width: 1200px) { + .hidden-lg { + display: none !important; + } +} +.visible-print { + display: none !important; +} +@media print { + .visible-print { + display: block !important; + } + table.visible-print { + display: table !important; + } + tr.visible-print { + display: table-row !important; + } + th.visible-print, + td.visible-print { + display: table-cell !important; + } +} +.visible-print-block { + display: none !important; +} +@media print { + .visible-print-block { + display: block !important; + } +} +.visible-print-inline { + display: none !important; +} +@media print { + .visible-print-inline { + display: inline !important; + } +} +.visible-print-inline-block { + display: none !important; +} +@media print { + .visible-print-inline-block { + display: inline-block !important; + } +} +@media print { + .hidden-print { + display: none !important; + } +} diff --git a/public/css/font-awesome.min.css b/public/css/font-awesome.min.css index ee4e9782b..67d975b06 100644 --- a/public/css/font-awesome.min.css +++ b/public/css/font-awesome.min.css @@ -1,4 +1,2026 @@ /*! * Font Awesome 4.4.0 by @davegandy - http://fontawesome.io - @fontawesome * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) - */@font-face{font-family:'FontAwesome';src:url('../fonts/fontawesome-webfont.eot?v=4.4.0');src:url('../fonts/fontawesome-webfont.eot?#iefix&v=4.4.0') format('embedded-opentype'),url('../fonts/fontawesome-webfont.woff2?v=4.4.0') format('woff2'),url('../fonts/fontawesome-webfont.woff?v=4.4.0') format('woff'),url('../fonts/fontawesome-webfont.ttf?v=4.4.0') format('truetype'),url('../fonts/fontawesome-webfont.svg?v=4.4.0#fontawesomeregular') format('svg');font-weight:normal;font-style:normal}.fa{display:inline-block;font:normal normal normal 14px/1 FontAwesome;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.fa-lg{font-size:1.33333333em;line-height:.75em;vertical-align:-15%}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-fw{width:1.28571429em;text-align:center}.fa-ul{padding-left:0;margin-left:2.14285714em;list-style-type:none}.fa-ul>li{position:relative}.fa-li{position:absolute;left:-2.14285714em;width:2.14285714em;top:.14285714em;text-align:center}.fa-li.fa-lg{left:-1.85714286em}.fa-border{padding:.2em .25em .15em;border:solid .08em #eee;border-radius:.1em}.fa-pull-left{float:left}.fa-pull-right{float:right}.fa.fa-pull-left{margin-right:.3em}.fa.fa-pull-right{margin-left:.3em}.pull-right{float:right}.pull-left{float:left}.fa.pull-left{margin-right:.3em}.fa.pull-right{margin-left:.3em}.fa-spin{-webkit-animation:fa-spin 2s infinite linear;animation:fa-spin 2s infinite linear}.fa-pulse{-webkit-animation:fa-spin 1s infinite steps(8);animation:fa-spin 1s infinite steps(8)}@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}.fa-rotate-90{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=1);-webkit-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=2);-webkit-transform:rotate(180deg);-ms-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=3);-webkit-transform:rotate(270deg);-ms-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1);-webkit-transform:scale(-1, 1);-ms-transform:scale(-1, 1);transform:scale(-1, 1)}.fa-flip-vertical{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1);-webkit-transform:scale(1, -1);-ms-transform:scale(1, -1);transform:scale(1, -1)}:root .fa-rotate-90,:root .fa-rotate-180,:root .fa-rotate-270,:root .fa-flip-horizontal,:root .fa-flip-vertical{filter:none}.fa-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:middle}.fa-stack-1x,.fa-stack-2x{position:absolute;left:0;width:100%;text-align:center}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-glass:before{content:"\f000"}.fa-music:before{content:"\f001"}.fa-search:before{content:"\f002"}.fa-envelope-o:before{content:"\f003"}.fa-heart:before{content:"\f004"}.fa-star:before{content:"\f005"}.fa-star-o:before{content:"\f006"}.fa-user:before{content:"\f007"}.fa-film:before{content:"\f008"}.fa-th-large:before{content:"\f009"}.fa-th:before{content:"\f00a"}.fa-th-list:before{content:"\f00b"}.fa-check:before{content:"\f00c"}.fa-remove:before,.fa-close:before,.fa-times:before{content:"\f00d"}.fa-search-plus:before{content:"\f00e"}.fa-search-minus:before{content:"\f010"}.fa-power-off:before{content:"\f011"}.fa-signal:before{content:"\f012"}.fa-gear:before,.fa-cog:before{content:"\f013"}.fa-trash-o:before{content:"\f014"}.fa-home:before{content:"\f015"}.fa-file-o:before{content:"\f016"}.fa-clock-o:before{content:"\f017"}.fa-road:before{content:"\f018"}.fa-download:before{content:"\f019"}.fa-arrow-circle-o-down:before{content:"\f01a"}.fa-arrow-circle-o-up:before{content:"\f01b"}.fa-inbox:before{content:"\f01c"}.fa-play-circle-o:before{content:"\f01d"}.fa-rotate-right:before,.fa-repeat:before{content:"\f01e"}.fa-refresh:before{content:"\f021"}.fa-list-alt:before{content:"\f022"}.fa-lock:before{content:"\f023"}.fa-flag:before{content:"\f024"}.fa-headphones:before{content:"\f025"}.fa-volume-off:before{content:"\f026"}.fa-volume-down:before{content:"\f027"}.fa-volume-up:before{content:"\f028"}.fa-qrcode:before{content:"\f029"}.fa-barcode:before{content:"\f02a"}.fa-tag:before{content:"\f02b"}.fa-tags:before{content:"\f02c"}.fa-book:before{content:"\f02d"}.fa-bookmark:before{content:"\f02e"}.fa-print:before{content:"\f02f"}.fa-camera:before{content:"\f030"}.fa-font:before{content:"\f031"}.fa-bold:before{content:"\f032"}.fa-italic:before{content:"\f033"}.fa-text-height:before{content:"\f034"}.fa-text-width:before{content:"\f035"}.fa-align-left:before{content:"\f036"}.fa-align-center:before{content:"\f037"}.fa-align-right:before{content:"\f038"}.fa-align-justify:before{content:"\f039"}.fa-list:before{content:"\f03a"}.fa-dedent:before,.fa-outdent:before{content:"\f03b"}.fa-indent:before{content:"\f03c"}.fa-video-camera:before{content:"\f03d"}.fa-photo:before,.fa-image:before,.fa-picture-o:before{content:"\f03e"}.fa-pencil:before{content:"\f040"}.fa-map-marker:before{content:"\f041"}.fa-adjust:before{content:"\f042"}.fa-tint:before{content:"\f043"}.fa-edit:before,.fa-pencil-square-o:before{content:"\f044"}.fa-share-square-o:before{content:"\f045"}.fa-check-square-o:before{content:"\f046"}.fa-arrows:before{content:"\f047"}.fa-step-backward:before{content:"\f048"}.fa-fast-backward:before{content:"\f049"}.fa-backward:before{content:"\f04a"}.fa-play:before{content:"\f04b"}.fa-pause:before{content:"\f04c"}.fa-stop:before{content:"\f04d"}.fa-forward:before{content:"\f04e"}.fa-fast-forward:before{content:"\f050"}.fa-step-forward:before{content:"\f051"}.fa-eject:before{content:"\f052"}.fa-chevron-left:before{content:"\f053"}.fa-chevron-right:before{content:"\f054"}.fa-plus-circle:before{content:"\f055"}.fa-minus-circle:before{content:"\f056"}.fa-times-circle:before{content:"\f057"}.fa-check-circle:before{content:"\f058"}.fa-question-circle:before{content:"\f059"}.fa-info-circle:before{content:"\f05a"}.fa-crosshairs:before{content:"\f05b"}.fa-times-circle-o:before{content:"\f05c"}.fa-check-circle-o:before{content:"\f05d"}.fa-ban:before{content:"\f05e"}.fa-arrow-left:before{content:"\f060"}.fa-arrow-right:before{content:"\f061"}.fa-arrow-up:before{content:"\f062"}.fa-arrow-down:before{content:"\f063"}.fa-mail-forward:before,.fa-share:before{content:"\f064"}.fa-expand:before{content:"\f065"}.fa-compress:before{content:"\f066"}.fa-plus:before{content:"\f067"}.fa-minus:before{content:"\f068"}.fa-asterisk:before{content:"\f069"}.fa-exclamation-circle:before{content:"\f06a"}.fa-gift:before{content:"\f06b"}.fa-leaf:before{content:"\f06c"}.fa-fire:before{content:"\f06d"}.fa-eye:before{content:"\f06e"}.fa-eye-slash:before{content:"\f070"}.fa-warning:before,.fa-exclamation-triangle:before{content:"\f071"}.fa-plane:before{content:"\f072"}.fa-calendar:before{content:"\f073"}.fa-random:before{content:"\f074"}.fa-comment:before{content:"\f075"}.fa-magnet:before{content:"\f076"}.fa-chevron-up:before{content:"\f077"}.fa-chevron-down:before{content:"\f078"}.fa-retweet:before{content:"\f079"}.fa-shopping-cart:before{content:"\f07a"}.fa-folder:before{content:"\f07b"}.fa-folder-open:before{content:"\f07c"}.fa-arrows-v:before{content:"\f07d"}.fa-arrows-h:before{content:"\f07e"}.fa-bar-chart-o:before,.fa-bar-chart:before{content:"\f080"}.fa-twitter-square:before{content:"\f081"}.fa-facebook-square:before{content:"\f082"}.fa-camera-retro:before{content:"\f083"}.fa-key:before{content:"\f084"}.fa-gears:before,.fa-cogs:before{content:"\f085"}.fa-comments:before{content:"\f086"}.fa-thumbs-o-up:before{content:"\f087"}.fa-thumbs-o-down:before{content:"\f088"}.fa-star-half:before{content:"\f089"}.fa-heart-o:before{content:"\f08a"}.fa-sign-out:before{content:"\f08b"}.fa-linkedin-square:before{content:"\f08c"}.fa-thumb-tack:before{content:"\f08d"}.fa-external-link:before{content:"\f08e"}.fa-sign-in:before{content:"\f090"}.fa-trophy:before{content:"\f091"}.fa-github-square:before{content:"\f092"}.fa-upload:before{content:"\f093"}.fa-lemon-o:before{content:"\f094"}.fa-phone:before{content:"\f095"}.fa-square-o:before{content:"\f096"}.fa-bookmark-o:before{content:"\f097"}.fa-phone-square:before{content:"\f098"}.fa-twitter:before{content:"\f099"}.fa-facebook-f:before,.fa-facebook:before{content:"\f09a"}.fa-github:before{content:"\f09b"}.fa-unlock:before{content:"\f09c"}.fa-credit-card:before{content:"\f09d"}.fa-feed:before,.fa-rss:before{content:"\f09e"}.fa-hdd-o:before{content:"\f0a0"}.fa-bullhorn:before{content:"\f0a1"}.fa-bell:before{content:"\f0f3"}.fa-certificate:before{content:"\f0a3"}.fa-hand-o-right:before{content:"\f0a4"}.fa-hand-o-left:before{content:"\f0a5"}.fa-hand-o-up:before{content:"\f0a6"}.fa-hand-o-down:before{content:"\f0a7"}.fa-arrow-circle-left:before{content:"\f0a8"}.fa-arrow-circle-right:before{content:"\f0a9"}.fa-arrow-circle-up:before{content:"\f0aa"}.fa-arrow-circle-down:before{content:"\f0ab"}.fa-globe:before{content:"\f0ac"}.fa-wrench:before{content:"\f0ad"}.fa-tasks:before{content:"\f0ae"}.fa-filter:before{content:"\f0b0"}.fa-briefcase:before{content:"\f0b1"}.fa-arrows-alt:before{content:"\f0b2"}.fa-group:before,.fa-users:before{content:"\f0c0"}.fa-chain:before,.fa-link:before{content:"\f0c1"}.fa-cloud:before{content:"\f0c2"}.fa-flask:before{content:"\f0c3"}.fa-cut:before,.fa-scissors:before{content:"\f0c4"}.fa-copy:before,.fa-files-o:before{content:"\f0c5"}.fa-paperclip:before{content:"\f0c6"}.fa-save:before,.fa-floppy-o:before{content:"\f0c7"}.fa-square:before{content:"\f0c8"}.fa-navicon:before,.fa-reorder:before,.fa-bars:before{content:"\f0c9"}.fa-list-ul:before{content:"\f0ca"}.fa-list-ol:before{content:"\f0cb"}.fa-strikethrough:before{content:"\f0cc"}.fa-underline:before{content:"\f0cd"}.fa-table:before{content:"\f0ce"}.fa-magic:before{content:"\f0d0"}.fa-truck:before{content:"\f0d1"}.fa-pinterest:before{content:"\f0d2"}.fa-pinterest-square:before{content:"\f0d3"}.fa-google-plus-square:before{content:"\f0d4"}.fa-google-plus:before{content:"\f0d5"}.fa-money:before{content:"\f0d6"}.fa-caret-down:before{content:"\f0d7"}.fa-caret-up:before{content:"\f0d8"}.fa-caret-left:before{content:"\f0d9"}.fa-caret-right:before{content:"\f0da"}.fa-columns:before{content:"\f0db"}.fa-unsorted:before,.fa-sort:before{content:"\f0dc"}.fa-sort-down:before,.fa-sort-desc:before{content:"\f0dd"}.fa-sort-up:before,.fa-sort-asc:before{content:"\f0de"}.fa-envelope:before{content:"\f0e0"}.fa-linkedin:before{content:"\f0e1"}.fa-rotate-left:before,.fa-undo:before{content:"\f0e2"}.fa-legal:before,.fa-gavel:before{content:"\f0e3"}.fa-dashboard:before,.fa-tachometer:before{content:"\f0e4"}.fa-comment-o:before{content:"\f0e5"}.fa-comments-o:before{content:"\f0e6"}.fa-flash:before,.fa-bolt:before{content:"\f0e7"}.fa-sitemap:before{content:"\f0e8"}.fa-umbrella:before{content:"\f0e9"}.fa-paste:before,.fa-clipboard:before{content:"\f0ea"}.fa-lightbulb-o:before{content:"\f0eb"}.fa-exchange:before{content:"\f0ec"}.fa-cloud-download:before{content:"\f0ed"}.fa-cloud-upload:before{content:"\f0ee"}.fa-user-md:before{content:"\f0f0"}.fa-stethoscope:before{content:"\f0f1"}.fa-suitcase:before{content:"\f0f2"}.fa-bell-o:before{content:"\f0a2"}.fa-coffee:before{content:"\f0f4"}.fa-cutlery:before{content:"\f0f5"}.fa-file-text-o:before{content:"\f0f6"}.fa-building-o:before{content:"\f0f7"}.fa-hospital-o:before{content:"\f0f8"}.fa-ambulance:before{content:"\f0f9"}.fa-medkit:before{content:"\f0fa"}.fa-fighter-jet:before{content:"\f0fb"}.fa-beer:before{content:"\f0fc"}.fa-h-square:before{content:"\f0fd"}.fa-plus-square:before{content:"\f0fe"}.fa-angle-double-left:before{content:"\f100"}.fa-angle-double-right:before{content:"\f101"}.fa-angle-double-up:before{content:"\f102"}.fa-angle-double-down:before{content:"\f103"}.fa-angle-left:before{content:"\f104"}.fa-angle-right:before{content:"\f105"}.fa-angle-up:before{content:"\f106"}.fa-angle-down:before{content:"\f107"}.fa-desktop:before{content:"\f108"}.fa-laptop:before{content:"\f109"}.fa-tablet:before{content:"\f10a"}.fa-mobile-phone:before,.fa-mobile:before{content:"\f10b"}.fa-circle-o:before{content:"\f10c"}.fa-quote-left:before{content:"\f10d"}.fa-quote-right:before{content:"\f10e"}.fa-spinner:before{content:"\f110"}.fa-circle:before{content:"\f111"}.fa-mail-reply:before,.fa-reply:before{content:"\f112"}.fa-github-alt:before{content:"\f113"}.fa-folder-o:before{content:"\f114"}.fa-folder-open-o:before{content:"\f115"}.fa-smile-o:before{content:"\f118"}.fa-frown-o:before{content:"\f119"}.fa-meh-o:before{content:"\f11a"}.fa-gamepad:before{content:"\f11b"}.fa-keyboard-o:before{content:"\f11c"}.fa-flag-o:before{content:"\f11d"}.fa-flag-checkered:before{content:"\f11e"}.fa-terminal:before{content:"\f120"}.fa-code:before{content:"\f121"}.fa-mail-reply-all:before,.fa-reply-all:before{content:"\f122"}.fa-star-half-empty:before,.fa-star-half-full:before,.fa-star-half-o:before{content:"\f123"}.fa-location-arrow:before{content:"\f124"}.fa-crop:before{content:"\f125"}.fa-code-fork:before{content:"\f126"}.fa-unlink:before,.fa-chain-broken:before{content:"\f127"}.fa-question:before{content:"\f128"}.fa-info:before{content:"\f129"}.fa-exclamation:before{content:"\f12a"}.fa-superscript:before{content:"\f12b"}.fa-subscript:before{content:"\f12c"}.fa-eraser:before{content:"\f12d"}.fa-puzzle-piece:before{content:"\f12e"}.fa-microphone:before{content:"\f130"}.fa-microphone-slash:before{content:"\f131"}.fa-shield:before{content:"\f132"}.fa-calendar-o:before{content:"\f133"}.fa-fire-extinguisher:before{content:"\f134"}.fa-rocket:before{content:"\f135"}.fa-maxcdn:before{content:"\f136"}.fa-chevron-circle-left:before{content:"\f137"}.fa-chevron-circle-right:before{content:"\f138"}.fa-chevron-circle-up:before{content:"\f139"}.fa-chevron-circle-down:before{content:"\f13a"}.fa-html5:before{content:"\f13b"}.fa-css3:before{content:"\f13c"}.fa-anchor:before{content:"\f13d"}.fa-unlock-alt:before{content:"\f13e"}.fa-bullseye:before{content:"\f140"}.fa-ellipsis-h:before{content:"\f141"}.fa-ellipsis-v:before{content:"\f142"}.fa-rss-square:before{content:"\f143"}.fa-play-circle:before{content:"\f144"}.fa-ticket:before{content:"\f145"}.fa-minus-square:before{content:"\f146"}.fa-minus-square-o:before{content:"\f147"}.fa-level-up:before{content:"\f148"}.fa-level-down:before{content:"\f149"}.fa-check-square:before{content:"\f14a"}.fa-pencil-square:before{content:"\f14b"}.fa-external-link-square:before{content:"\f14c"}.fa-share-square:before{content:"\f14d"}.fa-compass:before{content:"\f14e"}.fa-toggle-down:before,.fa-caret-square-o-down:before{content:"\f150"}.fa-toggle-up:before,.fa-caret-square-o-up:before{content:"\f151"}.fa-toggle-right:before,.fa-caret-square-o-right:before{content:"\f152"}.fa-euro:before,.fa-eur:before{content:"\f153"}.fa-gbp:before{content:"\f154"}.fa-dollar:before,.fa-usd:before{content:"\f155"}.fa-rupee:before,.fa-inr:before{content:"\f156"}.fa-cny:before,.fa-rmb:before,.fa-yen:before,.fa-jpy:before{content:"\f157"}.fa-ruble:before,.fa-rouble:before,.fa-rub:before{content:"\f158"}.fa-won:before,.fa-krw:before{content:"\f159"}.fa-bitcoin:before,.fa-btc:before{content:"\f15a"}.fa-file:before{content:"\f15b"}.fa-file-text:before{content:"\f15c"}.fa-sort-alpha-asc:before{content:"\f15d"}.fa-sort-alpha-desc:before{content:"\f15e"}.fa-sort-amount-asc:before{content:"\f160"}.fa-sort-amount-desc:before{content:"\f161"}.fa-sort-numeric-asc:before{content:"\f162"}.fa-sort-numeric-desc:before{content:"\f163"}.fa-thumbs-up:before{content:"\f164"}.fa-thumbs-down:before{content:"\f165"}.fa-youtube-square:before{content:"\f166"}.fa-youtube:before{content:"\f167"}.fa-xing:before{content:"\f168"}.fa-xing-square:before{content:"\f169"}.fa-youtube-play:before{content:"\f16a"}.fa-dropbox:before{content:"\f16b"}.fa-stack-overflow:before{content:"\f16c"}.fa-instagram:before{content:"\f16d"}.fa-flickr:before{content:"\f16e"}.fa-adn:before{content:"\f170"}.fa-bitbucket:before{content:"\f171"}.fa-bitbucket-square:before{content:"\f172"}.fa-tumblr:before{content:"\f173"}.fa-tumblr-square:before{content:"\f174"}.fa-long-arrow-down:before{content:"\f175"}.fa-long-arrow-up:before{content:"\f176"}.fa-long-arrow-left:before{content:"\f177"}.fa-long-arrow-right:before{content:"\f178"}.fa-apple:before{content:"\f179"}.fa-windows:before{content:"\f17a"}.fa-android:before{content:"\f17b"}.fa-linux:before{content:"\f17c"}.fa-dribbble:before{content:"\f17d"}.fa-skype:before{content:"\f17e"}.fa-foursquare:before{content:"\f180"}.fa-trello:before{content:"\f181"}.fa-female:before{content:"\f182"}.fa-male:before{content:"\f183"}.fa-gittip:before,.fa-gratipay:before{content:"\f184"}.fa-sun-o:before{content:"\f185"}.fa-moon-o:before{content:"\f186"}.fa-archive:before{content:"\f187"}.fa-bug:before{content:"\f188"}.fa-vk:before{content:"\f189"}.fa-weibo:before{content:"\f18a"}.fa-renren:before{content:"\f18b"}.fa-pagelines:before{content:"\f18c"}.fa-stack-exchange:before{content:"\f18d"}.fa-arrow-circle-o-right:before{content:"\f18e"}.fa-arrow-circle-o-left:before{content:"\f190"}.fa-toggle-left:before,.fa-caret-square-o-left:before{content:"\f191"}.fa-dot-circle-o:before{content:"\f192"}.fa-wheelchair:before{content:"\f193"}.fa-vimeo-square:before{content:"\f194"}.fa-turkish-lira:before,.fa-try:before{content:"\f195"}.fa-plus-square-o:before{content:"\f196"}.fa-space-shuttle:before{content:"\f197"}.fa-slack:before{content:"\f198"}.fa-envelope-square:before{content:"\f199"}.fa-wordpress:before{content:"\f19a"}.fa-openid:before{content:"\f19b"}.fa-institution:before,.fa-bank:before,.fa-university:before{content:"\f19c"}.fa-mortar-board:before,.fa-graduation-cap:before{content:"\f19d"}.fa-yahoo:before{content:"\f19e"}.fa-google:before{content:"\f1a0"}.fa-reddit:before{content:"\f1a1"}.fa-reddit-square:before{content:"\f1a2"}.fa-stumbleupon-circle:before{content:"\f1a3"}.fa-stumbleupon:before{content:"\f1a4"}.fa-delicious:before{content:"\f1a5"}.fa-digg:before{content:"\f1a6"}.fa-pied-piper:before{content:"\f1a7"}.fa-pied-piper-alt:before{content:"\f1a8"}.fa-drupal:before{content:"\f1a9"}.fa-joomla:before{content:"\f1aa"}.fa-language:before{content:"\f1ab"}.fa-fax:before{content:"\f1ac"}.fa-building:before{content:"\f1ad"}.fa-child:before{content:"\f1ae"}.fa-paw:before{content:"\f1b0"}.fa-spoon:before{content:"\f1b1"}.fa-cube:before{content:"\f1b2"}.fa-cubes:before{content:"\f1b3"}.fa-behance:before{content:"\f1b4"}.fa-behance-square:before{content:"\f1b5"}.fa-steam:before{content:"\f1b6"}.fa-steam-square:before{content:"\f1b7"}.fa-recycle:before{content:"\f1b8"}.fa-automobile:before,.fa-car:before{content:"\f1b9"}.fa-cab:before,.fa-taxi:before{content:"\f1ba"}.fa-tree:before{content:"\f1bb"}.fa-spotify:before{content:"\f1bc"}.fa-deviantart:before{content:"\f1bd"}.fa-soundcloud:before{content:"\f1be"}.fa-database:before{content:"\f1c0"}.fa-file-pdf-o:before{content:"\f1c1"}.fa-file-word-o:before{content:"\f1c2"}.fa-file-excel-o:before{content:"\f1c3"}.fa-file-powerpoint-o:before{content:"\f1c4"}.fa-file-photo-o:before,.fa-file-picture-o:before,.fa-file-image-o:before{content:"\f1c5"}.fa-file-zip-o:before,.fa-file-archive-o:before{content:"\f1c6"}.fa-file-sound-o:before,.fa-file-audio-o:before{content:"\f1c7"}.fa-file-movie-o:before,.fa-file-video-o:before{content:"\f1c8"}.fa-file-code-o:before{content:"\f1c9"}.fa-vine:before{content:"\f1ca"}.fa-codepen:before{content:"\f1cb"}.fa-jsfiddle:before{content:"\f1cc"}.fa-life-bouy:before,.fa-life-buoy:before,.fa-life-saver:before,.fa-support:before,.fa-life-ring:before{content:"\f1cd"}.fa-circle-o-notch:before{content:"\f1ce"}.fa-ra:before,.fa-rebel:before{content:"\f1d0"}.fa-ge:before,.fa-empire:before{content:"\f1d1"}.fa-git-square:before{content:"\f1d2"}.fa-git:before{content:"\f1d3"}.fa-y-combinator-square:before,.fa-yc-square:before,.fa-hacker-news:before{content:"\f1d4"}.fa-tencent-weibo:before{content:"\f1d5"}.fa-qq:before{content:"\f1d6"}.fa-wechat:before,.fa-weixin:before{content:"\f1d7"}.fa-send:before,.fa-paper-plane:before{content:"\f1d8"}.fa-send-o:before,.fa-paper-plane-o:before{content:"\f1d9"}.fa-history:before{content:"\f1da"}.fa-circle-thin:before{content:"\f1db"}.fa-header:before{content:"\f1dc"}.fa-paragraph:before{content:"\f1dd"}.fa-sliders:before{content:"\f1de"}.fa-share-alt:before{content:"\f1e0"}.fa-share-alt-square:before{content:"\f1e1"}.fa-bomb:before{content:"\f1e2"}.fa-soccer-ball-o:before,.fa-futbol-o:before{content:"\f1e3"}.fa-tty:before{content:"\f1e4"}.fa-binoculars:before{content:"\f1e5"}.fa-plug:before{content:"\f1e6"}.fa-slideshare:before{content:"\f1e7"}.fa-twitch:before{content:"\f1e8"}.fa-yelp:before{content:"\f1e9"}.fa-newspaper-o:before{content:"\f1ea"}.fa-wifi:before{content:"\f1eb"}.fa-calculator:before{content:"\f1ec"}.fa-paypal:before{content:"\f1ed"}.fa-google-wallet:before{content:"\f1ee"}.fa-cc-visa:before{content:"\f1f0"}.fa-cc-mastercard:before{content:"\f1f1"}.fa-cc-discover:before{content:"\f1f2"}.fa-cc-amex:before{content:"\f1f3"}.fa-cc-paypal:before{content:"\f1f4"}.fa-cc-stripe:before{content:"\f1f5"}.fa-bell-slash:before{content:"\f1f6"}.fa-bell-slash-o:before{content:"\f1f7"}.fa-trash:before{content:"\f1f8"}.fa-copyright:before{content:"\f1f9"}.fa-at:before{content:"\f1fa"}.fa-eyedropper:before{content:"\f1fb"}.fa-paint-brush:before{content:"\f1fc"}.fa-birthday-cake:before{content:"\f1fd"}.fa-area-chart:before{content:"\f1fe"}.fa-pie-chart:before{content:"\f200"}.fa-line-chart:before{content:"\f201"}.fa-lastfm:before{content:"\f202"}.fa-lastfm-square:before{content:"\f203"}.fa-toggle-off:before{content:"\f204"}.fa-toggle-on:before{content:"\f205"}.fa-bicycle:before{content:"\f206"}.fa-bus:before{content:"\f207"}.fa-ioxhost:before{content:"\f208"}.fa-angellist:before{content:"\f209"}.fa-cc:before{content:"\f20a"}.fa-shekel:before,.fa-sheqel:before,.fa-ils:before{content:"\f20b"}.fa-meanpath:before{content:"\f20c"}.fa-buysellads:before{content:"\f20d"}.fa-connectdevelop:before{content:"\f20e"}.fa-dashcube:before{content:"\f210"}.fa-forumbee:before{content:"\f211"}.fa-leanpub:before{content:"\f212"}.fa-sellsy:before{content:"\f213"}.fa-shirtsinbulk:before{content:"\f214"}.fa-simplybuilt:before{content:"\f215"}.fa-skyatlas:before{content:"\f216"}.fa-cart-plus:before{content:"\f217"}.fa-cart-arrow-down:before{content:"\f218"}.fa-diamond:before{content:"\f219"}.fa-ship:before{content:"\f21a"}.fa-user-secret:before{content:"\f21b"}.fa-motorcycle:before{content:"\f21c"}.fa-street-view:before{content:"\f21d"}.fa-heartbeat:before{content:"\f21e"}.fa-venus:before{content:"\f221"}.fa-mars:before{content:"\f222"}.fa-mercury:before{content:"\f223"}.fa-intersex:before,.fa-transgender:before{content:"\f224"}.fa-transgender-alt:before{content:"\f225"}.fa-venus-double:before{content:"\f226"}.fa-mars-double:before{content:"\f227"}.fa-venus-mars:before{content:"\f228"}.fa-mars-stroke:before{content:"\f229"}.fa-mars-stroke-v:before{content:"\f22a"}.fa-mars-stroke-h:before{content:"\f22b"}.fa-neuter:before{content:"\f22c"}.fa-genderless:before{content:"\f22d"}.fa-facebook-official:before{content:"\f230"}.fa-pinterest-p:before{content:"\f231"}.fa-whatsapp:before{content:"\f232"}.fa-server:before{content:"\f233"}.fa-user-plus:before{content:"\f234"}.fa-user-times:before{content:"\f235"}.fa-hotel:before,.fa-bed:before{content:"\f236"}.fa-viacoin:before{content:"\f237"}.fa-train:before{content:"\f238"}.fa-subway:before{content:"\f239"}.fa-medium:before{content:"\f23a"}.fa-yc:before,.fa-y-combinator:before{content:"\f23b"}.fa-optin-monster:before{content:"\f23c"}.fa-opencart:before{content:"\f23d"}.fa-expeditedssl:before{content:"\f23e"}.fa-battery-4:before,.fa-battery-full:before{content:"\f240"}.fa-battery-3:before,.fa-battery-three-quarters:before{content:"\f241"}.fa-battery-2:before,.fa-battery-half:before{content:"\f242"}.fa-battery-1:before,.fa-battery-quarter:before{content:"\f243"}.fa-battery-0:before,.fa-battery-empty:before{content:"\f244"}.fa-mouse-pointer:before{content:"\f245"}.fa-i-cursor:before{content:"\f246"}.fa-object-group:before{content:"\f247"}.fa-object-ungroup:before{content:"\f248"}.fa-sticky-note:before{content:"\f249"}.fa-sticky-note-o:before{content:"\f24a"}.fa-cc-jcb:before{content:"\f24b"}.fa-cc-diners-club:before{content:"\f24c"}.fa-clone:before{content:"\f24d"}.fa-balance-scale:before{content:"\f24e"}.fa-hourglass-o:before{content:"\f250"}.fa-hourglass-1:before,.fa-hourglass-start:before{content:"\f251"}.fa-hourglass-2:before,.fa-hourglass-half:before{content:"\f252"}.fa-hourglass-3:before,.fa-hourglass-end:before{content:"\f253"}.fa-hourglass:before{content:"\f254"}.fa-hand-grab-o:before,.fa-hand-rock-o:before{content:"\f255"}.fa-hand-stop-o:before,.fa-hand-paper-o:before{content:"\f256"}.fa-hand-scissors-o:before{content:"\f257"}.fa-hand-lizard-o:before{content:"\f258"}.fa-hand-spock-o:before{content:"\f259"}.fa-hand-pointer-o:before{content:"\f25a"}.fa-hand-peace-o:before{content:"\f25b"}.fa-trademark:before{content:"\f25c"}.fa-registered:before{content:"\f25d"}.fa-creative-commons:before{content:"\f25e"}.fa-gg:before{content:"\f260"}.fa-gg-circle:before{content:"\f261"}.fa-tripadvisor:before{content:"\f262"}.fa-odnoklassniki:before{content:"\f263"}.fa-odnoklassniki-square:before{content:"\f264"}.fa-get-pocket:before{content:"\f265"}.fa-wikipedia-w:before{content:"\f266"}.fa-safari:before{content:"\f267"}.fa-chrome:before{content:"\f268"}.fa-firefox:before{content:"\f269"}.fa-opera:before{content:"\f26a"}.fa-internet-explorer:before{content:"\f26b"}.fa-tv:before,.fa-television:before{content:"\f26c"}.fa-contao:before{content:"\f26d"}.fa-500px:before{content:"\f26e"}.fa-amazon:before{content:"\f270"}.fa-calendar-plus-o:before{content:"\f271"}.fa-calendar-minus-o:before{content:"\f272"}.fa-calendar-times-o:before{content:"\f273"}.fa-calendar-check-o:before{content:"\f274"}.fa-industry:before{content:"\f275"}.fa-map-pin:before{content:"\f276"}.fa-map-signs:before{content:"\f277"}.fa-map-o:before{content:"\f278"}.fa-map:before{content:"\f279"}.fa-commenting:before{content:"\f27a"}.fa-commenting-o:before{content:"\f27b"}.fa-houzz:before{content:"\f27c"}.fa-vimeo:before{content:"\f27d"}.fa-black-tie:before{content:"\f27e"}.fa-fonticons:before{content:"\f280"} + */ +@font-face { + font-family: "FontAwesome"; + src: url("../fonts/fontawesome-webfont.eot?v=4.4.0"); + src: url("../fonts/fontawesome-webfont.eot?#iefix&v=4.4.0") + format("embedded-opentype"), + url("../fonts/fontawesome-webfont.woff2?v=4.4.0") format("woff2"), + url("../fonts/fontawesome-webfont.woff?v=4.4.0") format("woff"), + url("../fonts/fontawesome-webfont.ttf?v=4.4.0") format("truetype"), + url("../fonts/fontawesome-webfont.svg?v=4.4.0#fontawesomeregular") + format("svg"); + font-weight: normal; + font-style: normal; +} +.fa { + display: inline-block; + font: normal normal normal 14px/1 FontAwesome; + font-size: inherit; + text-rendering: auto; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} +.fa-lg { + font-size: 1.33333333em; + line-height: 0.75em; + vertical-align: -15%; +} +.fa-2x { + font-size: 2em; +} +.fa-3x { + font-size: 3em; +} +.fa-4x { + font-size: 4em; +} +.fa-5x { + font-size: 5em; +} +.fa-fw { + width: 1.28571429em; + text-align: center; +} +.fa-ul { + padding-left: 0; + margin-left: 2.14285714em; + list-style-type: none; +} +.fa-ul > li { + position: relative; +} +.fa-li { + position: absolute; + left: -2.14285714em; + width: 2.14285714em; + top: 0.14285714em; + text-align: center; +} +.fa-li.fa-lg { + left: -1.85714286em; +} +.fa-border { + padding: 0.2em 0.25em 0.15em; + border: solid 0.08em #eee; + border-radius: 0.1em; +} +.fa-pull-left { + float: left; +} +.fa-pull-right { + float: right; +} +.fa.fa-pull-left { + margin-right: 0.3em; +} +.fa.fa-pull-right { + margin-left: 0.3em; +} +.pull-right { + float: right; +} +.pull-left { + float: left; +} +.fa.pull-left { + margin-right: 0.3em; +} +.fa.pull-right { + margin-left: 0.3em; +} +.fa-spin { + -webkit-animation: fa-spin 2s infinite linear; + animation: fa-spin 2s infinite linear; +} +.fa-pulse { + -webkit-animation: fa-spin 1s infinite steps(8); + animation: fa-spin 1s infinite steps(8); +} +@-webkit-keyframes fa-spin { + 0% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + } + 100% { + -webkit-transform: rotate(359deg); + transform: rotate(359deg); + } +} +@keyframes fa-spin { + 0% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + } + 100% { + -webkit-transform: rotate(359deg); + transform: rotate(359deg); + } +} +.fa-rotate-90 { + filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=1); + -webkit-transform: rotate(90deg); + -ms-transform: rotate(90deg); + transform: rotate(90deg); +} +.fa-rotate-180 { + filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=2); + -webkit-transform: rotate(180deg); + -ms-transform: rotate(180deg); + transform: rotate(180deg); +} +.fa-rotate-270 { + filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=3); + -webkit-transform: rotate(270deg); + -ms-transform: rotate(270deg); + transform: rotate(270deg); +} +.fa-flip-horizontal { + filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1); + -webkit-transform: scale(-1, 1); + -ms-transform: scale(-1, 1); + transform: scale(-1, 1); +} +.fa-flip-vertical { + filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1); + -webkit-transform: scale(1, -1); + -ms-transform: scale(1, -1); + transform: scale(1, -1); +} +:root .fa-rotate-90, +:root .fa-rotate-180, +:root .fa-rotate-270, +:root .fa-flip-horizontal, +:root .fa-flip-vertical { + filter: none; +} +.fa-stack { + position: relative; + display: inline-block; + width: 2em; + height: 2em; + line-height: 2em; + vertical-align: middle; +} +.fa-stack-1x, +.fa-stack-2x { + position: absolute; + left: 0; + width: 100%; + text-align: center; +} +.fa-stack-1x { + line-height: inherit; +} +.fa-stack-2x { + font-size: 2em; +} +.fa-inverse { + color: #fff; +} +.fa-glass:before { + content: "\f000"; +} +.fa-music:before { + content: "\f001"; +} +.fa-search:before { + content: "\f002"; +} +.fa-envelope-o:before { + content: "\f003"; +} +.fa-heart:before { + content: "\f004"; +} +.fa-star:before { + content: "\f005"; +} +.fa-star-o:before { + content: "\f006"; +} +.fa-user:before { + content: "\f007"; +} +.fa-film:before { + content: "\f008"; +} +.fa-th-large:before { + content: "\f009"; +} +.fa-th:before { + content: "\f00a"; +} +.fa-th-list:before { + content: "\f00b"; +} +.fa-check:before { + content: "\f00c"; +} +.fa-remove:before, +.fa-close:before, +.fa-times:before { + content: "\f00d"; +} +.fa-search-plus:before { + content: "\f00e"; +} +.fa-search-minus:before { + content: "\f010"; +} +.fa-power-off:before { + content: "\f011"; +} +.fa-signal:before { + content: "\f012"; +} +.fa-gear:before, +.fa-cog:before { + content: "\f013"; +} +.fa-trash-o:before { + content: "\f014"; +} +.fa-home:before { + content: "\f015"; +} +.fa-file-o:before { + content: "\f016"; +} +.fa-clock-o:before { + content: "\f017"; +} +.fa-road:before { + content: "\f018"; +} +.fa-download:before { + content: "\f019"; +} +.fa-arrow-circle-o-down:before { + content: "\f01a"; +} +.fa-arrow-circle-o-up:before { + content: "\f01b"; +} +.fa-inbox:before { + content: "\f01c"; +} +.fa-play-circle-o:before { + content: "\f01d"; +} +.fa-rotate-right:before, +.fa-repeat:before { + content: "\f01e"; +} +.fa-refresh:before { + content: "\f021"; +} +.fa-list-alt:before { + content: "\f022"; +} +.fa-lock:before { + content: "\f023"; +} +.fa-flag:before { + content: "\f024"; +} +.fa-headphones:before { + content: "\f025"; +} +.fa-volume-off:before { + content: "\f026"; +} +.fa-volume-down:before { + content: "\f027"; +} +.fa-volume-up:before { + content: "\f028"; +} +.fa-qrcode:before { + content: "\f029"; +} +.fa-barcode:before { + content: "\f02a"; +} +.fa-tag:before { + content: "\f02b"; +} +.fa-tags:before { + content: "\f02c"; +} +.fa-book:before { + content: "\f02d"; +} +.fa-bookmark:before { + content: "\f02e"; +} +.fa-print:before { + content: "\f02f"; +} +.fa-camera:before { + content: "\f030"; +} +.fa-font:before { + content: "\f031"; +} +.fa-bold:before { + content: "\f032"; +} +.fa-italic:before { + content: "\f033"; +} +.fa-text-height:before { + content: "\f034"; +} +.fa-text-width:before { + content: "\f035"; +} +.fa-align-left:before { + content: "\f036"; +} +.fa-align-center:before { + content: "\f037"; +} +.fa-align-right:before { + content: "\f038"; +} +.fa-align-justify:before { + content: "\f039"; +} +.fa-list:before { + content: "\f03a"; +} +.fa-dedent:before, +.fa-outdent:before { + content: "\f03b"; +} +.fa-indent:before { + content: "\f03c"; +} +.fa-video-camera:before { + content: "\f03d"; +} +.fa-photo:before, +.fa-image:before, +.fa-picture-o:before { + content: "\f03e"; +} +.fa-pencil:before { + content: "\f040"; +} +.fa-map-marker:before { + content: "\f041"; +} +.fa-adjust:before { + content: "\f042"; +} +.fa-tint:before { + content: "\f043"; +} +.fa-edit:before, +.fa-pencil-square-o:before { + content: "\f044"; +} +.fa-share-square-o:before { + content: "\f045"; +} +.fa-check-square-o:before { + content: "\f046"; +} +.fa-arrows:before { + content: "\f047"; +} +.fa-step-backward:before { + content: "\f048"; +} +.fa-fast-backward:before { + content: "\f049"; +} +.fa-backward:before { + content: "\f04a"; +} +.fa-play:before { + content: "\f04b"; +} +.fa-pause:before { + content: "\f04c"; +} +.fa-stop:before { + content: "\f04d"; +} +.fa-forward:before { + content: "\f04e"; +} +.fa-fast-forward:before { + content: "\f050"; +} +.fa-step-forward:before { + content: "\f051"; +} +.fa-eject:before { + content: "\f052"; +} +.fa-chevron-left:before { + content: "\f053"; +} +.fa-chevron-right:before { + content: "\f054"; +} +.fa-plus-circle:before { + content: "\f055"; +} +.fa-minus-circle:before { + content: "\f056"; +} +.fa-times-circle:before { + content: "\f057"; +} +.fa-check-circle:before { + content: "\f058"; +} +.fa-question-circle:before { + content: "\f059"; +} +.fa-info-circle:before { + content: "\f05a"; +} +.fa-crosshairs:before { + content: "\f05b"; +} +.fa-times-circle-o:before { + content: "\f05c"; +} +.fa-check-circle-o:before { + content: "\f05d"; +} +.fa-ban:before { + content: "\f05e"; +} +.fa-arrow-left:before { + content: "\f060"; +} +.fa-arrow-right:before { + content: "\f061"; +} +.fa-arrow-up:before { + content: "\f062"; +} +.fa-arrow-down:before { + content: "\f063"; +} +.fa-mail-forward:before, +.fa-share:before { + content: "\f064"; +} +.fa-expand:before { + content: "\f065"; +} +.fa-compress:before { + content: "\f066"; +} +.fa-plus:before { + content: "\f067"; +} +.fa-minus:before { + content: "\f068"; +} +.fa-asterisk:before { + content: "\f069"; +} +.fa-exclamation-circle:before { + content: "\f06a"; +} +.fa-gift:before { + content: "\f06b"; +} +.fa-leaf:before { + content: "\f06c"; +} +.fa-fire:before { + content: "\f06d"; +} +.fa-eye:before { + content: "\f06e"; +} +.fa-eye-slash:before { + content: "\f070"; +} +.fa-warning:before, +.fa-exclamation-triangle:before { + content: "\f071"; +} +.fa-plane:before { + content: "\f072"; +} +.fa-calendar:before { + content: "\f073"; +} +.fa-random:before { + content: "\f074"; +} +.fa-comment:before { + content: "\f075"; +} +.fa-magnet:before { + content: "\f076"; +} +.fa-chevron-up:before { + content: "\f077"; +} +.fa-chevron-down:before { + content: "\f078"; +} +.fa-retweet:before { + content: "\f079"; +} +.fa-shopping-cart:before { + content: "\f07a"; +} +.fa-folder:before { + content: "\f07b"; +} +.fa-folder-open:before { + content: "\f07c"; +} +.fa-arrows-v:before { + content: "\f07d"; +} +.fa-arrows-h:before { + content: "\f07e"; +} +.fa-bar-chart-o:before, +.fa-bar-chart:before { + content: "\f080"; +} +.fa-twitter-square:before { + content: "\f081"; +} +.fa-facebook-square:before { + content: "\f082"; +} +.fa-camera-retro:before { + content: "\f083"; +} +.fa-key:before { + content: "\f084"; +} +.fa-gears:before, +.fa-cogs:before { + content: "\f085"; +} +.fa-comments:before { + content: "\f086"; +} +.fa-thumbs-o-up:before { + content: "\f087"; +} +.fa-thumbs-o-down:before { + content: "\f088"; +} +.fa-star-half:before { + content: "\f089"; +} +.fa-heart-o:before { + content: "\f08a"; +} +.fa-sign-out:before { + content: "\f08b"; +} +.fa-linkedin-square:before { + content: "\f08c"; +} +.fa-thumb-tack:before { + content: "\f08d"; +} +.fa-external-link:before { + content: "\f08e"; +} +.fa-sign-in:before { + content: "\f090"; +} +.fa-trophy:before { + content: "\f091"; +} +.fa-github-square:before { + content: "\f092"; +} +.fa-upload:before { + content: "\f093"; +} +.fa-lemon-o:before { + content: "\f094"; +} +.fa-phone:before { + content: "\f095"; +} +.fa-square-o:before { + content: "\f096"; +} +.fa-bookmark-o:before { + content: "\f097"; +} +.fa-phone-square:before { + content: "\f098"; +} +.fa-twitter:before { + content: "\f099"; +} +.fa-facebook-f:before, +.fa-facebook:before { + content: "\f09a"; +} +.fa-github:before { + content: "\f09b"; +} +.fa-unlock:before { + content: "\f09c"; +} +.fa-credit-card:before { + content: "\f09d"; +} +.fa-feed:before, +.fa-rss:before { + content: "\f09e"; +} +.fa-hdd-o:before { + content: "\f0a0"; +} +.fa-bullhorn:before { + content: "\f0a1"; +} +.fa-bell:before { + content: "\f0f3"; +} +.fa-certificate:before { + content: "\f0a3"; +} +.fa-hand-o-right:before { + content: "\f0a4"; +} +.fa-hand-o-left:before { + content: "\f0a5"; +} +.fa-hand-o-up:before { + content: "\f0a6"; +} +.fa-hand-o-down:before { + content: "\f0a7"; +} +.fa-arrow-circle-left:before { + content: "\f0a8"; +} +.fa-arrow-circle-right:before { + content: "\f0a9"; +} +.fa-arrow-circle-up:before { + content: "\f0aa"; +} +.fa-arrow-circle-down:before { + content: "\f0ab"; +} +.fa-globe:before { + content: "\f0ac"; +} +.fa-wrench:before { + content: "\f0ad"; +} +.fa-tasks:before { + content: "\f0ae"; +} +.fa-filter:before { + content: "\f0b0"; +} +.fa-briefcase:before { + content: "\f0b1"; +} +.fa-arrows-alt:before { + content: "\f0b2"; +} +.fa-group:before, +.fa-users:before { + content: "\f0c0"; +} +.fa-chain:before, +.fa-link:before { + content: "\f0c1"; +} +.fa-cloud:before { + content: "\f0c2"; +} +.fa-flask:before { + content: "\f0c3"; +} +.fa-cut:before, +.fa-scissors:before { + content: "\f0c4"; +} +.fa-copy:before, +.fa-files-o:before { + content: "\f0c5"; +} +.fa-paperclip:before { + content: "\f0c6"; +} +.fa-save:before, +.fa-floppy-o:before { + content: "\f0c7"; +} +.fa-square:before { + content: "\f0c8"; +} +.fa-navicon:before, +.fa-reorder:before, +.fa-bars:before { + content: "\f0c9"; +} +.fa-list-ul:before { + content: "\f0ca"; +} +.fa-list-ol:before { + content: "\f0cb"; +} +.fa-strikethrough:before { + content: "\f0cc"; +} +.fa-underline:before { + content: "\f0cd"; +} +.fa-table:before { + content: "\f0ce"; +} +.fa-magic:before { + content: "\f0d0"; +} +.fa-truck:before { + content: "\f0d1"; +} +.fa-pinterest:before { + content: "\f0d2"; +} +.fa-pinterest-square:before { + content: "\f0d3"; +} +.fa-google-plus-square:before { + content: "\f0d4"; +} +.fa-google-plus:before { + content: "\f0d5"; +} +.fa-money:before { + content: "\f0d6"; +} +.fa-caret-down:before { + content: "\f0d7"; +} +.fa-caret-up:before { + content: "\f0d8"; +} +.fa-caret-left:before { + content: "\f0d9"; +} +.fa-caret-right:before { + content: "\f0da"; +} +.fa-columns:before { + content: "\f0db"; +} +.fa-unsorted:before, +.fa-sort:before { + content: "\f0dc"; +} +.fa-sort-down:before, +.fa-sort-desc:before { + content: "\f0dd"; +} +.fa-sort-up:before, +.fa-sort-asc:before { + content: "\f0de"; +} +.fa-envelope:before { + content: "\f0e0"; +} +.fa-linkedin:before { + content: "\f0e1"; +} +.fa-rotate-left:before, +.fa-undo:before { + content: "\f0e2"; +} +.fa-legal:before, +.fa-gavel:before { + content: "\f0e3"; +} +.fa-dashboard:before, +.fa-tachometer:before { + content: "\f0e4"; +} +.fa-comment-o:before { + content: "\f0e5"; +} +.fa-comments-o:before { + content: "\f0e6"; +} +.fa-flash:before, +.fa-bolt:before { + content: "\f0e7"; +} +.fa-sitemap:before { + content: "\f0e8"; +} +.fa-umbrella:before { + content: "\f0e9"; +} +.fa-paste:before, +.fa-clipboard:before { + content: "\f0ea"; +} +.fa-lightbulb-o:before { + content: "\f0eb"; +} +.fa-exchange:before { + content: "\f0ec"; +} +.fa-cloud-download:before { + content: "\f0ed"; +} +.fa-cloud-upload:before { + content: "\f0ee"; +} +.fa-user-md:before { + content: "\f0f0"; +} +.fa-stethoscope:before { + content: "\f0f1"; +} +.fa-suitcase:before { + content: "\f0f2"; +} +.fa-bell-o:before { + content: "\f0a2"; +} +.fa-coffee:before { + content: "\f0f4"; +} +.fa-cutlery:before { + content: "\f0f5"; +} +.fa-file-text-o:before { + content: "\f0f6"; +} +.fa-building-o:before { + content: "\f0f7"; +} +.fa-hospital-o:before { + content: "\f0f8"; +} +.fa-ambulance:before { + content: "\f0f9"; +} +.fa-medkit:before { + content: "\f0fa"; +} +.fa-fighter-jet:before { + content: "\f0fb"; +} +.fa-beer:before { + content: "\f0fc"; +} +.fa-h-square:before { + content: "\f0fd"; +} +.fa-plus-square:before { + content: "\f0fe"; +} +.fa-angle-double-left:before { + content: "\f100"; +} +.fa-angle-double-right:before { + content: "\f101"; +} +.fa-angle-double-up:before { + content: "\f102"; +} +.fa-angle-double-down:before { + content: "\f103"; +} +.fa-angle-left:before { + content: "\f104"; +} +.fa-angle-right:before { + content: "\f105"; +} +.fa-angle-up:before { + content: "\f106"; +} +.fa-angle-down:before { + content: "\f107"; +} +.fa-desktop:before { + content: "\f108"; +} +.fa-laptop:before { + content: "\f109"; +} +.fa-tablet:before { + content: "\f10a"; +} +.fa-mobile-phone:before, +.fa-mobile:before { + content: "\f10b"; +} +.fa-circle-o:before { + content: "\f10c"; +} +.fa-quote-left:before { + content: "\f10d"; +} +.fa-quote-right:before { + content: "\f10e"; +} +.fa-spinner:before { + content: "\f110"; +} +.fa-circle:before { + content: "\f111"; +} +.fa-mail-reply:before, +.fa-reply:before { + content: "\f112"; +} +.fa-github-alt:before { + content: "\f113"; +} +.fa-folder-o:before { + content: "\f114"; +} +.fa-folder-open-o:before { + content: "\f115"; +} +.fa-smile-o:before { + content: "\f118"; +} +.fa-frown-o:before { + content: "\f119"; +} +.fa-meh-o:before { + content: "\f11a"; +} +.fa-gamepad:before { + content: "\f11b"; +} +.fa-keyboard-o:before { + content: "\f11c"; +} +.fa-flag-o:before { + content: "\f11d"; +} +.fa-flag-checkered:before { + content: "\f11e"; +} +.fa-terminal:before { + content: "\f120"; +} +.fa-code:before { + content: "\f121"; +} +.fa-mail-reply-all:before, +.fa-reply-all:before { + content: "\f122"; +} +.fa-star-half-empty:before, +.fa-star-half-full:before, +.fa-star-half-o:before { + content: "\f123"; +} +.fa-location-arrow:before { + content: "\f124"; +} +.fa-crop:before { + content: "\f125"; +} +.fa-code-fork:before { + content: "\f126"; +} +.fa-unlink:before, +.fa-chain-broken:before { + content: "\f127"; +} +.fa-question:before { + content: "\f128"; +} +.fa-info:before { + content: "\f129"; +} +.fa-exclamation:before { + content: "\f12a"; +} +.fa-superscript:before { + content: "\f12b"; +} +.fa-subscript:before { + content: "\f12c"; +} +.fa-eraser:before { + content: "\f12d"; +} +.fa-puzzle-piece:before { + content: "\f12e"; +} +.fa-microphone:before { + content: "\f130"; +} +.fa-microphone-slash:before { + content: "\f131"; +} +.fa-shield:before { + content: "\f132"; +} +.fa-calendar-o:before { + content: "\f133"; +} +.fa-fire-extinguisher:before { + content: "\f134"; +} +.fa-rocket:before { + content: "\f135"; +} +.fa-maxcdn:before { + content: "\f136"; +} +.fa-chevron-circle-left:before { + content: "\f137"; +} +.fa-chevron-circle-right:before { + content: "\f138"; +} +.fa-chevron-circle-up:before { + content: "\f139"; +} +.fa-chevron-circle-down:before { + content: "\f13a"; +} +.fa-html5:before { + content: "\f13b"; +} +.fa-css3:before { + content: "\f13c"; +} +.fa-anchor:before { + content: "\f13d"; +} +.fa-unlock-alt:before { + content: "\f13e"; +} +.fa-bullseye:before { + content: "\f140"; +} +.fa-ellipsis-h:before { + content: "\f141"; +} +.fa-ellipsis-v:before { + content: "\f142"; +} +.fa-rss-square:before { + content: "\f143"; +} +.fa-play-circle:before { + content: "\f144"; +} +.fa-ticket:before { + content: "\f145"; +} +.fa-minus-square:before { + content: "\f146"; +} +.fa-minus-square-o:before { + content: "\f147"; +} +.fa-level-up:before { + content: "\f148"; +} +.fa-level-down:before { + content: "\f149"; +} +.fa-check-square:before { + content: "\f14a"; +} +.fa-pencil-square:before { + content: "\f14b"; +} +.fa-external-link-square:before { + content: "\f14c"; +} +.fa-share-square:before { + content: "\f14d"; +} +.fa-compass:before { + content: "\f14e"; +} +.fa-toggle-down:before, +.fa-caret-square-o-down:before { + content: "\f150"; +} +.fa-toggle-up:before, +.fa-caret-square-o-up:before { + content: "\f151"; +} +.fa-toggle-right:before, +.fa-caret-square-o-right:before { + content: "\f152"; +} +.fa-euro:before, +.fa-eur:before { + content: "\f153"; +} +.fa-gbp:before { + content: "\f154"; +} +.fa-dollar:before, +.fa-usd:before { + content: "\f155"; +} +.fa-rupee:before, +.fa-inr:before { + content: "\f156"; +} +.fa-cny:before, +.fa-rmb:before, +.fa-yen:before, +.fa-jpy:before { + content: "\f157"; +} +.fa-ruble:before, +.fa-rouble:before, +.fa-rub:before { + content: "\f158"; +} +.fa-won:before, +.fa-krw:before { + content: "\f159"; +} +.fa-bitcoin:before, +.fa-btc:before { + content: "\f15a"; +} +.fa-file:before { + content: "\f15b"; +} +.fa-file-text:before { + content: "\f15c"; +} +.fa-sort-alpha-asc:before { + content: "\f15d"; +} +.fa-sort-alpha-desc:before { + content: "\f15e"; +} +.fa-sort-amount-asc:before { + content: "\f160"; +} +.fa-sort-amount-desc:before { + content: "\f161"; +} +.fa-sort-numeric-asc:before { + content: "\f162"; +} +.fa-sort-numeric-desc:before { + content: "\f163"; +} +.fa-thumbs-up:before { + content: "\f164"; +} +.fa-thumbs-down:before { + content: "\f165"; +} +.fa-youtube-square:before { + content: "\f166"; +} +.fa-youtube:before { + content: "\f167"; +} +.fa-xing:before { + content: "\f168"; +} +.fa-xing-square:before { + content: "\f169"; +} +.fa-youtube-play:before { + content: "\f16a"; +} +.fa-dropbox:before { + content: "\f16b"; +} +.fa-stack-overflow:before { + content: "\f16c"; +} +.fa-instagram:before { + content: "\f16d"; +} +.fa-flickr:before { + content: "\f16e"; +} +.fa-adn:before { + content: "\f170"; +} +.fa-bitbucket:before { + content: "\f171"; +} +.fa-bitbucket-square:before { + content: "\f172"; +} +.fa-tumblr:before { + content: "\f173"; +} +.fa-tumblr-square:before { + content: "\f174"; +} +.fa-long-arrow-down:before { + content: "\f175"; +} +.fa-long-arrow-up:before { + content: "\f176"; +} +.fa-long-arrow-left:before { + content: "\f177"; +} +.fa-long-arrow-right:before { + content: "\f178"; +} +.fa-apple:before { + content: "\f179"; +} +.fa-windows:before { + content: "\f17a"; +} +.fa-android:before { + content: "\f17b"; +} +.fa-linux:before { + content: "\f17c"; +} +.fa-dribbble:before { + content: "\f17d"; +} +.fa-skype:before { + content: "\f17e"; +} +.fa-foursquare:before { + content: "\f180"; +} +.fa-trello:before { + content: "\f181"; +} +.fa-female:before { + content: "\f182"; +} +.fa-male:before { + content: "\f183"; +} +.fa-gittip:before, +.fa-gratipay:before { + content: "\f184"; +} +.fa-sun-o:before { + content: "\f185"; +} +.fa-moon-o:before { + content: "\f186"; +} +.fa-archive:before { + content: "\f187"; +} +.fa-bug:before { + content: "\f188"; +} +.fa-vk:before { + content: "\f189"; +} +.fa-weibo:before { + content: "\f18a"; +} +.fa-renren:before { + content: "\f18b"; +} +.fa-pagelines:before { + content: "\f18c"; +} +.fa-stack-exchange:before { + content: "\f18d"; +} +.fa-arrow-circle-o-right:before { + content: "\f18e"; +} +.fa-arrow-circle-o-left:before { + content: "\f190"; +} +.fa-toggle-left:before, +.fa-caret-square-o-left:before { + content: "\f191"; +} +.fa-dot-circle-o:before { + content: "\f192"; +} +.fa-wheelchair:before { + content: "\f193"; +} +.fa-vimeo-square:before { + content: "\f194"; +} +.fa-turkish-lira:before, +.fa-try:before { + content: "\f195"; +} +.fa-plus-square-o:before { + content: "\f196"; +} +.fa-space-shuttle:before { + content: "\f197"; +} +.fa-slack:before { + content: "\f198"; +} +.fa-envelope-square:before { + content: "\f199"; +} +.fa-wordpress:before { + content: "\f19a"; +} +.fa-openid:before { + content: "\f19b"; +} +.fa-institution:before, +.fa-bank:before, +.fa-university:before { + content: "\f19c"; +} +.fa-mortar-board:before, +.fa-graduation-cap:before { + content: "\f19d"; +} +.fa-yahoo:before { + content: "\f19e"; +} +.fa-google:before { + content: "\f1a0"; +} +.fa-reddit:before { + content: "\f1a1"; +} +.fa-reddit-square:before { + content: "\f1a2"; +} +.fa-stumbleupon-circle:before { + content: "\f1a3"; +} +.fa-stumbleupon:before { + content: "\f1a4"; +} +.fa-delicious:before { + content: "\f1a5"; +} +.fa-digg:before { + content: "\f1a6"; +} +.fa-pied-piper:before { + content: "\f1a7"; +} +.fa-pied-piper-alt:before { + content: "\f1a8"; +} +.fa-drupal:before { + content: "\f1a9"; +} +.fa-joomla:before { + content: "\f1aa"; +} +.fa-language:before { + content: "\f1ab"; +} +.fa-fax:before { + content: "\f1ac"; +} +.fa-building:before { + content: "\f1ad"; +} +.fa-child:before { + content: "\f1ae"; +} +.fa-paw:before { + content: "\f1b0"; +} +.fa-spoon:before { + content: "\f1b1"; +} +.fa-cube:before { + content: "\f1b2"; +} +.fa-cubes:before { + content: "\f1b3"; +} +.fa-behance:before { + content: "\f1b4"; +} +.fa-behance-square:before { + content: "\f1b5"; +} +.fa-steam:before { + content: "\f1b6"; +} +.fa-steam-square:before { + content: "\f1b7"; +} +.fa-recycle:before { + content: "\f1b8"; +} +.fa-automobile:before, +.fa-car:before { + content: "\f1b9"; +} +.fa-cab:before, +.fa-taxi:before { + content: "\f1ba"; +} +.fa-tree:before { + content: "\f1bb"; +} +.fa-spotify:before { + content: "\f1bc"; +} +.fa-deviantart:before { + content: "\f1bd"; +} +.fa-soundcloud:before { + content: "\f1be"; +} +.fa-database:before { + content: "\f1c0"; +} +.fa-file-pdf-o:before { + content: "\f1c1"; +} +.fa-file-word-o:before { + content: "\f1c2"; +} +.fa-file-excel-o:before { + content: "\f1c3"; +} +.fa-file-powerpoint-o:before { + content: "\f1c4"; +} +.fa-file-photo-o:before, +.fa-file-picture-o:before, +.fa-file-image-o:before { + content: "\f1c5"; +} +.fa-file-zip-o:before, +.fa-file-archive-o:before { + content: "\f1c6"; +} +.fa-file-sound-o:before, +.fa-file-audio-o:before { + content: "\f1c7"; +} +.fa-file-movie-o:before, +.fa-file-video-o:before { + content: "\f1c8"; +} +.fa-file-code-o:before { + content: "\f1c9"; +} +.fa-vine:before { + content: "\f1ca"; +} +.fa-codepen:before { + content: "\f1cb"; +} +.fa-jsfiddle:before { + content: "\f1cc"; +} +.fa-life-bouy:before, +.fa-life-buoy:before, +.fa-life-saver:before, +.fa-support:before, +.fa-life-ring:before { + content: "\f1cd"; +} +.fa-circle-o-notch:before { + content: "\f1ce"; +} +.fa-ra:before, +.fa-rebel:before { + content: "\f1d0"; +} +.fa-ge:before, +.fa-empire:before { + content: "\f1d1"; +} +.fa-git-square:before { + content: "\f1d2"; +} +.fa-git:before { + content: "\f1d3"; +} +.fa-y-combinator-square:before, +.fa-yc-square:before, +.fa-hacker-news:before { + content: "\f1d4"; +} +.fa-tencent-weibo:before { + content: "\f1d5"; +} +.fa-qq:before { + content: "\f1d6"; +} +.fa-wechat:before, +.fa-weixin:before { + content: "\f1d7"; +} +.fa-send:before, +.fa-paper-plane:before { + content: "\f1d8"; +} +.fa-send-o:before, +.fa-paper-plane-o:before { + content: "\f1d9"; +} +.fa-history:before { + content: "\f1da"; +} +.fa-circle-thin:before { + content: "\f1db"; +} +.fa-header:before { + content: "\f1dc"; +} +.fa-paragraph:before { + content: "\f1dd"; +} +.fa-sliders:before { + content: "\f1de"; +} +.fa-share-alt:before { + content: "\f1e0"; +} +.fa-share-alt-square:before { + content: "\f1e1"; +} +.fa-bomb:before { + content: "\f1e2"; +} +.fa-soccer-ball-o:before, +.fa-futbol-o:before { + content: "\f1e3"; +} +.fa-tty:before { + content: "\f1e4"; +} +.fa-binoculars:before { + content: "\f1e5"; +} +.fa-plug:before { + content: "\f1e6"; +} +.fa-slideshare:before { + content: "\f1e7"; +} +.fa-twitch:before { + content: "\f1e8"; +} +.fa-yelp:before { + content: "\f1e9"; +} +.fa-newspaper-o:before { + content: "\f1ea"; +} +.fa-wifi:before { + content: "\f1eb"; +} +.fa-calculator:before { + content: "\f1ec"; +} +.fa-paypal:before { + content: "\f1ed"; +} +.fa-google-wallet:before { + content: "\f1ee"; +} +.fa-cc-visa:before { + content: "\f1f0"; +} +.fa-cc-mastercard:before { + content: "\f1f1"; +} +.fa-cc-discover:before { + content: "\f1f2"; +} +.fa-cc-amex:before { + content: "\f1f3"; +} +.fa-cc-paypal:before { + content: "\f1f4"; +} +.fa-cc-stripe:before { + content: "\f1f5"; +} +.fa-bell-slash:before { + content: "\f1f6"; +} +.fa-bell-slash-o:before { + content: "\f1f7"; +} +.fa-trash:before { + content: "\f1f8"; +} +.fa-copyright:before { + content: "\f1f9"; +} +.fa-at:before { + content: "\f1fa"; +} +.fa-eyedropper:before { + content: "\f1fb"; +} +.fa-paint-brush:before { + content: "\f1fc"; +} +.fa-birthday-cake:before { + content: "\f1fd"; +} +.fa-area-chart:before { + content: "\f1fe"; +} +.fa-pie-chart:before { + content: "\f200"; +} +.fa-line-chart:before { + content: "\f201"; +} +.fa-lastfm:before { + content: "\f202"; +} +.fa-lastfm-square:before { + content: "\f203"; +} +.fa-toggle-off:before { + content: "\f204"; +} +.fa-toggle-on:before { + content: "\f205"; +} +.fa-bicycle:before { + content: "\f206"; +} +.fa-bus:before { + content: "\f207"; +} +.fa-ioxhost:before { + content: "\f208"; +} +.fa-angellist:before { + content: "\f209"; +} +.fa-cc:before { + content: "\f20a"; +} +.fa-shekel:before, +.fa-sheqel:before, +.fa-ils:before { + content: "\f20b"; +} +.fa-meanpath:before { + content: "\f20c"; +} +.fa-buysellads:before { + content: "\f20d"; +} +.fa-connectdevelop:before { + content: "\f20e"; +} +.fa-dashcube:before { + content: "\f210"; +} +.fa-forumbee:before { + content: "\f211"; +} +.fa-leanpub:before { + content: "\f212"; +} +.fa-sellsy:before { + content: "\f213"; +} +.fa-shirtsinbulk:before { + content: "\f214"; +} +.fa-simplybuilt:before { + content: "\f215"; +} +.fa-skyatlas:before { + content: "\f216"; +} +.fa-cart-plus:before { + content: "\f217"; +} +.fa-cart-arrow-down:before { + content: "\f218"; +} +.fa-diamond:before { + content: "\f219"; +} +.fa-ship:before { + content: "\f21a"; +} +.fa-user-secret:before { + content: "\f21b"; +} +.fa-motorcycle:before { + content: "\f21c"; +} +.fa-street-view:before { + content: "\f21d"; +} +.fa-heartbeat:before { + content: "\f21e"; +} +.fa-venus:before { + content: "\f221"; +} +.fa-mars:before { + content: "\f222"; +} +.fa-mercury:before { + content: "\f223"; +} +.fa-intersex:before, +.fa-transgender:before { + content: "\f224"; +} +.fa-transgender-alt:before { + content: "\f225"; +} +.fa-venus-double:before { + content: "\f226"; +} +.fa-mars-double:before { + content: "\f227"; +} +.fa-venus-mars:before { + content: "\f228"; +} +.fa-mars-stroke:before { + content: "\f229"; +} +.fa-mars-stroke-v:before { + content: "\f22a"; +} +.fa-mars-stroke-h:before { + content: "\f22b"; +} +.fa-neuter:before { + content: "\f22c"; +} +.fa-genderless:before { + content: "\f22d"; +} +.fa-facebook-official:before { + content: "\f230"; +} +.fa-pinterest-p:before { + content: "\f231"; +} +.fa-whatsapp:before { + content: "\f232"; +} +.fa-server:before { + content: "\f233"; +} +.fa-user-plus:before { + content: "\f234"; +} +.fa-user-times:before { + content: "\f235"; +} +.fa-hotel:before, +.fa-bed:before { + content: "\f236"; +} +.fa-viacoin:before { + content: "\f237"; +} +.fa-train:before { + content: "\f238"; +} +.fa-subway:before { + content: "\f239"; +} +.fa-medium:before { + content: "\f23a"; +} +.fa-yc:before, +.fa-y-combinator:before { + content: "\f23b"; +} +.fa-optin-monster:before { + content: "\f23c"; +} +.fa-opencart:before { + content: "\f23d"; +} +.fa-expeditedssl:before { + content: "\f23e"; +} +.fa-battery-4:before, +.fa-battery-full:before { + content: "\f240"; +} +.fa-battery-3:before, +.fa-battery-three-quarters:before { + content: "\f241"; +} +.fa-battery-2:before, +.fa-battery-half:before { + content: "\f242"; +} +.fa-battery-1:before, +.fa-battery-quarter:before { + content: "\f243"; +} +.fa-battery-0:before, +.fa-battery-empty:before { + content: "\f244"; +} +.fa-mouse-pointer:before { + content: "\f245"; +} +.fa-i-cursor:before { + content: "\f246"; +} +.fa-object-group:before { + content: "\f247"; +} +.fa-object-ungroup:before { + content: "\f248"; +} +.fa-sticky-note:before { + content: "\f249"; +} +.fa-sticky-note-o:before { + content: "\f24a"; +} +.fa-cc-jcb:before { + content: "\f24b"; +} +.fa-cc-diners-club:before { + content: "\f24c"; +} +.fa-clone:before { + content: "\f24d"; +} +.fa-balance-scale:before { + content: "\f24e"; +} +.fa-hourglass-o:before { + content: "\f250"; +} +.fa-hourglass-1:before, +.fa-hourglass-start:before { + content: "\f251"; +} +.fa-hourglass-2:before, +.fa-hourglass-half:before { + content: "\f252"; +} +.fa-hourglass-3:before, +.fa-hourglass-end:before { + content: "\f253"; +} +.fa-hourglass:before { + content: "\f254"; +} +.fa-hand-grab-o:before, +.fa-hand-rock-o:before { + content: "\f255"; +} +.fa-hand-stop-o:before, +.fa-hand-paper-o:before { + content: "\f256"; +} +.fa-hand-scissors-o:before { + content: "\f257"; +} +.fa-hand-lizard-o:before { + content: "\f258"; +} +.fa-hand-spock-o:before { + content: "\f259"; +} +.fa-hand-pointer-o:before { + content: "\f25a"; +} +.fa-hand-peace-o:before { + content: "\f25b"; +} +.fa-trademark:before { + content: "\f25c"; +} +.fa-registered:before { + content: "\f25d"; +} +.fa-creative-commons:before { + content: "\f25e"; +} +.fa-gg:before { + content: "\f260"; +} +.fa-gg-circle:before { + content: "\f261"; +} +.fa-tripadvisor:before { + content: "\f262"; +} +.fa-odnoklassniki:before { + content: "\f263"; +} +.fa-odnoklassniki-square:before { + content: "\f264"; +} +.fa-get-pocket:before { + content: "\f265"; +} +.fa-wikipedia-w:before { + content: "\f266"; +} +.fa-safari:before { + content: "\f267"; +} +.fa-chrome:before { + content: "\f268"; +} +.fa-firefox:before { + content: "\f269"; +} +.fa-opera:before { + content: "\f26a"; +} +.fa-internet-explorer:before { + content: "\f26b"; +} +.fa-tv:before, +.fa-television:before { + content: "\f26c"; +} +.fa-contao:before { + content: "\f26d"; +} +.fa-500px:before { + content: "\f26e"; +} +.fa-amazon:before { + content: "\f270"; +} +.fa-calendar-plus-o:before { + content: "\f271"; +} +.fa-calendar-minus-o:before { + content: "\f272"; +} +.fa-calendar-times-o:before { + content: "\f273"; +} +.fa-calendar-check-o:before { + content: "\f274"; +} +.fa-industry:before { + content: "\f275"; +} +.fa-map-pin:before { + content: "\f276"; +} +.fa-map-signs:before { + content: "\f277"; +} +.fa-map-o:before { + content: "\f278"; +} +.fa-map:before { + content: "\f279"; +} +.fa-commenting:before { + content: "\f27a"; +} +.fa-commenting-o:before { + content: "\f27b"; +} +.fa-houzz:before { + content: "\f27c"; +} +.fa-vimeo:before { + content: "\f27d"; +} +.fa-black-tie:before { + content: "\f27e"; +} +.fa-fonticons:before { + content: "\f280"; +} diff --git a/public/css/style.css b/public/css/style.css index c07944898..1ef4038fa 100644 --- a/public/css/style.css +++ b/public/css/style.css @@ -4,111 +4,137 @@ sassc scss/main.scss public/css/style.css */ body { - font: 14px "Open Sans", Helvetica, Arial, sans-serif; - color: #61686b; } + font: 14px 'Open Sans', Helvetica, Arial, sans-serif; + color: #61686b; +} a { - color: #5ba4e5; } + color: #5ba4e5; +} /* Simple class that makes its content's font size little bit bigger */ .text-bigger { - font-size: 16px; } + font-size: 16px; +} /* Add special class to remove default buttom space */ .no-bottom-space { - margin-bottom: 0px; } + margin-bottom: 0px; +} .large-bottom-space { - margin-bottom: 300px; } + margin-bottom: 300px; +} /* Increase space between form groups so they are more prominent */ .form-group { - margin-bottom: 20px; } + margin-bottom: 20px; +} /* Make help blocks in forms to be more distinguishable */ .form-group .help-block { - font-style: italic; } + font-style: italic; +} /* Make certain progress bars to be taller */ .progress.bigger { - height: 38px; } - .progress.bigger .progress-bar { - line-height: 38px; } + height: 38px; +} +.progress.bigger .progress-bar { + line-height: 38px; +} /* Space out content a bit */ body { padding-top: 20px; - padding-bottom: 20px; } + padding-bottom: 20px; +} label.label-plain { - font-weight: normal; } + font-weight: normal; +} /* Make breadcrumbs to be transparant */ .breadcrumb { background: none; padding-right: 0; - padding-left: 0; } + padding-left: 0; +} /* Make the masthead heading the same height as the navigation */ .header h3 { padding-bottom: 19px; margin-top: 0; margin-bottom: 0; - line-height: 40px; } + line-height: 40px; +} /* Custom page footer */ .footer { margin-top: 20px; padding-top: 20px; - border-top: 1px solid #e5e5e5; } + border-top: 1px solid #e5e5e5; +} -.header, .marketing, .footer { +.header, +.marketing, +.footer { padding-right: 0; - padding-left: 0; } + padding-left: 0; +} /* Space out the masthead */ .header { - margin-bottom: 30px; } + margin-bottom: 30px; +} .popover { - min-width: 300px; } + min-width: 300px; +} /* styling calendar*/ .calendar_month { - width: 100%; } + width: 100%; +} .calendar_month td { text-align: center; padding-top: 5px; - padding-bottom: 5px; } + padding-bottom: 5px; +} .calendar_month thead { text-align: center; - font-weight: bolder; } + font-weight: bolder; +} div.month_container { - height: 250px; } + height: 250px; +} .team-view-table { - width: 100%; } + width: 100%; +} .team-view-table td { padding-top: 5px; - padding-bottom: 5px; } + padding-bottom: 5px; +} td.team-view-header { height: 43px; - text-align: center; } + text-align: center; +} td.calendar_cell { width: 15px !important; @@ -117,7 +143,8 @@ td.calendar_cell { position: relative; text-align: center; padding-top: 5px; - padding-bottom: 5px; } + padding-bottom: 5px; +} td.calendar_cell span { position: relative; @@ -125,31 +152,38 @@ td.calendar_cell span { top: -1px; display: block; text-align: center; - z-index: 10; } + z-index: 10; +} td.current_day_cell { - background: #FFCDD2; - color: #ffffff; } + background: #ffcdd2; + color: #ffffff; +} td.weekend_cell { - background: #F5F7F8; } + background: #f5f7f8; +} td.bank_holiday_cell { - background: #31B0D5; - color: #ffffff; } + background: #31b0d5; + color: #ffffff; +} td.leave_cell { background: #9fbb58; color: #61686b; - font-weight: bolder; } + font-weight: bolder; +} td.leave_cell_pended { - background: #FFCBA4; + background: #ffcba4; color: #61686b; - font-weight: bolder; } + font-weight: bolder; +} .modal-dialog { - max-width: 450px; } + max-width: 450px; +} .left-column-cell { text-overflow: ellipsis; @@ -157,7 +191,8 @@ td.leave_cell_pended { width: 165px; white-space: nowrap; overflow: hidden; - display: inline-block; } + display: inline-block; +} .main-row_header { /* TODO refactore */ @@ -169,81 +204,103 @@ td.leave_cell_pended { line-height: 1.15em; text-align: left; padding-top: 30px; - padding-bottom: 30px; } + padding-bottom: 30px; +} /* Feeds */ .feed-calendar-big { font-size: 450px; - color: #F8F8F8; } + color: #f8f8f8; +} .feed-calendar-big-picture-holder { - text-align: center; } + text-align: center; +} p.description-paragraph { padding-top: 20px; - padding-left: 15px; } + padding-left: 15px; +} div.feeds-holder { - margin-top: 20px; } + margin-top: 20px; +} /* Calendars */ .top-leave-type-statistics { - text-align: center; } + text-align: center; +} .top-leave-type-statistics dt { font-size: 75px; color: #61686b; font-weight: 100; border-bottom: 1px solid #e5e5e5; - margin-bottom: 20px; } + margin-bottom: 20px; +} .top-leave-type-statistics dd { - font-size: 16px; } + font-size: 16px; +} .secondary-leave-type-statistics { - font-size: 16px; } + font-size: 16px; +} .secondary-leave-type-statistics dt { text-align: center; padding-bottom: 15px; margin-bottom: 15px; - border-bottom: 1px solid #e5e5e5; } + border-bottom: 1px solid #e5e5e5; +} .secondary-leave-type-statistics dd { padding-left: 10px; - padding-right: 10px; } + padding-right: 10px; +} .calendar-section-caption { text-align: center; - font-size: 1.2em; } + font-size: 1.2em; +} .setting-general-2nd-column { - padding-left: 30px; } + padding-left: 30px; +} .label.bigger { - font-size: large; } + font-size: large; +} /* Fix for issue with modal scrollings on mobiles */ @media (max-width: 768px) { body.modal-open { - position: fixed; } } + position: fixed; + } +} /* To be used for selected items in lists */ .selected-item { - background: #F5F7F8; - font-weight: bolder; } + background: #f5f7f8; + font-weight: bolder; +} .leave_type_color_1 { - background: #96c521 !important; } + background: #96c521 !important; +} .leave_type_color_2 { - background: #40C4FF !important; } + background: #40c4ff !important; +} .leave_type_color_3 { - background: #FF5722 !important; } + background: #ff5722 !important; +} .leave_type_color_4 { - background: #FF80AB !important; } + background: #ff80ab !important; +} .leave_type_color_5 { - background: #00BCD4 !important; } + background: #00bcd4 !important; +} diff --git a/public/js/bank_holidays.js b/public/js/bank_holidays.js index 11328fc75..f25ee304d 100644 --- a/public/js/bank_holidays.js +++ b/public/js/bank_holidays.js @@ -1,25 +1,25 @@ +$(document).ready(function() { + $('button.bankholiday-remove-btn').on('click', function(e) { + e.stopPropagation() -$(document).ready(function () { - $('button.bankholiday-remove-btn').on('click', function(e){ + const delete_form = $('#delete_bankholiday_form') + delete_form.attr( + 'action', + delete_form.attr('action') + $(this).attr('value') + '/' + ) - e.stopPropagation(); + delete_form.submit() - var delete_form = $('#delete_bankholiday_form'); - delete_form.attr('action', delete_form.attr('action') + $(this).attr('value') + '/'); + return false + }) - delete_form.submit(); + $('#bankholiday-import-btn').on('click', function(e) { + e.stopPropagation() - return false; - }); + const import_form = $('#import_bankholiday_form') - $('#bankholiday-import-btn').on('click', function(e){ + import_form.submit() - e.stopPropagation(); - - var import_form = $('#import_bankholiday_form'); - - import_form.submit(); - - return false; - }); -}); + return false + }) +}) diff --git a/public/js/bootstrap-datepicker.js b/public/js/bootstrap-datepicker.js index fb56652e1..6f6f330e5 100644 --- a/public/js/bootstrap-datepicker.js +++ b/public/js/bootstrap-datepicker.js @@ -4,1915 +4,2055 @@ * Copyright 2012 Stefan Petre * Improvements by Andrew Rowls * Licensed under the Apache License v2.0 (http://www.apache.org/licenses/LICENSE-2.0) - */(function(factory){ - if (typeof define === "function" && define.amd) { - define(["jquery"], factory); - } else if (typeof exports === 'object') { - factory(require('jquery')); + */ ;(function(factory) { + if (typeof define === 'function' && define.amd) { + define(['jquery'], factory) + } else if (typeof exports === 'object') { + factory(require('jquery')) + } else { + factory(jQuery) + } +})(function($, undefined) { + function UTCDate() { + return new Date(Date.UTC.apply(Date, arguments)) + } + function UTCToday() { + const today = new Date() + return UTCDate(today.getFullYear(), today.getMonth(), today.getDate()) + } + function isUTCEquals(date1, date2) { + return ( + date1.getUTCFullYear() === date2.getUTCFullYear() && + date1.getUTCMonth() === date2.getUTCMonth() && + date1.getUTCDate() === date2.getUTCDate() + ) + } + function alias(method) { + return function() { + return this[method].apply(this, arguments) + } + } + function isValidDate(d) { + return d && !isNaN(d.getTime()) + } + + var DateArray = (function() { + const extras = { + get: function(i) { + return this.slice(i)[0] + }, + contains: function(d) { + // Array.indexOf is not cross-browser; + // $.inArray doesn't work with Dates + const val = d && d.valueOf() + for (let i = 0, l = this.length; i < l; i++) + if (this[i].valueOf() === val) return i + return -1 + }, + remove: function(i) { + this.splice(i, 1) + }, + replace: function(new_array) { + if (!new_array) return + if (!$.isArray(new_array)) new_array = [new_array] + this.clear() + this.push.apply(this, new_array) + }, + clear: function() { + this.length = 0 + }, + copy: function() { + const a = new DateArray() + a.replace(this) + return a + } + } + + return function() { + const a = [] + a.push.apply(a, arguments) + $.extend(a, extras) + return a + } + })() + + // Picker object + + const Datepicker = function(element, options) { + $(element).data('datepicker', this) + this._process_options(options) + + this.dates = new DateArray() + this.viewDate = this.o.defaultViewDate + this.focusDate = null + + this.element = $(element) + this.isInline = false + this.isInput = this.element.is('input') + this.component = this.element.hasClass('date') + ? this.element.find('.add-on, .input-group-addon, .btn') + : false + this.hasInput = this.component && this.element.find('input').length + if (this.component && this.component.length === 0) this.component = false + + this.picker = $(DPGlobal.template) + this._buildEvents() + this._attachEvents() + + if (this.isInline) { + this.picker.addClass('datepicker-inline').appendTo(this.element) } else { - factory(jQuery); + this.picker.addClass('datepicker-dropdown dropdown-menu') + } + + if (this.o.rtl) { + this.picker.addClass('datepicker-rtl') } -}(function($, undefined){ - - function UTCDate(){ - return new Date(Date.UTC.apply(Date, arguments)); - } - function UTCToday(){ - var today = new Date(); - return UTCDate(today.getFullYear(), today.getMonth(), today.getDate()); - } - function isUTCEquals(date1, date2) { - return ( - date1.getUTCFullYear() === date2.getUTCFullYear() && - date1.getUTCMonth() === date2.getUTCMonth() && - date1.getUTCDate() === date2.getUTCDate() - ); - } - function alias(method){ - return function(){ - return this[method].apply(this, arguments); - }; - } - function isValidDate(d) { - return d && !isNaN(d.getTime()); - } - - var DateArray = (function(){ - var extras = { - get: function(i){ - return this.slice(i)[0]; - }, - contains: function(d){ - // Array.indexOf is not cross-browser; - // $.inArray doesn't work with Dates - var val = d && d.valueOf(); - for (var i=0, l=this.length; i < l; i++) - if (this[i].valueOf() === val) - return i; - return -1; - }, - remove: function(i){ - this.splice(i,1); - }, - replace: function(new_array){ - if (!new_array) - return; - if (!$.isArray(new_array)) - new_array = [new_array]; - this.clear(); - this.push.apply(this, new_array); - }, - clear: function(){ - this.length = 0; - }, - copy: function(){ - var a = new DateArray(); - a.replace(this); - return a; - } - }; - - return function(){ - var a = []; - a.push.apply(a, arguments); - $.extend(a, extras); - return a; - }; - })(); - - - // Picker object - - var Datepicker = function(element, options){ - $(element).data('datepicker', this); - this._process_options(options); - - this.dates = new DateArray(); - this.viewDate = this.o.defaultViewDate; - this.focusDate = null; - - this.element = $(element); - this.isInline = false; - this.isInput = this.element.is('input'); - this.component = this.element.hasClass('date') ? this.element.find('.add-on, .input-group-addon, .btn') : false; - this.hasInput = this.component && this.element.find('input').length; - if (this.component && this.component.length === 0) - this.component = false; - - this.picker = $(DPGlobal.template); - this._buildEvents(); - this._attachEvents(); - - if (this.isInline){ - this.picker.addClass('datepicker-inline').appendTo(this.element); - } - else { - this.picker.addClass('datepicker-dropdown dropdown-menu'); - } - - if (this.o.rtl){ - this.picker.addClass('datepicker-rtl'); - } - - this.viewMode = this.o.startView; - - if (this.o.calendarWeeks) - this.picker.find('thead .datepicker-title, tfoot .today, tfoot .clear') - .attr('colspan', function(i, val){ - return parseInt(val) + 1; - }); - - this._allow_update = false; - - this.setStartDate(this._o.startDate); - this.setEndDate(this._o.endDate); - this.setDaysOfWeekDisabled(this.o.daysOfWeekDisabled); - this.setDaysOfWeekHighlighted(this.o.daysOfWeekHighlighted); - this.setDatesDisabled(this.o.datesDisabled); - - this.fillDow(); - this.fillMonths(); - - this._allow_update = true; - - this.update(); - this.showMode(); - - if (this.isInline){ - this.show(); - } - }; - - Datepicker.prototype = { - constructor: Datepicker, - - _process_options: function(opts){ - // Store raw options for reference - this._o = $.extend({}, this._o, opts); - // Processed options - var o = this.o = $.extend({}, this._o); - - // Check if "de-DE" style date is available, if not language should - // fallback to 2 letter code eg "de" - var lang = o.language; - if (!dates[lang]){ - lang = lang.split('-')[0]; - if (!dates[lang]) - lang = defaults.language; - } - o.language = lang; - - switch (o.startView){ - case 2: - case 'decade': - o.startView = 2; - break; - case 1: - case 'year': - o.startView = 1; - break; - default: - o.startView = 0; - } - - switch (o.minViewMode){ - case 1: - case 'months': - o.minViewMode = 1; - break; - case 2: - case 'years': - o.minViewMode = 2; - break; - default: - o.minViewMode = 0; - } - - switch (o.maxViewMode) { - case 0: - case 'days': - o.maxViewMode = 0; - break; - case 1: - case 'months': - o.maxViewMode = 1; - break; - default: - o.maxViewMode = 2; - } - - o.startView = Math.min(o.startView, o.maxViewMode); - o.startView = Math.max(o.startView, o.minViewMode); - - // true, false, or Number > 0 - if (o.multidate !== true){ - o.multidate = Number(o.multidate) || false; - if (o.multidate !== false) - o.multidate = Math.max(0, o.multidate); - } - o.multidateSeparator = String(o.multidateSeparator); - - o.weekStart %= 7; - o.weekEnd = (o.weekStart + 6) % 7; - - var format = DPGlobal.parseFormat(o.format); - if (o.startDate !== -Infinity){ - if (!!o.startDate){ - if (o.startDate instanceof Date) - o.startDate = this._local_to_utc(this._zero_time(o.startDate)); - else - o.startDate = DPGlobal.parseDate(o.startDate, format, o.language); - } - else { - o.startDate = -Infinity; - } - } - if (o.endDate !== Infinity){ - if (!!o.endDate){ - if (o.endDate instanceof Date) - o.endDate = this._local_to_utc(this._zero_time(o.endDate)); - else - o.endDate = DPGlobal.parseDate(o.endDate, format, o.language); - } - else { - o.endDate = Infinity; - } - } - - o.daysOfWeekDisabled = o.daysOfWeekDisabled||[]; - if (!$.isArray(o.daysOfWeekDisabled)) - o.daysOfWeekDisabled = o.daysOfWeekDisabled.split(/[,\s]*/); - o.daysOfWeekDisabled = $.map(o.daysOfWeekDisabled, function(d){ - return parseInt(d, 10); - }); - - o.daysOfWeekHighlighted = o.daysOfWeekHighlighted||[]; - if (!$.isArray(o.daysOfWeekHighlighted)) - o.daysOfWeekHighlighted = o.daysOfWeekHighlighted.split(/[,\s]*/); - o.daysOfWeekHighlighted = $.map(o.daysOfWeekHighlighted, function(d){ - return parseInt(d, 10); - }); - - o.datesDisabled = o.datesDisabled||[]; - if (!$.isArray(o.datesDisabled)) { - var datesDisabled = []; - datesDisabled.push(DPGlobal.parseDate(o.datesDisabled, format, o.language)); - o.datesDisabled = datesDisabled; - } - o.datesDisabled = $.map(o.datesDisabled,function(d){ - return DPGlobal.parseDate(d, format, o.language); - }); - - var plc = String(o.orientation).toLowerCase().split(/\s+/g), - _plc = o.orientation.toLowerCase(); - plc = $.grep(plc, function(word){ - return /^auto|left|right|top|bottom$/.test(word); - }); - o.orientation = {x: 'auto', y: 'auto'}; - if (!_plc || _plc === 'auto') - ; // no action - else if (plc.length === 1){ - switch (plc[0]){ - case 'top': - case 'bottom': - o.orientation.y = plc[0]; - break; - case 'left': - case 'right': - o.orientation.x = plc[0]; - break; - } - } - else { - _plc = $.grep(plc, function(word){ - return /^left|right$/.test(word); - }); - o.orientation.x = _plc[0] || 'auto'; - - _plc = $.grep(plc, function(word){ - return /^top|bottom$/.test(word); - }); - o.orientation.y = _plc[0] || 'auto'; - } - if (o.defaultViewDate) { - var year = o.defaultViewDate.year || new Date().getFullYear(); - var month = o.defaultViewDate.month || 0; - var day = o.defaultViewDate.day || 1; - o.defaultViewDate = UTCDate(year, month, day); - } else { - o.defaultViewDate = UTCToday(); - } - }, - _events: [], - _secondaryEvents: [], - _applyEvents: function(evs){ - for (var i=0, el, ch, ev; i < evs.length; i++){ - el = evs[i][0]; - if (evs[i].length === 2){ - ch = undefined; - ev = evs[i][1]; - } - else if (evs[i].length === 3){ - ch = evs[i][1]; - ev = evs[i][2]; - } - el.on(ev, ch); - } - }, - _unapplyEvents: function(evs){ - for (var i=0, el, ev, ch; i < evs.length; i++){ - el = evs[i][0]; - if (evs[i].length === 2){ - ch = undefined; - ev = evs[i][1]; - } - else if (evs[i].length === 3){ - ch = evs[i][1]; - ev = evs[i][2]; - } - el.off(ev, ch); - } - }, - _buildEvents: function(){ - var events = { - keyup: $.proxy(function(e){ - if ($.inArray(e.keyCode, [27, 37, 39, 38, 40, 32, 13, 9]) === -1) - this.update(); - }, this), - keydown: $.proxy(this.keydown, this), - paste: $.proxy(this.paste, this) - }; - - if (this.o.showOnFocus === true) { - events.focus = $.proxy(this.show, this); + + this.viewMode = this.o.startView + + if (this.o.calendarWeeks) + this.picker + .find('thead .datepicker-title, tfoot .today, tfoot .clear') + .attr('colspan', function(i, val) { + return parseInt(val) + 1 + }) + + this._allow_update = false + + this.setStartDate(this._o.startDate) + this.setEndDate(this._o.endDate) + this.setDaysOfWeekDisabled(this.o.daysOfWeekDisabled) + this.setDaysOfWeekHighlighted(this.o.daysOfWeekHighlighted) + this.setDatesDisabled(this.o.datesDisabled) + + this.fillDow() + this.fillMonths() + + this._allow_update = true + + this.update() + this.showMode() + + if (this.isInline) { + this.show() + } + } + + Datepicker.prototype = { + constructor: Datepicker, + + _process_options: function(opts) { + // Store raw options for reference + this._o = $.extend({}, this._o, opts) + // Processed options + const o = (this.o = $.extend({}, this._o)) + + // Check if "de-DE" style date is available, if not language should + // fallback to 2 letter code eg "de" + let lang = o.language + if (!dates[lang]) { + lang = lang.split('-')[0] + if (!dates[lang]) lang = defaults.language + } + o.language = lang + + switch (o.startView) { + case 2: + case 'decade': + o.startView = 2 + break + case 1: + case 'year': + o.startView = 1 + break + default: + o.startView = 0 + } + + switch (o.minViewMode) { + case 1: + case 'months': + o.minViewMode = 1 + break + case 2: + case 'years': + o.minViewMode = 2 + break + default: + o.minViewMode = 0 + } + + switch (o.maxViewMode) { + case 0: + case 'days': + o.maxViewMode = 0 + break + case 1: + case 'months': + o.maxViewMode = 1 + break + default: + o.maxViewMode = 2 + } + + o.startView = Math.min(o.startView, o.maxViewMode) + o.startView = Math.max(o.startView, o.minViewMode) + + // true, false, or Number > 0 + if (o.multidate !== true) { + o.multidate = Number(o.multidate) || false + if (o.multidate !== false) o.multidate = Math.max(0, o.multidate) + } + o.multidateSeparator = String(o.multidateSeparator) + + o.weekStart %= 7 + o.weekEnd = (o.weekStart + 6) % 7 + + const format = DPGlobal.parseFormat(o.format) + if (o.startDate !== -Infinity) { + if (o.startDate) { + if (o.startDate instanceof Date) + o.startDate = this._local_to_utc(this._zero_time(o.startDate)) + else o.startDate = DPGlobal.parseDate(o.startDate, format, o.language) + } else { + o.startDate = -Infinity + } + } + if (o.endDate !== Infinity) { + if (o.endDate) { + if (o.endDate instanceof Date) + o.endDate = this._local_to_utc(this._zero_time(o.endDate)) + else o.endDate = DPGlobal.parseDate(o.endDate, format, o.language) + } else { + o.endDate = Infinity + } + } + + o.daysOfWeekDisabled = o.daysOfWeekDisabled || [] + if (!$.isArray(o.daysOfWeekDisabled)) + o.daysOfWeekDisabled = o.daysOfWeekDisabled.split(/[,\s]*/) + o.daysOfWeekDisabled = $.map(o.daysOfWeekDisabled, function(d) { + return parseInt(d, 10) + }) + + o.daysOfWeekHighlighted = o.daysOfWeekHighlighted || [] + if (!$.isArray(o.daysOfWeekHighlighted)) + o.daysOfWeekHighlighted = o.daysOfWeekHighlighted.split(/[,\s]*/) + o.daysOfWeekHighlighted = $.map(o.daysOfWeekHighlighted, function(d) { + return parseInt(d, 10) + }) + + o.datesDisabled = o.datesDisabled || [] + if (!$.isArray(o.datesDisabled)) { + const datesDisabled = [] + datesDisabled.push( + DPGlobal.parseDate(o.datesDisabled, format, o.language) + ) + o.datesDisabled = datesDisabled + } + o.datesDisabled = $.map(o.datesDisabled, function(d) { + return DPGlobal.parseDate(d, format, o.language) + }) + + let plc = String(o.orientation) + .toLowerCase() + .split(/\s+/g); + let _plc = o.orientation.toLowerCase() + plc = $.grep(plc, function(word) { + return /^auto|left|right|top|bottom$/.test(word) + }) + o.orientation = { x: 'auto', y: 'auto' } + if (!_plc || _plc === 'auto'); + else if (plc.length === 1) { + // no action + switch (plc[0]) { + case 'top': + case 'bottom': + o.orientation.y = plc[0] + break + case 'left': + case 'right': + o.orientation.x = plc[0] + break + } + } else { + _plc = $.grep(plc, function(word) { + return /^left|right$/.test(word) + }) + o.orientation.x = _plc[0] || 'auto' + + _plc = $.grep(plc, function(word) { + return /^top|bottom$/.test(word) + }) + o.orientation.y = _plc[0] || 'auto' + } + if (o.defaultViewDate) { + const year = o.defaultViewDate.year || new Date().getFullYear() + const month = o.defaultViewDate.month || 0 + const day = o.defaultViewDate.day || 1 + o.defaultViewDate = UTCDate(year, month, day) + } else { + o.defaultViewDate = UTCToday() + } + }, + _events: [], + _secondaryEvents: [], + _applyEvents: function(evs) { + for (var i = 0, el, ch, ev; i < evs.length; i++) { + el = evs[i][0] + if (evs[i].length === 2) { + ch = undefined + ev = evs[i][1] + } else if (evs[i].length === 3) { + ch = evs[i][1] + ev = evs[i][2] + } + el.on(ev, ch) + } + }, + _unapplyEvents: function(evs) { + for (var i = 0, el, ev, ch; i < evs.length; i++) { + el = evs[i][0] + if (evs[i].length === 2) { + ch = undefined + ev = evs[i][1] + } else if (evs[i].length === 3) { + ch = evs[i][1] + ev = evs[i][2] + } + el.off(ev, ch) + } + }, + _buildEvents: function() { + const events = { + keyup: $.proxy(function(e) { + if ($.inArray(e.keyCode, [27, 37, 39, 38, 40, 32, 13, 9]) === -1) + this.update() + }, this), + keydown: $.proxy(this.keydown, this), + paste: $.proxy(this.paste, this) + } + + if (this.o.showOnFocus === true) { + events.focus = $.proxy(this.show, this) + } + + if (this.isInput) { + // single input + this._events = [[this.element, events]] + } else if (this.component && this.hasInput) { + // component: input + button + this._events = [ + // For components that are not readonly, allow keyboard nav + [this.element.find('input'), events], + [ + this.component, + { + click: $.proxy(this.show, this) + } + ] + ] + } else if (this.element.is('div')) { + // inline datepicker + this.isInline = true + } else { + this._events = [ + [ + this.element, + { + click: $.proxy(this.show, this) } + ] + ] + } + this._events.push( + // Component: listen for blur on element descendants + [ + this.element, + '*', + { + blur: $.proxy(function(e) { + this._focused_from = e.target + }, this) + } + ], + // Input: listen for blur on element + [ + this.element, + { + blur: $.proxy(function(e) { + this._focused_from = e.target + }, this) + } + ] + ) + + if (this.o.immediateUpdates) { + // Trigger input updates immediately on changed year/month + this._events.push([ + this.element, + { + 'changeYear changeMonth': $.proxy(function(e) { + this.update(e.date) + }, this) + } + ]) + } + + this._secondaryEvents = [ + [ + this.picker, + { + click: $.proxy(this.click, this) + } + ], + [ + $(window), + { + resize: $.proxy(this.place, this) + } + ], + [ + $(document), + { + mousedown: $.proxy(function(e) { + // Clicked outside the datepicker, hide it + if ( + !( + this.element.is(e.target) || + this.element.find(e.target).length || + this.picker.is(e.target) || + this.picker.find(e.target).length || + this.picker.hasClass('datepicker-inline') + ) + ) { + this.hide() + } + }, this) + } + ] + ] + }, + _attachEvents: function() { + this._detachEvents() + this._applyEvents(this._events) + }, + _detachEvents: function() { + this._unapplyEvents(this._events) + }, + _attachSecondaryEvents: function() { + this._detachSecondaryEvents() + this._applyEvents(this._secondaryEvents) + }, + _detachSecondaryEvents: function() { + this._unapplyEvents(this._secondaryEvents) + }, + _trigger: function(event, altdate) { + const date = altdate || this.dates.get(-1); + const local_date = this._utc_to_local(date) + + this.element.trigger({ + type: event, + date: local_date, + dates: $.map(this.dates, this._utc_to_local), + format: $.proxy(function(ix, format) { + if (arguments.length === 0) { + ix = this.dates.length - 1 + format = this.o.format + } else if (typeof ix === 'string') { + format = ix + ix = this.dates.length - 1 + } + format = format || this.o.format + const date = this.dates.get(ix) + return DPGlobal.formatDate(date, format, this.o.language) + }, this) + }) + }, + + show: function() { + const element = this.component ? this.element.find('input') : this.element + if (element.attr('readonly') && this.o.enableOnReadonly === false) return + if (!this.isInline) this.picker.appendTo(this.o.container) + this.place() + this.picker.show() + this._attachSecondaryEvents() + this._trigger('show') + if ( + (window.navigator.msMaxTouchPoints || 'ontouchstart' in document) && + this.o.disableTouchKeyboard + ) { + $(this.element).blur() + } + return this + }, + + hide: function() { + if (this.isInline) return this + if (!this.picker.is(':visible')) return this + this.focusDate = null + this.picker.hide().detach() + this._detachSecondaryEvents() + this.viewMode = this.o.startView + this.showMode() + + if ( + this.o.forceParse && + ((this.isInput && this.element.val()) || + (this.hasInput && this.element.find('input').val())) + ) + this.setValue() + this._trigger('hide') + return this + }, + + remove: function() { + this.hide() + this._detachEvents() + this._detachSecondaryEvents() + this.picker.remove() + delete this.element.data().datepicker + if (!this.isInput) { + delete this.element.data().date + } + return this + }, + + paste: function(evt) { + let dateString + if ( + evt.originalEvent.clipboardData && + evt.originalEvent.clipboardData.types && + $.inArray('text/plain', evt.originalEvent.clipboardData.types) !== -1 + ) { + dateString = evt.originalEvent.clipboardData.getData('text/plain') + } else if (window.clipboardData) { + dateString = window.clipboardData.getData('Text') + } else { + return + } + this.setDate(dateString) + this.update() + evt.preventDefault() + }, + + _utc_to_local: function(utc) { + return utc && new Date(utc.getTime() + utc.getTimezoneOffset() * 60000) + }, + _local_to_utc: function(local) { + return ( + local && new Date(local.getTime() - local.getTimezoneOffset() * 60000) + ) + }, + _zero_time: function(local) { + return ( + local && + new Date(local.getFullYear(), local.getMonth(), local.getDate()) + ) + }, + _zero_utc_time: function(utc) { + return ( + utc && + new Date( + Date.UTC(utc.getUTCFullYear(), utc.getUTCMonth(), utc.getUTCDate()) + ) + ) + }, + + getDates: function() { + return $.map(this.dates, this._utc_to_local) + }, + + getUTCDates: function() { + return $.map(this.dates, function(d) { + return new Date(d) + }) + }, + + getDate: function() { + return this._utc_to_local(this.getUTCDate()) + }, + + getUTCDate: function() { + const selected_date = this.dates.get(-1) + if (typeof selected_date !== 'undefined') { + return new Date(selected_date) + } else { + return null + } + }, + + clearDates: function() { + let element + if (this.isInput) { + element = this.element + } else if (this.component) { + element = this.element.find('input') + } + + if (element) { + element.val('') + } - if (this.isInput) { // single input - this._events = [ - [this.element, events] - ]; + this.update() + this._trigger('changeDate') + + if (this.o.autoclose) { + this.hide() + } + }, + setDates: function() { + const args = $.isArray(arguments[0]) ? arguments[0] : arguments + this.update.apply(this, args) + this._trigger('changeDate') + this.setValue() + return this + }, + + setUTCDates: function() { + const args = $.isArray(arguments[0]) ? arguments[0] : arguments + this.update.apply(this, $.map(args, this._utc_to_local)) + this._trigger('changeDate') + this.setValue() + return this + }, + + setDate: alias('setDates'), + setUTCDate: alias('setUTCDates'), + + setValue: function() { + const formatted = this.getFormattedDate() + if (!this.isInput) { + if (this.component) { + this.element.find('input').val(formatted) + } + } else { + this.element.val(formatted) + } + return this + }, + + getFormattedDate: function(format) { + if (format === undefined) format = this.o.format + + const lang = this.o.language + return $.map(this.dates, function(d) { + return DPGlobal.formatDate(d, format, lang) + }).join(this.o.multidateSeparator) + }, + + setStartDate: function(startDate) { + this._process_options({ startDate }) + this.update() + this.updateNavArrows() + return this + }, + + setEndDate: function(endDate) { + this._process_options({ endDate }) + this.update() + this.updateNavArrows() + return this + }, + + setDaysOfWeekDisabled: function(daysOfWeekDisabled) { + this._process_options({ daysOfWeekDisabled }) + this.update() + this.updateNavArrows() + return this + }, + + setDaysOfWeekHighlighted: function(daysOfWeekHighlighted) { + this._process_options({ daysOfWeekHighlighted }) + this.update() + return this + }, + + setDatesDisabled: function(datesDisabled) { + this._process_options({ datesDisabled }) + this.update() + this.updateNavArrows() + }, + + place: function() { + if (this.isInline) return this + const calendarWidth = this.picker.outerWidth(); + const calendarHeight = this.picker.outerHeight(); + const visualPadding = 10; + const container = $(this.o.container); + const windowWidth = container.width(); + const scrollTop = + this.o.container === 'body' + ? $(document).scrollTop() + : container.scrollTop(); + const appendOffset = container.offset() + + const parentsZindex = [] + this.element.parents().each(function() { + const itemZIndex = $(this).css('z-index') + if (itemZIndex !== 'auto' && itemZIndex !== 0) + parentsZindex.push(parseInt(itemZIndex)) + }) + const zIndex = Math.max.apply(Math, parentsZindex) + this.o.zIndexOffset + const offset = this.component + ? this.component.parent().offset() + : this.element.offset() + const height = this.component + ? this.component.outerHeight(true) + : this.element.outerHeight(false) + const width = this.component + ? this.component.outerWidth(true) + : this.element.outerWidth(false) + let left = offset.left - appendOffset.left; + let top = offset.top - appendOffset.top + + if (this.o.container !== 'body') { + top += scrollTop + } + + this.picker.removeClass( + 'datepicker-orient-top datepicker-orient-bottom ' + + 'datepicker-orient-right datepicker-orient-left' + ) + + if (this.o.orientation.x !== 'auto') { + this.picker.addClass('datepicker-orient-' + this.o.orientation.x) + if (this.o.orientation.x === 'right') left -= calendarWidth - width + } + // auto x orientation is best-placement: if it crosses a window + // edge, fudge it sideways + else { + if (offset.left < 0) { + // component is outside the window on the left side. Move it into visible range + this.picker.addClass('datepicker-orient-left') + left -= offset.left - visualPadding + } else if (left + calendarWidth > windowWidth) { + // the calendar passes the widow right edge. Align it to component right side + this.picker.addClass('datepicker-orient-right') + left += width - calendarWidth + } else { + // Default to left + this.picker.addClass('datepicker-orient-left') + } + } + + // auto y orientation is best-situation: top or bottom, no fudging, + // decision based on which shows more of the calendar + let yorient = this.o.orientation.y; + let top_overflow + if (yorient === 'auto') { + top_overflow = -scrollTop + top - calendarHeight + yorient = top_overflow < 0 ? 'bottom' : 'top' + } + + this.picker.addClass('datepicker-orient-' + yorient) + if (yorient === 'top') + top -= calendarHeight + parseInt(this.picker.css('padding-top')) + else top += height + + if (this.o.rtl) { + const right = windowWidth - (left + width) + this.picker.css({ + top, + right, + zIndex + }) + } else { + this.picker.css({ + top, + left, + zIndex + }) + } + return this + }, + + _allow_update: true, + update: function() { + if (!this._allow_update) return this + + const oldDates = this.dates.copy(); + let dates = []; + let fromArgs = false + if (arguments.length) { + $.each( + arguments, + $.proxy(function(i, date) { + if (date instanceof Date) date = this._local_to_utc(date) + dates.push(date) + }, this) + ) + fromArgs = true + } else { + dates = this.isInput + ? this.element.val() + : this.element.data('date') || this.element.find('input').val() + if (dates && this.o.multidate) + dates = dates.split(this.o.multidateSeparator) + else dates = [dates] + delete this.element.data().date + } + + dates = $.map( + dates, + $.proxy(function(date) { + return DPGlobal.parseDate(date, this.o.format, this.o.language) + }, this) + ) + dates = $.grep( + dates, + $.proxy(function(date) { + return !this.dateWithinRange(date) || !date + }, this), + true + ) + this.dates.replace(dates) + + if (this.dates.length) this.viewDate = new Date(this.dates.get(-1)) + else if (this.viewDate < this.o.startDate) + this.viewDate = new Date(this.o.startDate) + else if (this.viewDate > this.o.endDate) + this.viewDate = new Date(this.o.endDate) + else this.viewDate = this.o.defaultViewDate + + if (fromArgs) { + // setting date by clicking + this.setValue() + } else if (dates.length) { + // setting date by typing + if (String(oldDates) !== String(this.dates)) this._trigger('changeDate') + } + if (!this.dates.length && oldDates.length) this._trigger('clearDate') + + this.fill() + this.element.change() + return this + }, + + fillDow: function() { + let dowCnt = this.o.weekStart; + let html = '' + if (this.o.calendarWeeks) { + this.picker + .find('.datepicker-days .datepicker-switch') + .attr('colspan', function(i, val) { + return parseInt(val) + 1 + }) + html += ' ' + } + while (dowCnt < this.o.weekStart + 7) { + html += + '' + + dates[this.o.language].daysMin[dowCnt++ % 7] + + '' + } + html += '' + this.picker.find('.datepicker-days thead').append(html) + }, + + fillMonths: function() { + let html = ''; + let i = 0 + while (i < 12) { + html += + '' + + dates[this.o.language].monthsShort[i++] + + '' + } + this.picker.find('.datepicker-months td').html(html) + }, + + setRange: function(range) { + if (!range || !range.length) delete this.range + else + this.range = $.map(range, function(d) { + return d.valueOf() + }) + this.fill() + }, + + getClassNames: function(date) { + const cls = []; + const year = this.viewDate.getUTCFullYear(); + const month = this.viewDate.getUTCMonth(); + const today = new Date() + if ( + date.getUTCFullYear() < year || + (date.getUTCFullYear() === year && date.getUTCMonth() < month) + ) { + cls.push('old') + } else if ( + date.getUTCFullYear() > year || + (date.getUTCFullYear() === year && date.getUTCMonth() > month) + ) { + cls.push('new') + } + if (this.focusDate && date.valueOf() === this.focusDate.valueOf()) + cls.push('focused') + // Compare internal UTC date with local today, not UTC today + if ( + this.o.todayHighlight && + date.getUTCFullYear() === today.getFullYear() && + date.getUTCMonth() === today.getMonth() && + date.getUTCDate() === today.getDate() + ) { + cls.push('today') + } + if (this.dates.contains(date) !== -1) cls.push('active') + if (!this.dateWithinRange(date) || this.dateIsDisabled(date)) { + cls.push('disabled') + } + if ($.inArray(date.getUTCDay(), this.o.daysOfWeekHighlighted) !== -1) { + cls.push('highlighted') + } + + if (this.range) { + if (date > this.range[0] && date < this.range[this.range.length - 1]) { + cls.push('range') + } + if ($.inArray(date.valueOf(), this.range) !== -1) { + cls.push('selected') + } + if (date.valueOf() === this.range[0]) { + cls.push('range-start') + } + if (date.valueOf() === this.range[this.range.length - 1]) { + cls.push('range-end') + } + } + return cls + }, + + fill: function() { + const d = new Date(this.viewDate); + let year = d.getUTCFullYear(); + const month = d.getUTCMonth(); + const startYear = + this.o.startDate !== -Infinity + ? this.o.startDate.getUTCFullYear() + : -Infinity; + const startMonth = + this.o.startDate !== -Infinity + ? this.o.startDate.getUTCMonth() + : -Infinity; + const endYear = + this.o.endDate !== Infinity + ? this.o.endDate.getUTCFullYear() + : Infinity; + const endMonth = + this.o.endDate !== Infinity ? this.o.endDate.getUTCMonth() : Infinity; + const todaytxt = dates[this.o.language].today || dates.en.today || ''; + const cleartxt = dates[this.o.language].clear || dates.en.clear || ''; + const titleFormat = + dates[this.o.language].titleFormat || dates.en.titleFormat; + let tooltip + if (isNaN(year) || isNaN(month)) return + this.picker + .find('.datepicker-days thead .datepicker-switch') + .text( + DPGlobal.formatDate( + new UTCDate(year, month), + titleFormat, + this.o.language + ) + ) + this.picker + .find('tfoot .today') + .text(todaytxt) + .toggle(this.o.todayBtn !== false) + this.picker + .find('tfoot .clear') + .text(cleartxt) + .toggle(this.o.clearBtn !== false) + this.picker + .find('thead .datepicker-title') + .text(this.o.title) + .toggle(this.o.title !== '') + this.updateNavArrows() + this.fillMonths() + const prevMonth = UTCDate(year, month - 1, 28); + const day = DPGlobal.getDaysInMonth( + prevMonth.getUTCFullYear(), + prevMonth.getUTCMonth() + ) + prevMonth.setUTCDate(day) + prevMonth.setUTCDate( + day - ((prevMonth.getUTCDay() - this.o.weekStart + 7) % 7) + ) + let nextMonth = new Date(prevMonth) + if (prevMonth.getUTCFullYear() < 100) { + nextMonth.setUTCFullYear(prevMonth.getUTCFullYear()) + } + nextMonth.setUTCDate(nextMonth.getUTCDate() + 42) + nextMonth = nextMonth.valueOf() + let html = [] + let clsName + while (prevMonth.valueOf() < nextMonth) { + if (prevMonth.getUTCDay() === this.o.weekStart) { + html.push('') + if (this.o.calendarWeeks) { + // ISO 8601: First week contains first thursday. + // ISO also states week starts on Monday, but we can be more abstract here. + const // Start of current week: based on weekstart/current date + ws = new Date( + +prevMonth + + ((this.o.weekStart - prevMonth.getUTCDay() - 7) % 7) * 864e5 + ); + // Thursday of this week + const th = new Date( + Number(ws) + ((7 + 4 - ws.getUTCDay()) % 7) * 864e5 + ); + // First Thursday of year, year from thursday + var yth = new Date( + Number((yth = UTCDate(th.getUTCFullYear(), 0, 1))) + + ((7 + 4 - yth.getUTCDay()) % 7) * 864e5 + ); + // Calendar week: ms between thursdays, div ms per day, div 7 days + const calWeek = (th - yth) / 864e5 / 7 + 1 + html.push('' + calWeek + '') + } + } + clsName = this.getClassNames(prevMonth) + clsName.push('day') + + if (this.o.beforeShowDay !== $.noop) { + let before = this.o.beforeShowDay(this._utc_to_local(prevMonth)) + if (before === undefined) before = {} + else if (typeof before === 'boolean') before = { enabled: before } + else if (typeof before === 'string') before = { classes: before } + if (before.enabled === false) clsName.push('disabled') + if (before.classes) + clsName = clsName.concat(before.classes.split(/\s+/)) + if (before.tooltip) tooltip = before.tooltip + } + + clsName = $.unique(clsName) + html.push( + '' + + prevMonth.getUTCDate() + + '' + ) + tooltip = null + if (prevMonth.getUTCDay() === this.o.weekEnd) { + html.push('') + } + prevMonth.setUTCDate(prevMonth.getUTCDate() + 1) + } + this.picker + .find('.datepicker-days tbody') + .empty() + .append(html.join('')) + + const monthsTitle = + dates[this.o.language].monthsTitle || + dates.en.monthsTitle || + 'Months' + const months = this.picker + .find('.datepicker-months') + .find('.datepicker-switch') + .text(this.o.maxViewMode < 2 ? monthsTitle : year) + .end() + .find('span') + .removeClass('active') + + $.each(this.dates, function(i, d) { + if (d.getUTCFullYear() === year) + months.eq(d.getUTCMonth()).addClass('active') + }) + + if (year < startYear || year > endYear) { + months.addClass('disabled') + } + if (year === startYear) { + months.slice(0, startMonth).addClass('disabled') + } + if (year === endYear) { + months.slice(endMonth + 1).addClass('disabled') + } + + if (this.o.beforeShowMonth !== $.noop) { + const that = this + $.each(months, function(i, month) { + if (!$(month).hasClass('disabled')) { + const moDate = new Date(year, i, 1) + const before = that.o.beforeShowMonth(moDate) + if (before === false) $(month).addClass('disabled') + } + }) + } + + html = '' + year = parseInt(year / 10, 10) * 10 + const yearCont = this.picker + .find('.datepicker-years') + .find('.datepicker-switch') + .text(year + '-' + (year + 9)) + .end() + .find('td') + year -= 1 + const years = $.map(this.dates, function(d) { + return d.getUTCFullYear() + }); + let classes + for (let i = -1; i < 11; i++) { + classes = ['year'] + tooltip = null + + if (i === -1) classes.push('old') + else if (i === 10) classes.push('new') + if ($.inArray(year, years) !== -1) classes.push('active') + if (year < startYear || year > endYear) classes.push('disabled') + + if (this.o.beforeShowYear !== $.noop) { + let yrBefore = this.o.beforeShowYear(new Date(year, 0, 1)) + if (yrBefore === undefined) yrBefore = {} + else if (typeof yrBefore === 'boolean') + yrBefore = { enabled: yrBefore } + else if (typeof yrBefore === 'string') + yrBefore = { classes: yrBefore } + if (yrBefore.enabled === false) classes.push('disabled') + if (yrBefore.classes) + classes = classes.concat(yrBefore.classes.split(/\s+/)) + if (yrBefore.tooltip) tooltip = yrBefore.tooltip + } + + html += + '' + + year + + '' + year += 1 + } + yearCont.html(html) + }, + + updateNavArrows: function() { + if (!this._allow_update) return + + const d = new Date(this.viewDate); + const year = d.getUTCFullYear(); + const month = d.getUTCMonth() + switch (this.viewMode) { + case 0: + if ( + this.o.startDate !== -Infinity && + year <= this.o.startDate.getUTCFullYear() && + month <= this.o.startDate.getUTCMonth() + ) { + this.picker.find('.prev').css({ visibility: 'hidden' }) + } else { + this.picker.find('.prev').css({ visibility: 'visible' }) + } + if ( + this.o.endDate !== Infinity && + year >= this.o.endDate.getUTCFullYear() && + month >= this.o.endDate.getUTCMonth() + ) { + this.picker.find('.next').css({ visibility: 'hidden' }) + } else { + this.picker.find('.next').css({ visibility: 'visible' }) + } + break + case 1: + case 2: + if ( + (this.o.startDate !== -Infinity && + year <= this.o.startDate.getUTCFullYear()) || + this.o.maxViewMode < 2 + ) { + this.picker.find('.prev').css({ visibility: 'hidden' }) + } else { + this.picker.find('.prev').css({ visibility: 'visible' }) + } + if ( + (this.o.endDate !== Infinity && + year >= this.o.endDate.getUTCFullYear()) || + this.o.maxViewMode < 2 + ) { + this.picker.find('.next').css({ visibility: 'hidden' }) + } else { + this.picker.find('.next').css({ visibility: 'visible' }) + } + break + } + }, + + click: function(e) { + e.preventDefault() + e.stopPropagation() + const target = $(e.target).closest('span, td, th'); + let year; + let month; + let day + if (target.length === 1) { + switch (target[0].nodeName.toLowerCase()) { + case 'th': + switch (target[0].className) { + case 'datepicker-switch': + this.showMode(1) + break + case 'prev': + case 'next': + var dir = + DPGlobal.modes[this.viewMode].navStep * + (target[0].className === 'prev' ? -1 : 1) + switch (this.viewMode) { + case 0: + this.viewDate = this.moveMonth(this.viewDate, dir) + this._trigger('changeMonth', this.viewDate) + break + case 1: + case 2: + this.viewDate = this.moveYear(this.viewDate, dir) + if (this.viewMode === 1) + this._trigger('changeYear', this.viewDate) + break + } + this.fill() + break + case 'today': + this.showMode(-2) + var which = this.o.todayBtn === 'linked' ? null : 'view' + this._setDate(UTCToday(), which) + break + case 'clear': + this.clearDates() + break + } + break + case 'span': + if (!target.hasClass('disabled')) { + this.viewDate.setUTCDate(1) + if (target.hasClass('month')) { + day = 1 + month = target + .parent() + .find('span') + .index(target) + year = this.viewDate.getUTCFullYear() + this.viewDate.setUTCMonth(month) + this._trigger('changeMonth', this.viewDate) + if (this.o.minViewMode === 1) { + this._setDate(UTCDate(year, month, day)) + this.showMode() + } else { + this.showMode(-1) + } + } else { + day = 1 + month = 0 + year = parseInt(target.text(), 10) || 0 + this.viewDate.setUTCFullYear(year) + this._trigger('changeYear', this.viewDate) + if (this.o.minViewMode === 2) { + this._setDate(UTCDate(year, month, day)) + } + this.showMode(-1) + } + this.fill() } - else if (this.component && this.hasInput) { // component: input + button - this._events = [ - // For components that are not readonly, allow keyboard nav - [this.element.find('input'), events], - [this.component, { - click: $.proxy(this.show, this) - }] - ]; + break + case 'td': + if (target.hasClass('day') && !target.hasClass('disabled')) { + day = parseInt(target.text(), 10) || 1 + year = this.viewDate.getUTCFullYear() + month = this.viewDate.getUTCMonth() + if (target.hasClass('old')) { + if (month === 0) { + month = 11 + year -= 1 + } else { + month -= 1 + } + } else if (target.hasClass('new')) { + if (month === 11) { + month = 0 + year += 1 + } else { + month += 1 + } + } + this._setDate(UTCDate(year, month, day)) } - else if (this.element.is('div')){ // inline datepicker - this.isInline = true; - } - else { - this._events = [ - [this.element, { - click: $.proxy(this.show, this) - }] - ]; - } - this._events.push( - // Component: listen for blur on element descendants - [this.element, '*', { - blur: $.proxy(function(e){ - this._focused_from = e.target; - }, this) - }], - // Input: listen for blur on element - [this.element, { - blur: $.proxy(function(e){ - this._focused_from = e.target; - }, this) - }] - ); - - if (this.o.immediateUpdates) { - // Trigger input updates immediately on changed year/month - this._events.push([this.element, { - 'changeYear changeMonth': $.proxy(function(e){ - this.update(e.date); - }, this) - }]); - } - - this._secondaryEvents = [ - [this.picker, { - click: $.proxy(this.click, this) - }], - [$(window), { - resize: $.proxy(this.place, this) - }], - [$(document), { - mousedown: $.proxy(function(e){ - // Clicked outside the datepicker, hide it - if (!( - this.element.is(e.target) || - this.element.find(e.target).length || - this.picker.is(e.target) || - this.picker.find(e.target).length || - this.picker.hasClass('datepicker-inline') - )){ - this.hide(); - } - }, this) - }] - ]; - }, - _attachEvents: function(){ - this._detachEvents(); - this._applyEvents(this._events); - }, - _detachEvents: function(){ - this._unapplyEvents(this._events); - }, - _attachSecondaryEvents: function(){ - this._detachSecondaryEvents(); - this._applyEvents(this._secondaryEvents); - }, - _detachSecondaryEvents: function(){ - this._unapplyEvents(this._secondaryEvents); - }, - _trigger: function(event, altdate){ - var date = altdate || this.dates.get(-1), - local_date = this._utc_to_local(date); - - this.element.trigger({ - type: event, - date: local_date, - dates: $.map(this.dates, this._utc_to_local), - format: $.proxy(function(ix, format){ - if (arguments.length === 0){ - ix = this.dates.length - 1; - format = this.o.format; - } - else if (typeof ix === 'string'){ - format = ix; - ix = this.dates.length - 1; - } - format = format || this.o.format; - var date = this.dates.get(ix); - return DPGlobal.formatDate(date, format, this.o.language); - }, this) - }); - }, - - show: function(){ - var element = this.component ? this.element.find('input') : this.element; - if (element.attr('readonly') && this.o.enableOnReadonly === false) - return; - if (!this.isInline) - this.picker.appendTo(this.o.container); - this.place(); - this.picker.show(); - this._attachSecondaryEvents(); - this._trigger('show'); - if ((window.navigator.msMaxTouchPoints || 'ontouchstart' in document) && this.o.disableTouchKeyboard) { - $(this.element).blur(); - } - return this; - }, - - hide: function(){ - if (this.isInline) - return this; - if (!this.picker.is(':visible')) - return this; - this.focusDate = null; - this.picker.hide().detach(); - this._detachSecondaryEvents(); - this.viewMode = this.o.startView; - this.showMode(); - - if ( - this.o.forceParse && - ( - this.isInput && this.element.val() || - this.hasInput && this.element.find('input').val() - ) - ) - this.setValue(); - this._trigger('hide'); - return this; - }, - - remove: function(){ - this.hide(); - this._detachEvents(); - this._detachSecondaryEvents(); - this.picker.remove(); - delete this.element.data().datepicker; - if (!this.isInput){ - delete this.element.data().date; - } - return this; - }, - - paste: function(evt){ - var dateString; - if (evt.originalEvent.clipboardData && evt.originalEvent.clipboardData.types - && $.inArray('text/plain', evt.originalEvent.clipboardData.types) !== -1) { - dateString = evt.originalEvent.clipboardData.getData('text/plain'); - } - else if (window.clipboardData) { - dateString = window.clipboardData.getData('Text'); - } - else { - return; - } - this.setDate(dateString); - this.update(); - evt.preventDefault(); - }, - - _utc_to_local: function(utc){ - return utc && new Date(utc.getTime() + (utc.getTimezoneOffset()*60000)); - }, - _local_to_utc: function(local){ - return local && new Date(local.getTime() - (local.getTimezoneOffset()*60000)); - }, - _zero_time: function(local){ - return local && new Date(local.getFullYear(), local.getMonth(), local.getDate()); - }, - _zero_utc_time: function(utc){ - return utc && new Date(Date.UTC(utc.getUTCFullYear(), utc.getUTCMonth(), utc.getUTCDate())); - }, - - getDates: function(){ - return $.map(this.dates, this._utc_to_local); - }, - - getUTCDates: function(){ - return $.map(this.dates, function(d){ - return new Date(d); - }); - }, - - getDate: function(){ - return this._utc_to_local(this.getUTCDate()); - }, - - getUTCDate: function(){ - var selected_date = this.dates.get(-1); - if (typeof selected_date !== 'undefined') { - return new Date(selected_date); - } else { - return null; - } - }, - - clearDates: function(){ - var element; - if (this.isInput) { - element = this.element; - } else if (this.component) { - element = this.element.find('input'); - } - - if (element) { - element.val(''); - } - - this.update(); - this._trigger('changeDate'); - - if (this.o.autoclose) { - this.hide(); - } - }, - setDates: function(){ - var args = $.isArray(arguments[0]) ? arguments[0] : arguments; - this.update.apply(this, args); - this._trigger('changeDate'); - this.setValue(); - return this; - }, - - setUTCDates: function(){ - var args = $.isArray(arguments[0]) ? arguments[0] : arguments; - this.update.apply(this, $.map(args, this._utc_to_local)); - this._trigger('changeDate'); - this.setValue(); - return this; - }, - - setDate: alias('setDates'), - setUTCDate: alias('setUTCDates'), - - setValue: function(){ - var formatted = this.getFormattedDate(); - if (!this.isInput){ - if (this.component){ - this.element.find('input').val(formatted); - } - } - else { - this.element.val(formatted); - } - return this; - }, - - getFormattedDate: function(format){ - if (format === undefined) - format = this.o.format; - - var lang = this.o.language; - return $.map(this.dates, function(d){ - return DPGlobal.formatDate(d, format, lang); - }).join(this.o.multidateSeparator); - }, - - setStartDate: function(startDate){ - this._process_options({startDate: startDate}); - this.update(); - this.updateNavArrows(); - return this; - }, - - setEndDate: function(endDate){ - this._process_options({endDate: endDate}); - this.update(); - this.updateNavArrows(); - return this; - }, - - setDaysOfWeekDisabled: function(daysOfWeekDisabled){ - this._process_options({daysOfWeekDisabled: daysOfWeekDisabled}); - this.update(); - this.updateNavArrows(); - return this; - }, - - setDaysOfWeekHighlighted: function(daysOfWeekHighlighted){ - this._process_options({daysOfWeekHighlighted: daysOfWeekHighlighted}); - this.update(); - return this; - }, - - setDatesDisabled: function(datesDisabled){ - this._process_options({datesDisabled: datesDisabled}); - this.update(); - this.updateNavArrows(); - }, - - place: function(){ - if (this.isInline) - return this; - var calendarWidth = this.picker.outerWidth(), - calendarHeight = this.picker.outerHeight(), - visualPadding = 10, - container = $(this.o.container), - windowWidth = container.width(), - scrollTop = this.o.container === 'body' ? $(document).scrollTop() : container.scrollTop(), - appendOffset = container.offset(); - - var parentsZindex = []; - this.element.parents().each(function(){ - var itemZIndex = $(this).css('z-index'); - if (itemZIndex !== 'auto' && itemZIndex !== 0) parentsZindex.push(parseInt(itemZIndex)); - }); - var zIndex = Math.max.apply(Math, parentsZindex) + this.o.zIndexOffset; - var offset = this.component ? this.component.parent().offset() : this.element.offset(); - var height = this.component ? this.component.outerHeight(true) : this.element.outerHeight(false); - var width = this.component ? this.component.outerWidth(true) : this.element.outerWidth(false); - var left = offset.left - appendOffset.left, - top = offset.top - appendOffset.top; - - if (this.o.container !== 'body') { - top += scrollTop; - } - - this.picker.removeClass( - 'datepicker-orient-top datepicker-orient-bottom '+ - 'datepicker-orient-right datepicker-orient-left' - ); - - if (this.o.orientation.x !== 'auto'){ - this.picker.addClass('datepicker-orient-' + this.o.orientation.x); - if (this.o.orientation.x === 'right') - left -= calendarWidth - width; - } - // auto x orientation is best-placement: if it crosses a window - // edge, fudge it sideways - else { - if (offset.left < 0) { - // component is outside the window on the left side. Move it into visible range - this.picker.addClass('datepicker-orient-left'); - left -= offset.left - visualPadding; - } else if (left + calendarWidth > windowWidth) { - // the calendar passes the widow right edge. Align it to component right side - this.picker.addClass('datepicker-orient-right'); - left += width - calendarWidth; - } else { - // Default to left - this.picker.addClass('datepicker-orient-left'); - } - } - - // auto y orientation is best-situation: top or bottom, no fudging, - // decision based on which shows more of the calendar - var yorient = this.o.orientation.y, - top_overflow; - if (yorient === 'auto'){ - top_overflow = -scrollTop + top - calendarHeight; - yorient = top_overflow < 0 ? 'bottom' : 'top'; - } - - this.picker.addClass('datepicker-orient-' + yorient); - if (yorient === 'top') - top -= calendarHeight + parseInt(this.picker.css('padding-top')); - else - top += height; - - if (this.o.rtl) { - var right = windowWidth - (left + width); - this.picker.css({ - top: top, - right: right, - zIndex: zIndex - }); - } else { - this.picker.css({ - top: top, - left: left, - zIndex: zIndex - }); - } - return this; - }, - - _allow_update: true, - update: function(){ - if (!this._allow_update) - return this; - - var oldDates = this.dates.copy(), - dates = [], - fromArgs = false; - if (arguments.length){ - $.each(arguments, $.proxy(function(i, date){ - if (date instanceof Date) - date = this._local_to_utc(date); - dates.push(date); - }, this)); - fromArgs = true; - } - else { - dates = this.isInput - ? this.element.val() - : this.element.data('date') || this.element.find('input').val(); - if (dates && this.o.multidate) - dates = dates.split(this.o.multidateSeparator); - else - dates = [dates]; - delete this.element.data().date; - } - - dates = $.map(dates, $.proxy(function(date){ - return DPGlobal.parseDate(date, this.o.format, this.o.language); - }, this)); - dates = $.grep(dates, $.proxy(function(date){ - return ( - !this.dateWithinRange(date) || - !date - ); - }, this), true); - this.dates.replace(dates); - - if (this.dates.length) - this.viewDate = new Date(this.dates.get(-1)); - else if (this.viewDate < this.o.startDate) - this.viewDate = new Date(this.o.startDate); - else if (this.viewDate > this.o.endDate) - this.viewDate = new Date(this.o.endDate); - else - this.viewDate = this.o.defaultViewDate; - - if (fromArgs){ - // setting date by clicking - this.setValue(); - } - else if (dates.length){ - // setting date by typing - if (String(oldDates) !== String(this.dates)) - this._trigger('changeDate'); - } - if (!this.dates.length && oldDates.length) - this._trigger('clearDate'); - - this.fill(); - this.element.change(); - return this; - }, - - fillDow: function(){ - var dowCnt = this.o.weekStart, - html = ''; - if (this.o.calendarWeeks){ - this.picker.find('.datepicker-days .datepicker-switch') - .attr('colspan', function(i, val){ - return parseInt(val) + 1; - }); - html += ' '; - } - while (dowCnt < this.o.weekStart + 7){ - html += ''+dates[this.o.language].daysMin[(dowCnt++)%7]+''; - } - html += ''; - this.picker.find('.datepicker-days thead').append(html); - }, - - fillMonths: function(){ - var html = '', - i = 0; - while (i < 12){ - html += ''+dates[this.o.language].monthsShort[i++]+''; - } - this.picker.find('.datepicker-months td').html(html); - }, - - setRange: function(range){ - if (!range || !range.length) - delete this.range; - else - this.range = $.map(range, function(d){ - return d.valueOf(); - }); - this.fill(); - }, - - getClassNames: function(date){ - var cls = [], - year = this.viewDate.getUTCFullYear(), - month = this.viewDate.getUTCMonth(), - today = new Date(); - if (date.getUTCFullYear() < year || (date.getUTCFullYear() === year && date.getUTCMonth() < month)){ - cls.push('old'); - } - else if (date.getUTCFullYear() > year || (date.getUTCFullYear() === year && date.getUTCMonth() > month)){ - cls.push('new'); - } - if (this.focusDate && date.valueOf() === this.focusDate.valueOf()) - cls.push('focused'); - // Compare internal UTC date with local today, not UTC today - if (this.o.todayHighlight && - date.getUTCFullYear() === today.getFullYear() && - date.getUTCMonth() === today.getMonth() && - date.getUTCDate() === today.getDate()){ - cls.push('today'); - } - if (this.dates.contains(date) !== -1) - cls.push('active'); - if (!this.dateWithinRange(date) || this.dateIsDisabled(date)){ - cls.push('disabled'); - } - if ($.inArray(date.getUTCDay(), this.o.daysOfWeekHighlighted) !== -1){ - cls.push('highlighted'); - } - - if (this.range){ - if (date > this.range[0] && date < this.range[this.range.length-1]){ - cls.push('range'); - } - if ($.inArray(date.valueOf(), this.range) !== -1){ - cls.push('selected'); - } - if (date.valueOf() === this.range[0]){ - cls.push('range-start'); + break } - if (date.valueOf() === this.range[this.range.length-1]){ - cls.push('range-end'); + } + if (this.picker.is(':visible') && this._focused_from) { + $(this._focused_from).focus() + } + delete this._focused_from + }, + + _toggle_multidate: function(date) { + const ix = this.dates.contains(date) + if (!date) { + this.dates.clear() + } + + if (ix !== -1) { + if ( + this.o.multidate === true || + this.o.multidate > 1 || + this.o.toggleActive + ) { + this.dates.remove(ix) } - } - return cls; - }, - - fill: function(){ - var d = new Date(this.viewDate), - year = d.getUTCFullYear(), - month = d.getUTCMonth(), - startYear = this.o.startDate !== -Infinity ? this.o.startDate.getUTCFullYear() : -Infinity, - startMonth = this.o.startDate !== -Infinity ? this.o.startDate.getUTCMonth() : -Infinity, - endYear = this.o.endDate !== Infinity ? this.o.endDate.getUTCFullYear() : Infinity, - endMonth = this.o.endDate !== Infinity ? this.o.endDate.getUTCMonth() : Infinity, - todaytxt = dates[this.o.language].today || dates['en'].today || '', - cleartxt = dates[this.o.language].clear || dates['en'].clear || '', - titleFormat = dates[this.o.language].titleFormat || dates['en'].titleFormat, - tooltip; - if (isNaN(year) || isNaN(month)) - return; - this.picker.find('.datepicker-days thead .datepicker-switch') - .text(DPGlobal.formatDate(new UTCDate(year, month), titleFormat, this.o.language)); - this.picker.find('tfoot .today') - .text(todaytxt) - .toggle(this.o.todayBtn !== false); - this.picker.find('tfoot .clear') - .text(cleartxt) - .toggle(this.o.clearBtn !== false); - this.picker.find('thead .datepicker-title') - .text(this.o.title) - .toggle(this.o.title !== ''); - this.updateNavArrows(); - this.fillMonths(); - var prevMonth = UTCDate(year, month-1, 28), - day = DPGlobal.getDaysInMonth(prevMonth.getUTCFullYear(), prevMonth.getUTCMonth()); - prevMonth.setUTCDate(day); - prevMonth.setUTCDate(day - (prevMonth.getUTCDay() - this.o.weekStart + 7)%7); - var nextMonth = new Date(prevMonth); - if (prevMonth.getUTCFullYear() < 100){ - nextMonth.setUTCFullYear(prevMonth.getUTCFullYear()); - } - nextMonth.setUTCDate(nextMonth.getUTCDate() + 42); - nextMonth = nextMonth.valueOf(); - var html = []; - var clsName; - while (prevMonth.valueOf() < nextMonth){ - if (prevMonth.getUTCDay() === this.o.weekStart){ - html.push(''); - if (this.o.calendarWeeks){ - // ISO 8601: First week contains first thursday. - // ISO also states week starts on Monday, but we can be more abstract here. - var - // Start of current week: based on weekstart/current date - ws = new Date(+prevMonth + (this.o.weekStart - prevMonth.getUTCDay() - 7) % 7 * 864e5), - // Thursday of this week - th = new Date(Number(ws) + (7 + 4 - ws.getUTCDay()) % 7 * 864e5), - // First Thursday of year, year from thursday - yth = new Date(Number(yth = UTCDate(th.getUTCFullYear(), 0, 1)) + (7 + 4 - yth.getUTCDay())%7*864e5), - // Calendar week: ms between thursdays, div ms per day, div 7 days - calWeek = (th - yth) / 864e5 / 7 + 1; - html.push(''+ calWeek +''); - - } - } - clsName = this.getClassNames(prevMonth); - clsName.push('day'); - - if (this.o.beforeShowDay !== $.noop){ - var before = this.o.beforeShowDay(this._utc_to_local(prevMonth)); - if (before === undefined) - before = {}; - else if (typeof(before) === 'boolean') - before = {enabled: before}; - else if (typeof(before) === 'string') - before = {classes: before}; - if (before.enabled === false) - clsName.push('disabled'); - if (before.classes) - clsName = clsName.concat(before.classes.split(/\s+/)); - if (before.tooltip) - tooltip = before.tooltip; - } - - clsName = $.unique(clsName); - html.push(''+prevMonth.getUTCDate() + ''); - tooltip = null; - if (prevMonth.getUTCDay() === this.o.weekEnd){ - html.push(''); - } - prevMonth.setUTCDate(prevMonth.getUTCDate()+1); - } - this.picker.find('.datepicker-days tbody').empty().append(html.join('')); - - var monthsTitle = dates[this.o.language].monthsTitle || dates['en'].monthsTitle || 'Months'; - var months = this.picker.find('.datepicker-months') - .find('.datepicker-switch') - .text(this.o.maxViewMode < 2 ? monthsTitle : year) - .end() - .find('span').removeClass('active'); - - $.each(this.dates, function(i, d){ - if (d.getUTCFullYear() === year) - months.eq(d.getUTCMonth()).addClass('active'); - }); - - if (year < startYear || year > endYear){ - months.addClass('disabled'); - } - if (year === startYear){ - months.slice(0, startMonth).addClass('disabled'); - } - if (year === endYear){ - months.slice(endMonth+1).addClass('disabled'); - } - - if (this.o.beforeShowMonth !== $.noop){ - var that = this; - $.each(months, function(i, month){ - if (!$(month).hasClass('disabled')) { - var moDate = new Date(year, i, 1); - var before = that.o.beforeShowMonth(moDate); - if (before === false) - $(month).addClass('disabled'); - } - }); - } - - html = ''; - year = parseInt(year/10, 10) * 10; - var yearCont = this.picker.find('.datepicker-years') - .find('.datepicker-switch') - .text(year + '-' + (year + 9)) - .end() - .find('td'); - year -= 1; - var years = $.map(this.dates, function(d){ - return d.getUTCFullYear(); - }), - classes; - for (var i = -1; i < 11; i++){ - classes = ['year']; - tooltip = null; - - if (i === -1) - classes.push('old'); - else if (i === 10) - classes.push('new'); - if ($.inArray(year, years) !== -1) - classes.push('active'); - if (year < startYear || year > endYear) - classes.push('disabled'); - - if (this.o.beforeShowYear !== $.noop) { - var yrBefore = this.o.beforeShowYear(new Date(year, 0, 1)); - if (yrBefore === undefined) - yrBefore = {}; - else if (typeof(yrBefore) === 'boolean') - yrBefore = {enabled: yrBefore}; - else if (typeof(yrBefore) === 'string') - yrBefore = {classes: yrBefore}; - if (yrBefore.enabled === false) - classes.push('disabled'); - if (yrBefore.classes) - classes = classes.concat(yrBefore.classes.split(/\s+/)); - if (yrBefore.tooltip) - tooltip = yrBefore.tooltip; - } - - html += '' + year + ''; - year += 1; - } - yearCont.html(html); - }, - - updateNavArrows: function(){ - if (!this._allow_update) - return; - - var d = new Date(this.viewDate), - year = d.getUTCFullYear(), - month = d.getUTCMonth(); - switch (this.viewMode){ - case 0: - if (this.o.startDate !== -Infinity && year <= this.o.startDate.getUTCFullYear() && month <= this.o.startDate.getUTCMonth()){ - this.picker.find('.prev').css({visibility: 'hidden'}); - } - else { - this.picker.find('.prev').css({visibility: 'visible'}); - } - if (this.o.endDate !== Infinity && year >= this.o.endDate.getUTCFullYear() && month >= this.o.endDate.getUTCMonth()){ - this.picker.find('.next').css({visibility: 'hidden'}); - } - else { - this.picker.find('.next').css({visibility: 'visible'}); - } - break; - case 1: - case 2: - if (this.o.startDate !== -Infinity && year <= this.o.startDate.getUTCFullYear() || this.o.maxViewMode < 2){ - this.picker.find('.prev').css({visibility: 'hidden'}); - } - else { - this.picker.find('.prev').css({visibility: 'visible'}); - } - if (this.o.endDate !== Infinity && year >= this.o.endDate.getUTCFullYear() || this.o.maxViewMode < 2){ - this.picker.find('.next').css({visibility: 'hidden'}); - } - else { - this.picker.find('.next').css({visibility: 'visible'}); - } - break; - } - }, - - click: function(e){ - e.preventDefault(); - e.stopPropagation(); - var target = $(e.target).closest('span, td, th'), - year, month, day; - if (target.length === 1){ - switch (target[0].nodeName.toLowerCase()){ - case 'th': - switch (target[0].className){ - case 'datepicker-switch': - this.showMode(1); - break; - case 'prev': - case 'next': - var dir = DPGlobal.modes[this.viewMode].navStep * (target[0].className === 'prev' ? -1 : 1); - switch (this.viewMode){ - case 0: - this.viewDate = this.moveMonth(this.viewDate, dir); - this._trigger('changeMonth', this.viewDate); - break; - case 1: - case 2: - this.viewDate = this.moveYear(this.viewDate, dir); - if (this.viewMode === 1) - this._trigger('changeYear', this.viewDate); - break; - } - this.fill(); - break; - case 'today': - this.showMode(-2); - var which = this.o.todayBtn === 'linked' ? null : 'view'; - this._setDate(UTCToday(), which); - break; - case 'clear': - this.clearDates(); - break; - } - break; - case 'span': - if (!target.hasClass('disabled')){ - this.viewDate.setUTCDate(1); - if (target.hasClass('month')){ - day = 1; - month = target.parent().find('span').index(target); - year = this.viewDate.getUTCFullYear(); - this.viewDate.setUTCMonth(month); - this._trigger('changeMonth', this.viewDate); - if (this.o.minViewMode === 1){ - this._setDate(UTCDate(year, month, day)); - this.showMode(); - } else { - this.showMode(-1); - } - } - else { - day = 1; - month = 0; - year = parseInt(target.text(), 10)||0; - this.viewDate.setUTCFullYear(year); - this._trigger('changeYear', this.viewDate); - if (this.o.minViewMode === 2){ - this._setDate(UTCDate(year, month, day)); - } - this.showMode(-1); - } - this.fill(); - } - break; - case 'td': - if (target.hasClass('day') && !target.hasClass('disabled')){ - day = parseInt(target.text(), 10)||1; - year = this.viewDate.getUTCFullYear(); - month = this.viewDate.getUTCMonth(); - if (target.hasClass('old')){ - if (month === 0){ - month = 11; - year -= 1; - } - else { - month -= 1; - } - } - else if (target.hasClass('new')){ - if (month === 11){ - month = 0; - year += 1; - } - else { - month += 1; - } - } - this._setDate(UTCDate(year, month, day)); - } - break; - } - } - if (this.picker.is(':visible') && this._focused_from){ - $(this._focused_from).focus(); - } - delete this._focused_from; - }, - - _toggle_multidate: function(date){ - var ix = this.dates.contains(date); - if (!date){ - this.dates.clear(); - } - - if (ix !== -1){ - if (this.o.multidate === true || this.o.multidate > 1 || this.o.toggleActive){ - this.dates.remove(ix); - } - } else if (this.o.multidate === false) { - this.dates.clear(); - this.dates.push(date); - } - else { - this.dates.push(date); - } - - if (typeof this.o.multidate === 'number') - while (this.dates.length > this.o.multidate) - this.dates.remove(0); - }, - - _setDate: function(date, which){ - if (!which || which === 'date') - this._toggle_multidate(date && new Date(date)); - if (!which || which === 'view') - this.viewDate = date && new Date(date); - - this.fill(); - this.setValue(); - if (!which || which !== 'view') { - this._trigger('changeDate'); - } - var element; - if (this.isInput){ - element = this.element; - } - else if (this.component){ - element = this.element.find('input'); - } - if (element){ - element.change(); - } - if (this.o.autoclose && (!which || which === 'date')){ - this.hide(); - } - }, - - moveDay: function(date, dir){ - var newDate = new Date(date); - newDate.setUTCDate(date.getUTCDate() + dir); - - return newDate; - }, - - moveWeek: function(date, dir){ - return this.moveDay(date, dir * 7); - }, - - moveMonth: function(date, dir){ - if (!isValidDate(date)) - return this.o.defaultViewDate; - if (!dir) - return date; - var new_date = new Date(date.valueOf()), - day = new_date.getUTCDate(), - month = new_date.getUTCMonth(), - mag = Math.abs(dir), - new_month, test; - dir = dir > 0 ? 1 : -1; - if (mag === 1){ - test = dir === -1 - // If going back one month, make sure month is not current month - // (eg, Mar 31 -> Feb 31 == Feb 28, not Mar 02) - ? function(){ - return new_date.getUTCMonth() === month; - } - // If going forward one month, make sure month is as expected - // (eg, Jan 31 -> Feb 31 == Feb 28, not Mar 02) - : function(){ - return new_date.getUTCMonth() !== new_month; - }; - new_month = month + dir; - new_date.setUTCMonth(new_month); - // Dec -> Jan (12) or Jan -> Dec (-1) -- limit expected date to 0-11 - if (new_month < 0 || new_month > 11) - new_month = (new_month + 12) % 12; - } - else { - // For magnitudes >1, move one month at a time... - for (var i=0; i < mag; i++) - // ...which might decrease the day (eg, Jan 31 to Feb 28, etc)... - new_date = this.moveMonth(new_date, dir); - // ...then reset the day, keeping it in the new month - new_month = new_date.getUTCMonth(); - new_date.setUTCDate(day); - test = function(){ - return new_month !== new_date.getUTCMonth(); - }; - } - // Common date-resetting loop -- if date is beyond end of month, make it - // end of month - while (test()){ - new_date.setUTCDate(--day); - new_date.setUTCMonth(new_month); - } - return new_date; - }, - - moveYear: function(date, dir){ - return this.moveMonth(date, dir*12); - }, - - moveAvailableDate: function(date, dir, fn){ - do { - date = this[fn](date, dir); - - if (!this.dateWithinRange(date)) - return false; - - fn = 'moveDay'; - } - while (this.dateIsDisabled(date)); - - return date; - }, - - weekOfDateIsDisabled: function(date){ - return $.inArray(date.getUTCDay(), this.o.daysOfWeekDisabled) !== -1; - }, - - dateIsDisabled: function(date){ - return ( - this.weekOfDateIsDisabled(date) || - $.grep(this.o.datesDisabled, function(d){ - return isUTCEquals(date, d); - }).length > 0 - ); - }, - - dateWithinRange: function(date){ - return date >= this.o.startDate && date <= this.o.endDate; - }, - - keydown: function(e){ - if (!this.picker.is(':visible')){ - if (e.keyCode === 40 || e.keyCode === 27) { // allow down to re-show picker - this.show(); - e.stopPropagation(); + } else if (this.o.multidate === false) { + this.dates.clear() + this.dates.push(date) + } else { + this.dates.push(date) + } + + if (typeof this.o.multidate === 'number') + while (this.dates.length > this.o.multidate) this.dates.remove(0) + }, + + _setDate: function(date, which) { + if (!which || which === 'date') + this._toggle_multidate(date && new Date(date)) + if (!which || which === 'view') this.viewDate = date && new Date(date) + + this.fill() + this.setValue() + if (!which || which !== 'view') { + this._trigger('changeDate') + } + let element + if (this.isInput) { + element = this.element + } else if (this.component) { + element = this.element.find('input') + } + if (element) { + element.change() + } + if (this.o.autoclose && (!which || which === 'date')) { + this.hide() + } + }, + + moveDay: function(date, dir) { + const newDate = new Date(date) + newDate.setUTCDate(date.getUTCDate() + dir) + + return newDate + }, + + moveWeek: function(date, dir) { + return this.moveDay(date, dir * 7) + }, + + moveMonth: function(date, dir) { + if (!isValidDate(date)) return this.o.defaultViewDate + if (!dir) return date + let new_date = new Date(date.valueOf()); + let day = new_date.getUTCDate(); + const month = new_date.getUTCMonth(); + const mag = Math.abs(dir); + let new_month; + let test + dir = dir > 0 ? 1 : -1 + if (mag === 1) { + test = + dir === -1 + ? // If going back one month, make sure month is not current month + // (eg, Mar 31 -> Feb 31 == Feb 28, not Mar 02) + function() { + return new_date.getUTCMonth() === month + } + : // If going forward one month, make sure month is as expected + // (eg, Jan 31 -> Feb 31 == Feb 28, not Mar 02) + function() { + return new_date.getUTCMonth() !== new_month + } + new_month = month + dir + new_date.setUTCMonth(new_month) + // Dec -> Jan (12) or Jan -> Dec (-1) -- limit expected date to 0-11 + if (new_month < 0 || new_month > 11) new_month = (new_month + 12) % 12 + } else { + // For magnitudes >1, move one month at a time... + for (let i = 0; i < mag; i++) + // ...which might decrease the day (eg, Jan 31 to Feb 28, etc)... + new_date = this.moveMonth(new_date, dir) + // ...then reset the day, keeping it in the new month + new_month = new_date.getUTCMonth() + new_date.setUTCDate(day) + test = function() { + return new_month !== new_date.getUTCMonth() + } + } + // Common date-resetting loop -- if date is beyond end of month, make it + // end of month + while (test()) { + new_date.setUTCDate(--day) + new_date.setUTCMonth(new_month) + } + return new_date + }, + + moveYear: function(date, dir) { + return this.moveMonth(date, dir * 12) + }, + + moveAvailableDate: function(date, dir, fn) { + do { + date = this[fn](date, dir) + + if (!this.dateWithinRange(date)) return false + + fn = 'moveDay' + } while (this.dateIsDisabled(date)) + + return date + }, + + weekOfDateIsDisabled: function(date) { + return $.inArray(date.getUTCDay(), this.o.daysOfWeekDisabled) !== -1 + }, + + dateIsDisabled: function(date) { + return ( + this.weekOfDateIsDisabled(date) || + $.grep(this.o.datesDisabled, function(d) { + return isUTCEquals(date, d) + }).length > 0 + ) + }, + + dateWithinRange: function(date) { + return date >= this.o.startDate && date <= this.o.endDate + }, + + keydown: function(e) { + if (!this.picker.is(':visible')) { + if (e.keyCode === 40 || e.keyCode === 27) { + // allow down to re-show picker + this.show() + e.stopPropagation() + } + return + } + let dateChanged = false; + let dir; + let newViewDate; + let focusDate = this.focusDate || this.viewDate + switch (e.keyCode) { + case 27: // escape + if (this.focusDate) { + this.focusDate = null + this.viewDate = this.dates.get(-1) || this.viewDate + this.fill() + } else this.hide() + e.preventDefault() + e.stopPropagation() + break + case 37: // left + case 38: // up + case 39: // right + case 40: // down + if ( + !this.o.keyboardNavigation || + this.o.daysOfWeekDisabled.length === 7 + ) + break + dir = e.keyCode === 37 || e.keyCode === 38 ? -1 : 1 + if (e.ctrlKey) { + newViewDate = this.moveAvailableDate(focusDate, dir, 'moveYear') + + if (newViewDate) this._trigger('changeYear', this.viewDate) + } else if (e.shiftKey) { + newViewDate = this.moveAvailableDate(focusDate, dir, 'moveMonth') + + if (newViewDate) this._trigger('changeMonth', this.viewDate) + } else if (e.keyCode === 37 || e.keyCode === 39) { + newViewDate = this.moveAvailableDate(focusDate, dir, 'moveDay') + } else if (!this.weekOfDateIsDisabled(focusDate)) { + newViewDate = this.moveAvailableDate(focusDate, dir, 'moveWeek') + } + if (newViewDate) { + this.focusDate = this.viewDate = newViewDate + this.setValue() + this.fill() + e.preventDefault() + } + break + case 13: // enter + if (!this.o.forceParse) break + focusDate = this.focusDate || this.dates.get(-1) || this.viewDate + if (this.o.keyboardNavigation) { + this._toggle_multidate(focusDate) + dateChanged = true + } + this.focusDate = null + this.viewDate = this.dates.get(-1) || this.viewDate + this.setValue() + this.fill() + if (this.picker.is(':visible')) { + e.preventDefault() + e.stopPropagation() + if (this.o.autoclose) this.hide() + } + break + case 9: // tab + this.focusDate = null + this.viewDate = this.dates.get(-1) || this.viewDate + this.fill() + this.hide() + break + } + if (dateChanged) { + if (this.dates.length) this._trigger('changeDate') + else this._trigger('clearDate') + let element + if (this.isInput) { + element = this.element + } else if (this.component) { + element = this.element.find('input') + } + if (element) { + element.change() + } + } + }, + + showMode: function(dir) { + if (dir) { + this.viewMode = Math.max( + this.o.minViewMode, + Math.min(this.o.maxViewMode, this.viewMode + dir) + ) + } + this.picker + .children('div') + .hide() + .filter('.datepicker-' + DPGlobal.modes[this.viewMode].clsName) + .show() + this.updateNavArrows() + } + } + + const DateRangePicker = function(element, options) { + $(element).data('datepicker', this) + this.element = $(element) + this.inputs = $.map(options.inputs, function(i) { + return i.jquery ? i[0] : i + }) + delete options.inputs + + datepickerPlugin + .call($(this.inputs), options) + .on('changeDate', $.proxy(this.dateUpdated, this)) + + this.pickers = $.map(this.inputs, function(i) { + return $(i).data('datepicker') + }) + this.updateDates() + } + DateRangePicker.prototype = { + updateDates: function() { + this.dates = $.map(this.pickers, function(i) { + return i.getUTCDate() + }) + this.updateRanges() + }, + updateRanges: function() { + const range = $.map(this.dates, function(d) { + return d.valueOf() + }) + $.each(this.pickers, function(i, p) { + p.setRange(range) + }) + }, + dateUpdated: function(e) { + // `this.updating` is a workaround for preventing infinite recursion + // between `changeDate` triggering and `setUTCDate` calling. Until + // there is a better mechanism. + if (this.updating) return + this.updating = true + + const dp = $(e.target).data('datepicker') + + if (typeof dp === 'undefined') { + return + } + + const new_date = dp.getUTCDate(); + const i = $.inArray(e.target, this.inputs); + let j = i - 1; + let k = i + 1; + const l = this.inputs.length + if (i === -1) return + + $.each(this.pickers, function(i, p) { + if (!p.getUTCDate()) p.setUTCDate(new_date) + }) + + if (new_date < this.dates[j]) { + // Date being moved earlier/left + while (j >= 0 && new_date < this.dates[j]) { + this.pickers[j--].setUTCDate(new_date) + } + } else if (new_date > this.dates[k]) { + // Date being moved later/right + while (k < l && new_date > this.dates[k]) { + this.pickers[k++].setUTCDate(new_date) + } + } + this.updateDates() + + delete this.updating + }, + remove: function() { + $.map(this.pickers, function(p) { + p.remove() + }) + delete this.element.data().datepicker + } + } + + function opts_from_el(el, prefix) { + // Derive options from element data-attrs + const data = $(el).data(); + const out = {}; + let inkey; + const replace = new RegExp('^' + prefix.toLowerCase() + '([A-Z])') + prefix = new RegExp('^' + prefix.toLowerCase()) + function re_lower(_, a) { + return a.toLowerCase() + } + for (const key in data) + if (prefix.test(key)) { + inkey = key.replace(replace, re_lower) + out[inkey] = data[key] + } + return out + } + + function opts_from_locale(lang) { + // Derive options from locale plugins + const out = {} + // Check if "de-DE" style date is available, if not language should + // fallback to 2 letter code eg "de" + if (!dates[lang]) { + lang = lang.split('-')[0] + if (!dates[lang]) return + } + const d = dates[lang] + $.each(locale_opts, function(i, k) { + if (k in d) out[k] = d[k] + }) + return out + } + + const old = $.fn.datepicker + var datepickerPlugin = function(option) { + const args = Array.apply(null, arguments) + args.shift() + let internal_return + this.each(function() { + const $this = $(this); + let data = $this.data('datepicker'); + const options = typeof option === 'object' && option + if (!data) { + const elopts = opts_from_el(this, 'date'); + // Preliminary otions + const xopts = $.extend({}, defaults, elopts, options); + const locopts = opts_from_locale(xopts.language); + // Options priority: js args, data-attrs, locales, defaults + const opts = $.extend({}, defaults, locopts, elopts, options) + if ($this.hasClass('input-daterange') || opts.inputs) { + $.extend(opts, { + inputs: opts.inputs || $this.find('input').toArray() + }) + data = new DateRangePicker(this, opts) + } else { + data = new Datepicker(this, opts) + } + $this.data('datepicker', data) + } + if (typeof option === 'string' && typeof data[option] === 'function') { + internal_return = data[option].apply(data, args) + } + }) + + if ( + internal_return === undefined || + internal_return instanceof Datepicker || + internal_return instanceof DateRangePicker + ) + return this + + if (this.length > 1) + throw new Error( + 'Using only allowed for the collection of a single element (' + + option + + ' function)' + ) + else return internal_return + } + $.fn.datepicker = datepickerPlugin + + var defaults = ($.fn.datepicker.defaults = { + autoclose: false, + beforeShowDay: $.noop, + beforeShowMonth: $.noop, + beforeShowYear: $.noop, + calendarWeeks: false, + clearBtn: false, + toggleActive: false, + daysOfWeekDisabled: [], + daysOfWeekHighlighted: [], + datesDisabled: [], + endDate: Infinity, + forceParse: true, + format: 'mm/dd/yyyy', + keyboardNavigation: true, + language: 'en', + minViewMode: 0, + maxViewMode: 2, + multidate: false, + multidateSeparator: ',', + orientation: 'auto', + rtl: false, + startDate: -Infinity, + startView: 0, + todayBtn: false, + todayHighlight: false, + weekStart: 0, + disableTouchKeyboard: false, + enableOnReadonly: true, + showOnFocus: true, + zIndexOffset: 10, + container: 'body', + immediateUpdates: false, + title: '' + }) + var locale_opts = ($.fn.datepicker.locale_opts = [ + 'format', + 'rtl', + 'weekStart' + ]) + $.fn.datepicker.Constructor = Datepicker + var dates = ($.fn.datepicker.dates = { + en: { + days: [ + 'Sunday', + 'Monday', + 'Tuesday', + 'Wednesday', + 'Thursday', + 'Friday', + 'Saturday' + ], + daysShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'], + daysMin: ['Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa'], + months: [ + 'January', + 'February', + 'March', + 'April', + 'May', + 'June', + 'July', + 'August', + 'September', + 'October', + 'November', + 'December' + ], + monthsShort: [ + 'Jan', + 'Feb', + 'Mar', + 'Apr', + 'May', + 'Jun', + 'Jul', + 'Aug', + 'Sep', + 'Oct', + 'Nov', + 'Dec' + ], + today: 'Today', + clear: 'Clear', + titleFormat: 'MM yyyy' + } + }) + + var DPGlobal = { + modes: [ + { + clsName: 'days', + navFnc: 'Month', + navStep: 1 + }, + { + clsName: 'months', + navFnc: 'FullYear', + navStep: 1 + }, + { + clsName: 'years', + navFnc: 'FullYear', + navStep: 10 + } + ], + isLeapYear: function(year) { + return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0 + }, + getDaysInMonth: function(year, month) { + return [ + 31, + DPGlobal.isLeapYear(year) ? 29 : 28, + 31, + 30, + 31, + 30, + 31, + 31, + 30, + 31, + 30, + 31 + ][month] + }, + validParts: /dd?|DD?|mm?|MM?|yy(?:yy)?/g, + nonpunctuation: /[^ -\/:-@\[\u3400-\u9fff-`{-~\t\n\r]+/g, + parseFormat: function(format) { + if ( + typeof format.toValue === 'function' && + typeof format.toDisplay === 'function' + ) + return format + // IE treats \0 as a string end in inputs (truncating the value), + // so it's a bad format delimiter, anyway + const separators = format.replace(this.validParts, '\0').split('\0'); + const parts = format.match(this.validParts) + if (!separators || !separators.length || !parts || parts.length === 0) { + throw new Error('Invalid date format.') + } + return { separators, parts } + }, + parseDate: function(date, format, language) { + if (!date) return undefined + if (date instanceof Date) return date + if (typeof format === 'string') format = DPGlobal.parseFormat(format) + if (format.toValue) return format.toValue(date, format, language) + const part_re = /([\-+]\d+)([dmwy])/; + let parts = date.match(/([\-+]\d+)([dmwy])/g); + const fn_map = { + d: 'moveDay', + m: 'moveMonth', + w: 'moveWeek', + y: 'moveYear' + }; + let part; + let dir; + let i; + let fn + if (/^[\-+]\d+[dmwy]([\s,]+[\-+]\d+[dmwy])*$/.test(date)) { + date = new Date() + for (i = 0; i < parts.length; i++) { + part = part_re.exec(parts[i]) + dir = parseInt(part[1]) + fn = fn_map[part[2]] + date = Datepicker.prototype[fn](date, dir) } - return; - } - var dateChanged = false, - dir, newViewDate, - focusDate = this.focusDate || this.viewDate; - switch (e.keyCode){ - case 27: // escape - if (this.focusDate){ - this.focusDate = null; - this.viewDate = this.dates.get(-1) || this.viewDate; - this.fill(); - } - else - this.hide(); - e.preventDefault(); - e.stopPropagation(); - break; - case 37: // left - case 38: // up - case 39: // right - case 40: // down - if (!this.o.keyboardNavigation || this.o.daysOfWeekDisabled.length === 7) - break; - dir = e.keyCode === 37 || e.keyCode === 38 ? -1 : 1; - if (e.ctrlKey){ - newViewDate = this.moveAvailableDate(focusDate, dir, 'moveYear'); - - if (newViewDate) - this._trigger('changeYear', this.viewDate); - } - else if (e.shiftKey){ - newViewDate = this.moveAvailableDate(focusDate, dir, 'moveMonth'); - - if (newViewDate) - this._trigger('changeMonth', this.viewDate); - } - else if (e.keyCode === 37 || e.keyCode === 39){ - newViewDate = this.moveAvailableDate(focusDate, dir, 'moveDay'); - } - else if (!this.weekOfDateIsDisabled(focusDate)){ - newViewDate = this.moveAvailableDate(focusDate, dir, 'moveWeek'); - } - if (newViewDate){ - this.focusDate = this.viewDate = newViewDate; - this.setValue(); - this.fill(); - e.preventDefault(); - } - break; - case 13: // enter - if (!this.o.forceParse) - break; - focusDate = this.focusDate || this.dates.get(-1) || this.viewDate; - if (this.o.keyboardNavigation) { - this._toggle_multidate(focusDate); - dateChanged = true; - } - this.focusDate = null; - this.viewDate = this.dates.get(-1) || this.viewDate; - this.setValue(); - this.fill(); - if (this.picker.is(':visible')){ - e.preventDefault(); - e.stopPropagation(); - if (this.o.autoclose) - this.hide(); - } - break; - case 9: // tab - this.focusDate = null; - this.viewDate = this.dates.get(-1) || this.viewDate; - this.fill(); - this.hide(); - break; - } - if (dateChanged){ - if (this.dates.length) - this._trigger('changeDate'); - else - this._trigger('clearDate'); - var element; - if (this.isInput){ - element = this.element; - } - else if (this.component){ - element = this.element.find('input'); - } - if (element){ - element.change(); - } - } - }, - - showMode: function(dir){ - if (dir){ - this.viewMode = Math.max(this.o.minViewMode, Math.min(this.o.maxViewMode, this.viewMode + dir)); - } - this.picker - .children('div') - .hide() - .filter('.datepicker-' + DPGlobal.modes[this.viewMode].clsName) - .show(); - this.updateNavArrows(); - } - }; - - var DateRangePicker = function(element, options){ - $(element).data('datepicker', this); - this.element = $(element); - this.inputs = $.map(options.inputs, function(i){ - return i.jquery ? i[0] : i; - }); - delete options.inputs; - - datepickerPlugin.call($(this.inputs), options) - .on('changeDate', $.proxy(this.dateUpdated, this)); - - this.pickers = $.map(this.inputs, function(i){ - return $(i).data('datepicker'); - }); - this.updateDates(); - }; - DateRangePicker.prototype = { - updateDates: function(){ - this.dates = $.map(this.pickers, function(i){ - return i.getUTCDate(); - }); - this.updateRanges(); - }, - updateRanges: function(){ - var range = $.map(this.dates, function(d){ - return d.valueOf(); - }); - $.each(this.pickers, function(i, p){ - p.setRange(range); - }); - }, - dateUpdated: function(e){ - // `this.updating` is a workaround for preventing infinite recursion - // between `changeDate` triggering and `setUTCDate` calling. Until - // there is a better mechanism. - if (this.updating) - return; - this.updating = true; - - var dp = $(e.target).data('datepicker'); - - if (typeof(dp) === "undefined") { - return; - } - - var new_date = dp.getUTCDate(), - i = $.inArray(e.target, this.inputs), - j = i - 1, - k = i + 1, - l = this.inputs.length; - if (i === -1) - return; - - $.each(this.pickers, function(i, p){ - if (!p.getUTCDate()) - p.setUTCDate(new_date); - }); - - if (new_date < this.dates[j]){ - // Date being moved earlier/left - while (j >= 0 && new_date < this.dates[j]){ - this.pickers[j--].setUTCDate(new_date); - } - } - else if (new_date > this.dates[k]){ - // Date being moved later/right - while (k < l && new_date > this.dates[k]){ - this.pickers[k++].setUTCDate(new_date); - } - } - this.updateDates(); - - delete this.updating; - }, - remove: function(){ - $.map(this.pickers, function(p){ p.remove(); }); - delete this.element.data().datepicker; - } - }; - - function opts_from_el(el, prefix){ - // Derive options from element data-attrs - var data = $(el).data(), - out = {}, inkey, - replace = new RegExp('^' + prefix.toLowerCase() + '([A-Z])'); - prefix = new RegExp('^' + prefix.toLowerCase()); - function re_lower(_,a){ - return a.toLowerCase(); - } - for (var key in data) - if (prefix.test(key)){ - inkey = key.replace(replace, re_lower); - out[inkey] = data[key]; - } - return out; - } - - function opts_from_locale(lang){ - // Derive options from locale plugins - var out = {}; - // Check if "de-DE" style date is available, if not language should - // fallback to 2 letter code eg "de" - if (!dates[lang]){ - lang = lang.split('-')[0]; - if (!dates[lang]) - return; - } - var d = dates[lang]; - $.each(locale_opts, function(i,k){ - if (k in d) - out[k] = d[k]; - }); - return out; - } - - var old = $.fn.datepicker; - var datepickerPlugin = function(option){ - var args = Array.apply(null, arguments); - args.shift(); - var internal_return; - this.each(function(){ - var $this = $(this), - data = $this.data('datepicker'), - options = typeof option === 'object' && option; - if (!data){ - var elopts = opts_from_el(this, 'date'), - // Preliminary otions - xopts = $.extend({}, defaults, elopts, options), - locopts = opts_from_locale(xopts.language), - // Options priority: js args, data-attrs, locales, defaults - opts = $.extend({}, defaults, locopts, elopts, options); - if ($this.hasClass('input-daterange') || opts.inputs){ - $.extend(opts, { - inputs: opts.inputs || $this.find('input').toArray() - }); - data = new DateRangePicker(this, opts); - } - else { - data = new Datepicker(this, opts); - } - $this.data('datepicker', data); - } - if (typeof option === 'string' && typeof data[option] === 'function'){ - internal_return = data[option].apply(data, args); - } - }); - - if ( - internal_return === undefined || - internal_return instanceof Datepicker || - internal_return instanceof DateRangePicker - ) - return this; - - if (this.length > 1) - throw new Error('Using only allowed for the collection of a single element (' + option + ' function)'); - else - return internal_return; - }; - $.fn.datepicker = datepickerPlugin; - - var defaults = $.fn.datepicker.defaults = { - autoclose: false, - beforeShowDay: $.noop, - beforeShowMonth: $.noop, - beforeShowYear: $.noop, - calendarWeeks: false, - clearBtn: false, - toggleActive: false, - daysOfWeekDisabled: [], - daysOfWeekHighlighted: [], - datesDisabled: [], - endDate: Infinity, - forceParse: true, - format: 'mm/dd/yyyy', - keyboardNavigation: true, - language: 'en', - minViewMode: 0, - maxViewMode: 2, - multidate: false, - multidateSeparator: ',', - orientation: "auto", - rtl: false, - startDate: -Infinity, - startView: 0, - todayBtn: false, - todayHighlight: false, - weekStart: 0, - disableTouchKeyboard: false, - enableOnReadonly: true, - showOnFocus: true, - zIndexOffset: 10, - container: 'body', - immediateUpdates: false, - title: '' - }; - var locale_opts = $.fn.datepicker.locale_opts = [ - 'format', - 'rtl', - 'weekStart' - ]; - $.fn.datepicker.Constructor = Datepicker; - var dates = $.fn.datepicker.dates = { - en: { - days: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"], - daysShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"], - daysMin: ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"], - months: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"], - monthsShort: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"], - today: "Today", - clear: "Clear", - titleFormat: "MM yyyy" - } - }; - - var DPGlobal = { - modes: [ - { - clsName: 'days', - navFnc: 'Month', - navStep: 1 - }, - { - clsName: 'months', - navFnc: 'FullYear', - navStep: 1 - }, - { - clsName: 'years', - navFnc: 'FullYear', - navStep: 10 - }], - isLeapYear: function(year){ - return (((year % 4 === 0) && (year % 100 !== 0)) || (year % 400 === 0)); - }, - getDaysInMonth: function(year, month){ - return [31, (DPGlobal.isLeapYear(year) ? 29 : 28), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month]; - }, - validParts: /dd?|DD?|mm?|MM?|yy(?:yy)?/g, - nonpunctuation: /[^ -\/:-@\[\u3400-\u9fff-`{-~\t\n\r]+/g, - parseFormat: function(format){ - if (typeof format.toValue === 'function' && typeof format.toDisplay === 'function') - return format; - // IE treats \0 as a string end in inputs (truncating the value), - // so it's a bad format delimiter, anyway - var separators = format.replace(this.validParts, '\0').split('\0'), - parts = format.match(this.validParts); - if (!separators || !separators.length || !parts || parts.length === 0){ - throw new Error("Invalid date format."); - } - return {separators: separators, parts: parts}; - }, - parseDate: function(date, format, language){ - if (!date) - return undefined; - if (date instanceof Date) - return date; - if (typeof format === 'string') - format = DPGlobal.parseFormat(format); - if (format.toValue) - return format.toValue(date, format, language); - var part_re = /([\-+]\d+)([dmwy])/, - parts = date.match(/([\-+]\d+)([dmwy])/g), - fn_map = { - d: 'moveDay', - m: 'moveMonth', - w: 'moveWeek', - y: 'moveYear' - }, - part, dir, i, fn; - if (/^[\-+]\d+[dmwy]([\s,]+[\-+]\d+[dmwy])*$/.test(date)){ - date = new Date(); - for (i=0; i < parts.length; i++){ - part = part_re.exec(parts[i]); - dir = parseInt(part[1]); - fn = fn_map[part[2]]; - date = Datepicker.prototype[fn](date, dir); - } - return UTCDate(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate()); - } - parts = date && date.match(this.nonpunctuation) || []; - date = new Date(); - var parsed = {}, - setters_order = ['yyyy', 'yy', 'M', 'MM', 'm', 'mm', 'd', 'dd'], - setters_map = { - yyyy: function(d,v){ - return d.setUTCFullYear(v); - }, - yy: function(d,v){ - return d.setUTCFullYear(2000+v); - }, - m: function(d,v){ - if (isNaN(d)) - return d; - v -= 1; - while (v < 0) v += 12; - v %= 12; - d.setUTCMonth(v); - while (d.getUTCMonth() !== v) - d.setUTCDate(d.getUTCDate()-1); - return d; - }, - d: function(d,v){ - return d.setUTCDate(v); - } - }, - val, filtered; - setters_map['M'] = setters_map['MM'] = setters_map['mm'] = setters_map['m']; - setters_map['dd'] = setters_map['d']; - date = UTCToday(); - var fparts = format.parts.slice(); - // Remove noop parts - if (parts.length !== fparts.length){ - fparts = $(fparts).filter(function(i,p){ - return $.inArray(p, setters_order) !== -1; - }).toArray(); - } - // Process remainder - function match_part(){ - var m = this.slice(0, parts[i].length), - p = parts[i].slice(0, m.length); - return m.toLowerCase() === p.toLowerCase(); - } - if (parts.length === fparts.length){ - var cnt; - for (i=0, cnt = fparts.length; i < cnt; i++){ - val = parseInt(parts[i], 10); - part = fparts[i]; - if (isNaN(val)){ - switch (part){ - case 'MM': - filtered = $(dates[language].months).filter(match_part); - val = $.inArray(filtered[0], dates[language].months) + 1; - break; - case 'M': - filtered = $(dates[language].monthsShort).filter(match_part); - val = $.inArray(filtered[0], dates[language].monthsShort) + 1; - break; - } - } - parsed[part] = val; - } - var _date, s; - for (i=0; i < setters_order.length; i++){ - s = setters_order[i]; - if (s in parsed && !isNaN(parsed[s])){ - _date = new Date(date); - setters_map[s](_date, parsed[s]); - if (!isNaN(_date)) - date = _date; - } - } - } - return date; - }, - formatDate: function(date, format, language){ - if (!date) - return ''; - if (typeof format === 'string') - format = DPGlobal.parseFormat(format); - if (format.toDisplay) - return format.toDisplay(date, format, language); - var val = { - d: date.getUTCDate(), - D: dates[language].daysShort[date.getUTCDay()], - DD: dates[language].days[date.getUTCDay()], - m: date.getUTCMonth() + 1, - M: dates[language].monthsShort[date.getUTCMonth()], - MM: dates[language].months[date.getUTCMonth()], - yy: date.getUTCFullYear().toString().substring(2), - yyyy: date.getUTCFullYear() - }; - val.dd = (val.d < 10 ? '0' : '') + val.d; - val.mm = (val.m < 10 ? '0' : '') + val.m; - date = []; - var seps = $.extend([], format.separators); - for (var i=0, cnt = format.parts.length; i <= cnt; i++){ - if (seps.length) - date.push(seps.shift()); - date.push(val[format.parts[i]]); - } - return date.join(''); - }, - headTemplate: ''+ - ''+ - ''+ - ''+ - ''+ - '«'+ - ''+ - '»'+ - ''+ - '', - contTemplate: '', - footTemplate: ''+ - ''+ - ''+ - ''+ - ''+ - ''+ - ''+ - '' - }; - DPGlobal.template = '
'+ - '
'+ - ''+ - DPGlobal.headTemplate+ - ''+ - DPGlobal.footTemplate+ - '
'+ - '
'+ - '
'+ - ''+ - DPGlobal.headTemplate+ - DPGlobal.contTemplate+ - DPGlobal.footTemplate+ - '
'+ - '
'+ - '
'+ - ''+ - DPGlobal.headTemplate+ - DPGlobal.contTemplate+ - DPGlobal.footTemplate+ - '
'+ - '
'+ - '
'; - - $.fn.datepicker.DPGlobal = DPGlobal; - - - /* DATEPICKER NO CONFLICT - * =================== */ - - $.fn.datepicker.noConflict = function(){ - $.fn.datepicker = old; - return this; - }; - - /* DATEPICKER VERSION - * =================== */ - $.fn.datepicker.version = '1.5.1'; - - /* DATEPICKER DATA-API - * ================== */ - - $(document).on( - 'focus.datepicker.data-api click.datepicker.data-api', - '[data-provide="datepicker"]', - function(e){ - var $this = $(this); - if ($this.data('datepicker')) - return; - e.preventDefault(); - // component click requires us to explicitly show it - datepickerPlugin.call($this, 'show'); - } - ); - $(function(){ - datepickerPlugin.call($('[data-provide="datepicker-inline"]')); - }); - -})); + return UTCDate( + date.getUTCFullYear(), + date.getUTCMonth(), + date.getUTCDate() + ) + } + parts = (date && date.match(this.nonpunctuation)) || [] + date = new Date() + const parsed = {}; + const setters_order = ['yyyy', 'yy', 'M', 'MM', 'm', 'mm', 'd', 'dd']; + const setters_map = { + yyyy: function(d, v) { + return d.setUTCFullYear(v) + }, + yy: function(d, v) { + return d.setUTCFullYear(2000 + v) + }, + m: function(d, v) { + if (isNaN(d)) return d + v -= 1 + while (v < 0) v += 12 + v %= 12 + d.setUTCMonth(v) + while (d.getUTCMonth() !== v) d.setUTCDate(d.getUTCDate() - 1) + return d + }, + d: function(d, v) { + return d.setUTCDate(v) + } + }; + let val; + let filtered + setters_map.M = setters_map.MM = setters_map.mm = + setters_map.m + setters_map.dd = setters_map.d + date = UTCToday() + let fparts = format.parts.slice() + // Remove noop parts + if (parts.length !== fparts.length) { + fparts = $(fparts) + .filter(function(i, p) { + return $.inArray(p, setters_order) !== -1 + }) + .toArray() + } + // Process remainder + function match_part() { + const m = this.slice(0, parts[i].length); + const p = parts[i].slice(0, m.length) + return m.toLowerCase() === p.toLowerCase() + } + if (parts.length === fparts.length) { + let cnt + for (i = 0, cnt = fparts.length; i < cnt; i++) { + val = parseInt(parts[i], 10) + part = fparts[i] + if (isNaN(val)) { + switch (part) { + case 'MM': + filtered = $(dates[language].months).filter(match_part) + val = $.inArray(filtered[0], dates[language].months) + 1 + break + case 'M': + filtered = $(dates[language].monthsShort).filter(match_part) + val = $.inArray(filtered[0], dates[language].monthsShort) + 1 + break + } + } + parsed[part] = val + } + let _date, s + for (i = 0; i < setters_order.length; i++) { + s = setters_order[i] + if (s in parsed && !isNaN(parsed[s])) { + _date = new Date(date) + setters_map[s](_date, parsed[s]) + if (!isNaN(_date)) date = _date + } + } + } + return date + }, + formatDate: function(date, format, language) { + if (!date) return '' + if (typeof format === 'string') format = DPGlobal.parseFormat(format) + if (format.toDisplay) return format.toDisplay(date, format, language) + const val = { + d: date.getUTCDate(), + D: dates[language].daysShort[date.getUTCDay()], + DD: dates[language].days[date.getUTCDay()], + m: date.getUTCMonth() + 1, + M: dates[language].monthsShort[date.getUTCMonth()], + MM: dates[language].months[date.getUTCMonth()], + yy: date + .getUTCFullYear() + .toString() + .substring(2), + yyyy: date.getUTCFullYear() + } + val.dd = (val.d < 10 ? '0' : '') + val.d + val.mm = (val.m < 10 ? '0' : '') + val.m + date = [] + const seps = $.extend([], format.separators) + for (let i = 0, cnt = format.parts.length; i <= cnt; i++) { + if (seps.length) date.push(seps.shift()) + date.push(val[format.parts[i]]) + } + return date.join('') + }, + headTemplate: + '' + + '' + + '' + + '' + + '' + + '«' + + '' + + '»' + + '' + + '', + contTemplate: '', + footTemplate: + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + } + DPGlobal.template = + '
' + + '
' + + '' + + DPGlobal.headTemplate + + '' + + DPGlobal.footTemplate + + '
' + + '
' + + '
' + + '' + + DPGlobal.headTemplate + + DPGlobal.contTemplate + + DPGlobal.footTemplate + + '
' + + '
' + + '
' + + '' + + DPGlobal.headTemplate + + DPGlobal.contTemplate + + DPGlobal.footTemplate + + '
' + + '
' + + '
' + + $.fn.datepicker.DPGlobal = DPGlobal + + /* DATEPICKER NO CONFLICT + * =================== */ + + $.fn.datepicker.noConflict = function() { + $.fn.datepicker = old + return this + } + + /* DATEPICKER VERSION + * =================== */ + $.fn.datepicker.version = '1.5.1' + + /* DATEPICKER DATA-API + * ================== */ + + $(document).on( + 'focus.datepicker.data-api click.datepicker.data-api', + '[data-provide="datepicker"]', + function(e) { + const $this = $(this) + if ($this.data('datepicker')) return + e.preventDefault() + // component click requires us to explicitly show it + datepickerPlugin.call($this, 'show') + } + ) + $(function() { + datepickerPlugin.call($('[data-provide="datepicker-inline"]')) + }) +}) diff --git a/public/js/bootstrap.min.js b/public/js/bootstrap.min.js index c8f82e592..9864852dd 100644 --- a/public/js/bootstrap.min.js +++ b/public/js/bootstrap.min.js @@ -3,5 +3,1657 @@ * Copyright 2011-2015 Twitter, Inc. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) */ -if("undefined"==typeof jQuery)throw new Error("Bootstrap's JavaScript requires jQuery");+function(a){"use strict";var b=a.fn.jquery.split(" ")[0].split(".");if(b[0]<2&&b[1]<9||1==b[0]&&9==b[1]&&b[2]<1)throw new Error("Bootstrap's JavaScript requires jQuery version 1.9.1 or higher")}(jQuery),+function(a){"use strict";function b(){var a=document.createElement("bootstrap"),b={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"};for(var c in b)if(void 0!==a.style[c])return{end:b[c]};return!1}a.fn.emulateTransitionEnd=function(b){var c=!1,d=this;a(this).one("bsTransitionEnd",function(){c=!0});var e=function(){c||a(d).trigger(a.support.transition.end)};return setTimeout(e,b),this},a(function(){a.support.transition=b(),a.support.transition&&(a.event.special.bsTransitionEnd={bindType:a.support.transition.end,delegateType:a.support.transition.end,handle:function(b){return a(b.target).is(this)?b.handleObj.handler.apply(this,arguments):void 0}})})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var c=a(this),e=c.data("bs.alert");e||c.data("bs.alert",e=new d(this)),"string"==typeof b&&e[b].call(c)})}var c='[data-dismiss="alert"]',d=function(b){a(b).on("click",c,this.close)};d.VERSION="3.3.4",d.TRANSITION_DURATION=150,d.prototype.close=function(b){function c(){g.detach().trigger("closed.bs.alert").remove()}var e=a(this),f=e.attr("data-target");f||(f=e.attr("href"),f=f&&f.replace(/.*(?=#[^\s]*$)/,""));var g=a(f);b&&b.preventDefault(),g.length||(g=e.closest(".alert")),g.trigger(b=a.Event("close.bs.alert")),b.isDefaultPrevented()||(g.removeClass("in"),a.support.transition&&g.hasClass("fade")?g.one("bsTransitionEnd",c).emulateTransitionEnd(d.TRANSITION_DURATION):c())};var e=a.fn.alert;a.fn.alert=b,a.fn.alert.Constructor=d,a.fn.alert.noConflict=function(){return a.fn.alert=e,this},a(document).on("click.bs.alert.data-api",c,d.prototype.close)}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.button"),f="object"==typeof b&&b;e||d.data("bs.button",e=new c(this,f)),"toggle"==b?e.toggle():b&&e.setState(b)})}var c=function(b,d){this.$element=a(b),this.options=a.extend({},c.DEFAULTS,d),this.isLoading=!1};c.VERSION="3.3.4",c.DEFAULTS={loadingText:"loading..."},c.prototype.setState=function(b){var c="disabled",d=this.$element,e=d.is("input")?"val":"html",f=d.data();b+="Text",null==f.resetText&&d.data("resetText",d[e]()),setTimeout(a.proxy(function(){d[e](null==f[b]?this.options[b]:f[b]),"loadingText"==b?(this.isLoading=!0,d.addClass(c).attr(c,c)):this.isLoading&&(this.isLoading=!1,d.removeClass(c).removeAttr(c))},this),0)},c.prototype.toggle=function(){var a=!0,b=this.$element.closest('[data-toggle="buttons"]');if(b.length){var c=this.$element.find("input");"radio"==c.prop("type")&&(c.prop("checked")&&this.$element.hasClass("active")?a=!1:b.find(".active").removeClass("active")),a&&c.prop("checked",!this.$element.hasClass("active")).trigger("change")}else this.$element.attr("aria-pressed",!this.$element.hasClass("active"));a&&this.$element.toggleClass("active")};var d=a.fn.button;a.fn.button=b,a.fn.button.Constructor=c,a.fn.button.noConflict=function(){return a.fn.button=d,this},a(document).on("click.bs.button.data-api",'[data-toggle^="button"]',function(c){var d=a(c.target);d.hasClass("btn")||(d=d.closest(".btn")),b.call(d,"toggle"),c.preventDefault()}).on("focus.bs.button.data-api blur.bs.button.data-api",'[data-toggle^="button"]',function(b){a(b.target).closest(".btn").toggleClass("focus",/^focus(in)?$/.test(b.type))})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.carousel"),f=a.extend({},c.DEFAULTS,d.data(),"object"==typeof b&&b),g="string"==typeof b?b:f.slide;e||d.data("bs.carousel",e=new c(this,f)),"number"==typeof b?e.to(b):g?e[g]():f.interval&&e.pause().cycle()})}var c=function(b,c){this.$element=a(b),this.$indicators=this.$element.find(".carousel-indicators"),this.options=c,this.paused=null,this.sliding=null,this.interval=null,this.$active=null,this.$items=null,this.options.keyboard&&this.$element.on("keydown.bs.carousel",a.proxy(this.keydown,this)),"hover"==this.options.pause&&!("ontouchstart"in document.documentElement)&&this.$element.on("mouseenter.bs.carousel",a.proxy(this.pause,this)).on("mouseleave.bs.carousel",a.proxy(this.cycle,this))};c.VERSION="3.3.4",c.TRANSITION_DURATION=600,c.DEFAULTS={interval:5e3,pause:"hover",wrap:!0,keyboard:!0},c.prototype.keydown=function(a){if(!/input|textarea/i.test(a.target.tagName)){switch(a.which){case 37:this.prev();break;case 39:this.next();break;default:return}a.preventDefault()}},c.prototype.cycle=function(b){return b||(this.paused=!1),this.interval&&clearInterval(this.interval),this.options.interval&&!this.paused&&(this.interval=setInterval(a.proxy(this.next,this),this.options.interval)),this},c.prototype.getItemIndex=function(a){return this.$items=a.parent().children(".item"),this.$items.index(a||this.$active)},c.prototype.getItemForDirection=function(a,b){var c=this.getItemIndex(b),d="prev"==a&&0===c||"next"==a&&c==this.$items.length-1;if(d&&!this.options.wrap)return b;var e="prev"==a?-1:1,f=(c+e)%this.$items.length;return this.$items.eq(f)},c.prototype.to=function(a){var b=this,c=this.getItemIndex(this.$active=this.$element.find(".item.active"));return a>this.$items.length-1||0>a?void 0:this.sliding?this.$element.one("slid.bs.carousel",function(){b.to(a)}):c==a?this.pause().cycle():this.slide(a>c?"next":"prev",this.$items.eq(a))},c.prototype.pause=function(b){return b||(this.paused=!0),this.$element.find(".next, .prev").length&&a.support.transition&&(this.$element.trigger(a.support.transition.end),this.cycle(!0)),this.interval=clearInterval(this.interval),this},c.prototype.next=function(){return this.sliding?void 0:this.slide("next")},c.prototype.prev=function(){return this.sliding?void 0:this.slide("prev")},c.prototype.slide=function(b,d){var e=this.$element.find(".item.active"),f=d||this.getItemForDirection(b,e),g=this.interval,h="next"==b?"left":"right",i=this;if(f.hasClass("active"))return this.sliding=!1;var j=f[0],k=a.Event("slide.bs.carousel",{relatedTarget:j,direction:h});if(this.$element.trigger(k),!k.isDefaultPrevented()){if(this.sliding=!0,g&&this.pause(),this.$indicators.length){this.$indicators.find(".active").removeClass("active");var l=a(this.$indicators.children()[this.getItemIndex(f)]);l&&l.addClass("active")}var m=a.Event("slid.bs.carousel",{relatedTarget:j,direction:h});return a.support.transition&&this.$element.hasClass("slide")?(f.addClass(b),f[0].offsetWidth,e.addClass(h),f.addClass(h),e.one("bsTransitionEnd",function(){f.removeClass([b,h].join(" ")).addClass("active"),e.removeClass(["active",h].join(" ")),i.sliding=!1,setTimeout(function(){i.$element.trigger(m)},0)}).emulateTransitionEnd(c.TRANSITION_DURATION)):(e.removeClass("active"),f.addClass("active"),this.sliding=!1,this.$element.trigger(m)),g&&this.cycle(),this}};var d=a.fn.carousel;a.fn.carousel=b,a.fn.carousel.Constructor=c,a.fn.carousel.noConflict=function(){return a.fn.carousel=d,this};var e=function(c){var d,e=a(this),f=a(e.attr("data-target")||(d=e.attr("href"))&&d.replace(/.*(?=#[^\s]+$)/,""));if(f.hasClass("carousel")){var g=a.extend({},f.data(),e.data()),h=e.attr("data-slide-to");h&&(g.interval=!1),b.call(f,g),h&&f.data("bs.carousel").to(h),c.preventDefault()}};a(document).on("click.bs.carousel.data-api","[data-slide]",e).on("click.bs.carousel.data-api","[data-slide-to]",e),a(window).on("load",function(){a('[data-ride="carousel"]').each(function(){var c=a(this);b.call(c,c.data())})})}(jQuery),+function(a){"use strict";function b(b){var c,d=b.attr("data-target")||(c=b.attr("href"))&&c.replace(/.*(?=#[^\s]+$)/,"");return a(d)}function c(b){return this.each(function(){var c=a(this),e=c.data("bs.collapse"),f=a.extend({},d.DEFAULTS,c.data(),"object"==typeof b&&b);!e&&f.toggle&&/show|hide/.test(b)&&(f.toggle=!1),e||c.data("bs.collapse",e=new d(this,f)),"string"==typeof b&&e[b]()})}var d=function(b,c){this.$element=a(b),this.options=a.extend({},d.DEFAULTS,c),this.$trigger=a('[data-toggle="collapse"][href="#'+b.id+'"],[data-toggle="collapse"][data-target="#'+b.id+'"]'),this.transitioning=null,this.options.parent?this.$parent=this.getParent():this.addAriaAndCollapsedClass(this.$element,this.$trigger),this.options.toggle&&this.toggle()};d.VERSION="3.3.4",d.TRANSITION_DURATION=350,d.DEFAULTS={toggle:!0},d.prototype.dimension=function(){var a=this.$element.hasClass("width");return a?"width":"height"},d.prototype.show=function(){if(!this.transitioning&&!this.$element.hasClass("in")){var b,e=this.$parent&&this.$parent.children(".panel").children(".in, .collapsing");if(!(e&&e.length&&(b=e.data("bs.collapse"),b&&b.transitioning))){var f=a.Event("show.bs.collapse");if(this.$element.trigger(f),!f.isDefaultPrevented()){e&&e.length&&(c.call(e,"hide"),b||e.data("bs.collapse",null));var g=this.dimension();this.$element.removeClass("collapse").addClass("collapsing")[g](0).attr("aria-expanded",!0),this.$trigger.removeClass("collapsed").attr("aria-expanded",!0),this.transitioning=1;var h=function(){this.$element.removeClass("collapsing").addClass("collapse in")[g](""),this.transitioning=0,this.$element.trigger("shown.bs.collapse")};if(!a.support.transition)return h.call(this);var i=a.camelCase(["scroll",g].join("-"));this.$element.one("bsTransitionEnd",a.proxy(h,this)).emulateTransitionEnd(d.TRANSITION_DURATION)[g](this.$element[0][i])}}}},d.prototype.hide=function(){if(!this.transitioning&&this.$element.hasClass("in")){var b=a.Event("hide.bs.collapse");if(this.$element.trigger(b),!b.isDefaultPrevented()){var c=this.dimension();this.$element[c](this.$element[c]())[0].offsetHeight,this.$element.addClass("collapsing").removeClass("collapse in").attr("aria-expanded",!1),this.$trigger.addClass("collapsed").attr("aria-expanded",!1),this.transitioning=1;var e=function(){this.transitioning=0,this.$element.removeClass("collapsing").addClass("collapse").trigger("hidden.bs.collapse")};return a.support.transition?void this.$element[c](0).one("bsTransitionEnd",a.proxy(e,this)).emulateTransitionEnd(d.TRANSITION_DURATION):e.call(this)}}},d.prototype.toggle=function(){this[this.$element.hasClass("in")?"hide":"show"]()},d.prototype.getParent=function(){return a(this.options.parent).find('[data-toggle="collapse"][data-parent="'+this.options.parent+'"]').each(a.proxy(function(c,d){var e=a(d);this.addAriaAndCollapsedClass(b(e),e)},this)).end()},d.prototype.addAriaAndCollapsedClass=function(a,b){var c=a.hasClass("in");a.attr("aria-expanded",c),b.toggleClass("collapsed",!c).attr("aria-expanded",c)};var e=a.fn.collapse;a.fn.collapse=c,a.fn.collapse.Constructor=d,a.fn.collapse.noConflict=function(){return a.fn.collapse=e,this},a(document).on("click.bs.collapse.data-api",'[data-toggle="collapse"]',function(d){var e=a(this);e.attr("data-target")||d.preventDefault();var f=b(e),g=f.data("bs.collapse"),h=g?"toggle":e.data();c.call(f,h)})}(jQuery),+function(a){"use strict";function b(b){b&&3===b.which||(a(e).remove(),a(f).each(function(){var d=a(this),e=c(d),f={relatedTarget:this};e.hasClass("open")&&(e.trigger(b=a.Event("hide.bs.dropdown",f)),b.isDefaultPrevented()||(d.attr("aria-expanded","false"),e.removeClass("open").trigger("hidden.bs.dropdown",f)))}))}function c(b){var c=b.attr("data-target");c||(c=b.attr("href"),c=c&&/#[A-Za-z]/.test(c)&&c.replace(/.*(?=#[^\s]*$)/,""));var d=c&&a(c);return d&&d.length?d:b.parent()}function d(b){return this.each(function(){var c=a(this),d=c.data("bs.dropdown");d||c.data("bs.dropdown",d=new g(this)),"string"==typeof b&&d[b].call(c)})}var e=".dropdown-backdrop",f='[data-toggle="dropdown"]',g=function(b){a(b).on("click.bs.dropdown",this.toggle)};g.VERSION="3.3.4",g.prototype.toggle=function(d){var e=a(this);if(!e.is(".disabled, :disabled")){var f=c(e),g=f.hasClass("open");if(b(),!g){"ontouchstart"in document.documentElement&&!f.closest(".navbar-nav").length&&a('',trigger:"hover focus",title:"",delay:0,html:!1,container:!1,viewport:{selector:"body",padding:0}},c.prototype.init=function(b,c,d){if(this.enabled=!0,this.type=b,this.$element=a(c),this.options=this.getOptions(d),this.$viewport=this.options.viewport&&a(this.options.viewport.selector||this.options.viewport),this.$element[0]instanceof document.constructor&&!this.options.selector)throw new Error("`selector` option must be specified when initializing "+this.type+" on the window.document object!");for(var e=this.options.trigger.split(" "),f=e.length;f--;){var g=e[f];if("click"==g)this.$element.on("click."+this.type,this.options.selector,a.proxy(this.toggle,this));else if("manual"!=g){var h="hover"==g?"mouseenter":"focusin",i="hover"==g?"mouseleave":"focusout";this.$element.on(h+"."+this.type,this.options.selector,a.proxy(this.enter,this)),this.$element.on(i+"."+this.type,this.options.selector,a.proxy(this.leave,this))}}this.options.selector?this._options=a.extend({},this.options,{trigger:"manual",selector:""}):this.fixTitle()},c.prototype.getDefaults=function(){return c.DEFAULTS},c.prototype.getOptions=function(b){return b=a.extend({},this.getDefaults(),this.$element.data(),b),b.delay&&"number"==typeof b.delay&&(b.delay={show:b.delay,hide:b.delay}),b},c.prototype.getDelegateOptions=function(){var b={},c=this.getDefaults();return this._options&&a.each(this._options,function(a,d){c[a]!=d&&(b[a]=d)}),b},c.prototype.enter=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget).data("bs."+this.type);return c&&c.$tip&&c.$tip.is(":visible")?void(c.hoverState="in"):(c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c)),clearTimeout(c.timeout),c.hoverState="in",c.options.delay&&c.options.delay.show?void(c.timeout=setTimeout(function(){"in"==c.hoverState&&c.show()},c.options.delay.show)):c.show())},c.prototype.leave=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget).data("bs."+this.type);return c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c)),clearTimeout(c.timeout),c.hoverState="out",c.options.delay&&c.options.delay.hide?void(c.timeout=setTimeout(function(){"out"==c.hoverState&&c.hide()},c.options.delay.hide)):c.hide()},c.prototype.show=function(){var b=a.Event("show.bs."+this.type);if(this.hasContent()&&this.enabled){this.$element.trigger(b);var d=a.contains(this.$element[0].ownerDocument.documentElement,this.$element[0]);if(b.isDefaultPrevented()||!d)return;var e=this,f=this.tip(),g=this.getUID(this.type);this.setContent(),f.attr("id",g),this.$element.attr("aria-describedby",g),this.options.animation&&f.addClass("fade");var h="function"==typeof this.options.placement?this.options.placement.call(this,f[0],this.$element[0]):this.options.placement,i=/\s?auto?\s?/i,j=i.test(h);j&&(h=h.replace(i,"")||"top"),f.detach().css({top:0,left:0,display:"block"}).addClass(h).data("bs."+this.type,this),this.options.container?f.appendTo(this.options.container):f.insertAfter(this.$element);var k=this.getPosition(),l=f[0].offsetWidth,m=f[0].offsetHeight;if(j){var n=h,o=this.options.container?a(this.options.container):this.$element.parent(),p=this.getPosition(o);h="bottom"==h&&k.bottom+m>p.bottom?"top":"top"==h&&k.top-mp.width?"left":"left"==h&&k.left-lg.top+g.height&&(e.top=g.top+g.height-i)}else{var j=b.left-f,k=b.left+f+c;jg.width&&(e.left=g.left+g.width-k)}return e},c.prototype.getTitle=function(){var a,b=this.$element,c=this.options;return a=b.attr("data-original-title")||("function"==typeof c.title?c.title.call(b[0]):c.title)},c.prototype.getUID=function(a){do a+=~~(1e6*Math.random());while(document.getElementById(a));return a},c.prototype.tip=function(){return this.$tip=this.$tip||a(this.options.template)},c.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".tooltip-arrow")},c.prototype.enable=function(){this.enabled=!0},c.prototype.disable=function(){this.enabled=!1},c.prototype.toggleEnabled=function(){this.enabled=!this.enabled},c.prototype.toggle=function(b){var c=this;b&&(c=a(b.currentTarget).data("bs."+this.type),c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c))),c.tip().hasClass("in")?c.leave(c):c.enter(c)},c.prototype.destroy=function(){var a=this;clearTimeout(this.timeout),this.hide(function(){a.$element.off("."+a.type).removeData("bs."+a.type)})};var d=a.fn.tooltip;a.fn.tooltip=b,a.fn.tooltip.Constructor=c,a.fn.tooltip.noConflict=function(){return a.fn.tooltip=d,this}}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.popover"),f="object"==typeof b&&b;(e||!/destroy|hide/.test(b))&&(e||d.data("bs.popover",e=new c(this,f)),"string"==typeof b&&e[b]())})}var c=function(a,b){this.init("popover",a,b)};if(!a.fn.tooltip)throw new Error("Popover requires tooltip.js");c.VERSION="3.3.4",c.DEFAULTS=a.extend({},a.fn.tooltip.Constructor.DEFAULTS,{placement:"right",trigger:"click",content:"",template:''}),c.prototype=a.extend({},a.fn.tooltip.Constructor.prototype),c.prototype.constructor=c,c.prototype.getDefaults=function(){return c.DEFAULTS},c.prototype.setContent=function(){var a=this.tip(),b=this.getTitle(),c=this.getContent();a.find(".popover-title")[this.options.html?"html":"text"](b),a.find(".popover-content").children().detach().end()[this.options.html?"string"==typeof c?"html":"append":"text"](c),a.removeClass("fade top bottom left right in"),a.find(".popover-title").html()||a.find(".popover-title").hide()},c.prototype.hasContent=function(){return this.getTitle()||this.getContent()},c.prototype.getContent=function(){var a=this.$element,b=this.options;return a.attr("data-content")||("function"==typeof b.content?b.content.call(a[0]):b.content)},c.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".arrow")};var d=a.fn.popover;a.fn.popover=b,a.fn.popover.Constructor=c,a.fn.popover.noConflict=function(){return a.fn.popover=d,this}}(jQuery),+function(a){"use strict";function b(c,d){this.$body=a(document.body),this.$scrollElement=a(a(c).is(document.body)?window:c),this.options=a.extend({},b.DEFAULTS,d),this.selector=(this.options.target||"")+" .nav li > a",this.offsets=[],this.targets=[],this.activeTarget=null,this.scrollHeight=0,this.$scrollElement.on("scroll.bs.scrollspy",a.proxy(this.process,this)),this.refresh(),this.process()}function c(c){return this.each(function(){var d=a(this),e=d.data("bs.scrollspy"),f="object"==typeof c&&c;e||d.data("bs.scrollspy",e=new b(this,f)),"string"==typeof c&&e[c]()})}b.VERSION="3.3.4",b.DEFAULTS={offset:10},b.prototype.getScrollHeight=function(){return this.$scrollElement[0].scrollHeight||Math.max(this.$body[0].scrollHeight,document.documentElement.scrollHeight)},b.prototype.refresh=function(){var b=this,c="offset",d=0;this.offsets=[],this.targets=[],this.scrollHeight=this.getScrollHeight(),a.isWindow(this.$scrollElement[0])||(c="position",d=this.$scrollElement.scrollTop()),this.$body.find(this.selector).map(function(){var b=a(this),e=b.data("target")||b.attr("href"),f=/^#./.test(e)&&a(e);return f&&f.length&&f.is(":visible")&&[[f[c]().top+d,e]]||null}).sort(function(a,b){return a[0]-b[0]}).each(function(){b.offsets.push(this[0]),b.targets.push(this[1])})},b.prototype.process=function(){var a,b=this.$scrollElement.scrollTop()+this.options.offset,c=this.getScrollHeight(),d=this.options.offset+c-this.$scrollElement.height(),e=this.offsets,f=this.targets,g=this.activeTarget;if(this.scrollHeight!=c&&this.refresh(),b>=d)return g!=(a=f[f.length-1])&&this.activate(a);if(g&&b=e[a]&&(void 0===e[a+1]||b .dropdown-menu > .active").removeClass("active").end().find('[data-toggle="tab"]').attr("aria-expanded",!1),b.addClass("active").find('[data-toggle="tab"]').attr("aria-expanded",!0),h?(b[0].offsetWidth,b.addClass("in")):b.removeClass("fade"),b.parent(".dropdown-menu").length&&b.closest("li.dropdown").addClass("active").end().find('[data-toggle="tab"]').attr("aria-expanded",!0),e&&e()}var g=d.find("> .active"),h=e&&a.support.transition&&(g.length&&g.hasClass("fade")||!!d.find("> .fade").length);g.length&&h?g.one("bsTransitionEnd",f).emulateTransitionEnd(c.TRANSITION_DURATION):f(),g.removeClass("in")};var d=a.fn.tab;a.fn.tab=b,a.fn.tab.Constructor=c,a.fn.tab.noConflict=function(){return a.fn.tab=d,this};var e=function(c){c.preventDefault(),b.call(a(this),"show")};a(document).on("click.bs.tab.data-api",'[data-toggle="tab"]',e).on("click.bs.tab.data-api",'[data-toggle="pill"]',e)}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.affix"),f="object"==typeof b&&b;e||d.data("bs.affix",e=new c(this,f)),"string"==typeof b&&e[b]()})}var c=function(b,d){this.options=a.extend({},c.DEFAULTS,d),this.$target=a(this.options.target).on("scroll.bs.affix.data-api",a.proxy(this.checkPosition,this)).on("click.bs.affix.data-api",a.proxy(this.checkPositionWithEventLoop,this)),this.$element=a(b),this.affixed=null,this.unpin=null,this.pinnedOffset=null,this.checkPosition()};c.VERSION="3.3.4",c.RESET="affix affix-top affix-bottom",c.DEFAULTS={offset:0,target:window},c.prototype.getState=function(a,b,c,d){var e=this.$target.scrollTop(),f=this.$element.offset(),g=this.$target.height();if(null!=c&&"top"==this.affixed)return c>e?"top":!1;if("bottom"==this.affixed)return null!=c?e+this.unpin<=f.top?!1:"bottom":a-d>=e+g?!1:"bottom";var h=null==this.affixed,i=h?e:f.top,j=h?g:b;return null!=c&&c>=e?"top":null!=d&&i+j>=a-d?"bottom":!1},c.prototype.getPinnedOffset=function(){if(this.pinnedOffset)return this.pinnedOffset;this.$element.removeClass(c.RESET).addClass("affix");var a=this.$target.scrollTop(),b=this.$element.offset();return this.pinnedOffset=b.top-a},c.prototype.checkPositionWithEventLoop=function(){setTimeout(a.proxy(this.checkPosition,this),1)},c.prototype.checkPosition=function(){if(this.$element.is(":visible")){var b=this.$element.height(),d=this.options.offset,e=d.top,f=d.bottom,g=a(document.body).height();"object"!=typeof d&&(f=e=d),"function"==typeof e&&(e=d.top(this.$element)),"function"==typeof f&&(f=d.bottom(this.$element));var h=this.getState(g,b,e,f);if(this.affixed!=h){null!=this.unpin&&this.$element.css("top","");var i="affix"+(h?"-"+h:""),j=a.Event(i+".bs.affix");if(this.$element.trigger(j),j.isDefaultPrevented())return;this.affixed=h,this.unpin="bottom"==h?this.getPinnedOffset():null,this.$element.removeClass(c.RESET).addClass(i).trigger(i.replace("affix","affixed")+".bs.affix")}"bottom"==h&&this.$element.offset({top:g-b-f})}};var d=a.fn.affix;a.fn.affix=b,a.fn.affix.Constructor=c,a.fn.affix.noConflict=function(){return a.fn.affix=d,this},a(window).on("load",function(){a('[data-spy="affix"]').each(function(){var c=a(this),d=c.data();d.offset=d.offset||{},null!=d.offsetBottom&&(d.offset.bottom=d.offsetBottom),null!=d.offsetTop&&(d.offset.top=d.offsetTop),b.call(c,d)})})}(jQuery); \ No newline at end of file +if (typeof jQuery === 'undefined') + throw new Error("Bootstrap's JavaScript requires jQuery") +;+(function(a) { + 'use strict' + const b = a.fn.jquery.split(' ')[0].split('.') + if ((b[0] < 2 && b[1] < 9) || (b[0] == 1 && b[1] == 9 && b[2] < 1)) + throw new Error( + "Bootstrap's JavaScript requires jQuery version 1.9.1 or higher" + ) +})(jQuery), + +(function(a) { + 'use strict' + function b() { + const a = document.createElement('bootstrap'); + const b = { + WebkitTransition: 'webkitTransitionEnd', + MozTransition: 'transitionend', + OTransition: 'oTransitionEnd otransitionend', + transition: 'transitionend' + } + for (const c in b) if (void 0 !== a.style[c]) return { end: b[c] } + return !1 + } + ;(a.fn.emulateTransitionEnd = function(b) { + let c = !1; + const d = this + a(this).one('bsTransitionEnd', function() { + c = !0 + }) + const e = function() { + c || a(d).trigger(a.support.transition.end) + } + return setTimeout(e, b), this + }), + a(function() { + ;(a.support.transition = b()), + a.support.transition && + (a.event.special.bsTransitionEnd = { + bindType: a.support.transition.end, + delegateType: a.support.transition.end, + handle: function(b) { + return a(b.target).is(this) + ? b.handleObj.handler.apply(this, arguments) + : void 0 + } + }) + }) + })(jQuery), + +(function(a) { + 'use strict' + function b(b) { + return this.each(function() { + const c = a(this); + let e = c.data('bs.alert') + e || c.data('bs.alert', (e = new d(this))), + typeof b === 'string' && e[b].call(c) + }) + } + const c = '[data-dismiss="alert"]'; + var d = function(b) { + a(b).on('click', c, this.close) + } + ;(d.VERSION = '3.3.4'), + (d.TRANSITION_DURATION = 150), + (d.prototype.close = function(b) { + function c() { + g.detach() + .trigger('closed.bs.alert') + .remove() + } + const e = a(this); + let f = e.attr('data-target') + f || ((f = e.attr('href')), (f = f && f.replace(/.*(?=#[^\s]*$)/, ''))) + var g = a(f) + b && b.preventDefault(), + g.length || (g = e.closest('.alert')), + g.trigger((b = a.Event('close.bs.alert'))), + b.isDefaultPrevented() || + (g.removeClass('in'), + a.support.transition && g.hasClass('fade') + ? g + .one('bsTransitionEnd', c) + .emulateTransitionEnd(d.TRANSITION_DURATION) + : c()) + }) + const e = a.fn.alert + ;(a.fn.alert = b), + (a.fn.alert.Constructor = d), + (a.fn.alert.noConflict = function() { + return (a.fn.alert = e), this + }), + a(document).on('click.bs.alert.data-api', c, d.prototype.close) + })(jQuery), + +(function(a) { + 'use strict' + function b(b) { + return this.each(function() { + const d = a(this); + let e = d.data('bs.button'); + const f = typeof b === 'object' && b + e || d.data('bs.button', (e = new c(this, f))), + b == 'toggle' ? e.toggle() : b && e.setState(b) + }) + } + var c = function(b, d) { + ;(this.$element = a(b)), + (this.options = a.extend({}, c.DEFAULTS, d)), + (this.isLoading = !1) + } + ;(c.VERSION = '3.3.4'), + (c.DEFAULTS = { loadingText: 'loading...' }), + (c.prototype.setState = function(b) { + const c = 'disabled'; + const d = this.$element; + const e = d.is('input') ? 'val' : 'html'; + const f = d.data() + ;(b += 'Text'), + f.resetText == null && d.data('resetText', d[e]()), + setTimeout( + a.proxy(function() { + d[e](f[b] == null ? this.options[b] : f[b]), + b == 'loadingText' + ? ((this.isLoading = !0), d.addClass(c).attr(c, c)) + : this.isLoading && + ((this.isLoading = !1), d.removeClass(c).removeAttr(c)) + }, this), + 0 + ) + }), + (c.prototype.toggle = function() { + let a = !0; + const b = this.$element.closest('[data-toggle="buttons"]') + if (b.length) { + const c = this.$element.find('input') + c.prop('type') == 'radio' && + (c.prop('checked') && this.$element.hasClass('active') + ? (a = !1) + : b.find('.active').removeClass('active')), + a && + c + .prop('checked', !this.$element.hasClass('active')) + .trigger('change') + } else + this.$element.attr('aria-pressed', !this.$element.hasClass('active')) + a && this.$element.toggleClass('active') + }) + const d = a.fn.button + ;(a.fn.button = b), + (a.fn.button.Constructor = c), + (a.fn.button.noConflict = function() { + return (a.fn.button = d), this + }), + a(document) + .on('click.bs.button.data-api', '[data-toggle^="button"]', function(c) { + let d = a(c.target) + d.hasClass('btn') || (d = d.closest('.btn')), + b.call(d, 'toggle'), + c.preventDefault() + }) + .on( + 'focus.bs.button.data-api blur.bs.button.data-api', + '[data-toggle^="button"]', + function(b) { + a(b.target) + .closest('.btn') + .toggleClass('focus', /^focus(in)?$/.test(b.type)) + } + ) + })(jQuery), + +(function(a) { + 'use strict' + function b(b) { + return this.each(function() { + const d = a(this); + let e = d.data('bs.carousel'); + const f = a.extend({}, c.DEFAULTS, d.data(), typeof b === 'object' && b); + const g = typeof b === 'string' ? b : f.slide + e || d.data('bs.carousel', (e = new c(this, f))), + typeof b === 'number' + ? e.to(b) + : g + ? e[g]() + : f.interval && e.pause().cycle() + }) + } + var c = function(b, c) { + ;(this.$element = a(b)), + (this.$indicators = this.$element.find('.carousel-indicators')), + (this.options = c), + (this.paused = null), + (this.sliding = null), + (this.interval = null), + (this.$active = null), + (this.$items = null), + this.options.keyboard && + this.$element.on('keydown.bs.carousel', a.proxy(this.keydown, this)), + this.options.pause == 'hover' && + !('ontouchstart' in document.documentElement) && + this.$element + .on('mouseenter.bs.carousel', a.proxy(this.pause, this)) + .on('mouseleave.bs.carousel', a.proxy(this.cycle, this)) + } + ;(c.VERSION = '3.3.4'), + (c.TRANSITION_DURATION = 600), + (c.DEFAULTS = { interval: 5e3, pause: 'hover', wrap: !0, keyboard: !0 }), + (c.prototype.keydown = function(a) { + if (!/input|textarea/i.test(a.target.tagName)) { + switch (a.which) { + case 37: + this.prev() + break + case 39: + this.next() + break + default: + return + } + a.preventDefault() + } + }), + (c.prototype.cycle = function(b) { + return ( + b || (this.paused = !1), + this.interval && clearInterval(this.interval), + this.options.interval && + !this.paused && + (this.interval = setInterval( + a.proxy(this.next, this), + this.options.interval + )), + this + ) + }), + (c.prototype.getItemIndex = function(a) { + return ( + (this.$items = a.parent().children('.item')), + this.$items.index(a || this.$active) + ) + }), + (c.prototype.getItemForDirection = function(a, b) { + const c = this.getItemIndex(b); + const d = + (a == 'prev' && c === 0) || + (a == 'next' && c == this.$items.length - 1) + if (d && !this.options.wrap) return b + const e = a == 'prev' ? -1 : 1; + const f = (c + e) % this.$items.length + return this.$items.eq(f) + }), + (c.prototype.to = function(a) { + const b = this; + const c = this.getItemIndex( + (this.$active = this.$element.find('.item.active')) + ) + return a > this.$items.length - 1 || a < 0 + ? void 0 + : this.sliding + ? this.$element.one('slid.bs.carousel', function() { + b.to(a) + }) + : c == a + ? this.pause().cycle() + : this.slide(a > c ? 'next' : 'prev', this.$items.eq(a)) + }), + (c.prototype.pause = function(b) { + return ( + b || (this.paused = !0), + this.$element.find('.next, .prev').length && + a.support.transition && + (this.$element.trigger(a.support.transition.end), this.cycle(!0)), + (this.interval = clearInterval(this.interval)), + this + ) + }), + (c.prototype.next = function() { + return this.sliding ? void 0 : this.slide('next') + }), + (c.prototype.prev = function() { + return this.sliding ? void 0 : this.slide('prev') + }), + (c.prototype.slide = function(b, d) { + const e = this.$element.find('.item.active'); + const f = d || this.getItemForDirection(b, e); + const g = this.interval; + const h = b == 'next' ? 'left' : 'right'; + const i = this + if (f.hasClass('active')) return (this.sliding = !1) + const j = f[0]; + const k = a.Event('slide.bs.carousel', { relatedTarget: j, direction: h }) + if ((this.$element.trigger(k), !k.isDefaultPrevented())) { + if ( + ((this.sliding = !0), g && this.pause(), this.$indicators.length) + ) { + this.$indicators.find('.active').removeClass('active') + const l = a(this.$indicators.children()[this.getItemIndex(f)]) + l && l.addClass('active') + } + const m = a.Event('slid.bs.carousel', { + relatedTarget: j, + direction: h + }) + return ( + a.support.transition && this.$element.hasClass('slide') + ? (f.addClass(b), + f[0].offsetWidth, + e.addClass(h), + f.addClass(h), + e + .one('bsTransitionEnd', function() { + f.removeClass([b, h].join(' ')).addClass('active'), + e.removeClass(['active', h].join(' ')), + (i.sliding = !1), + setTimeout(function() { + i.$element.trigger(m) + }, 0) + }) + .emulateTransitionEnd(c.TRANSITION_DURATION)) + : (e.removeClass('active'), + f.addClass('active'), + (this.sliding = !1), + this.$element.trigger(m)), + g && this.cycle(), + this + ) + } + }) + const d = a.fn.carousel + ;(a.fn.carousel = b), + (a.fn.carousel.Constructor = c), + (a.fn.carousel.noConflict = function() { + return (a.fn.carousel = d), this + }) + const e = function(c) { + let d; + const e = a(this); + const f = a( + e.attr('data-target') || + ((d = e.attr('href')) && d.replace(/.*(?=#[^\s]+$)/, '')) + ) + if (f.hasClass('carousel')) { + const g = a.extend({}, f.data(), e.data()); + const h = e.attr('data-slide-to') + h && (g.interval = !1), + b.call(f, g), + h && f.data('bs.carousel').to(h), + c.preventDefault() + } + } + a(document) + .on('click.bs.carousel.data-api', '[data-slide]', e) + .on('click.bs.carousel.data-api', '[data-slide-to]', e), + a(window).on('load', function() { + a('[data-ride="carousel"]').each(function() { + const c = a(this) + b.call(c, c.data()) + }) + }) + })(jQuery), + +(function(a) { + 'use strict' + function b(b) { + let c; + const d = + b.attr('data-target') || + ((c = b.attr('href')) && c.replace(/.*(?=#[^\s]+$)/, '')) + return a(d) + } + function c(b) { + return this.each(function() { + const c = a(this); + let e = c.data('bs.collapse'); + const f = a.extend({}, d.DEFAULTS, c.data(), typeof b === 'object' && b) + !e && f.toggle && /show|hide/.test(b) && (f.toggle = !1), + e || c.data('bs.collapse', (e = new d(this, f))), + typeof b === 'string' && e[b]() + }) + } + var d = function(b, c) { + ;(this.$element = a(b)), + (this.options = a.extend({}, d.DEFAULTS, c)), + (this.$trigger = a( + '[data-toggle="collapse"][href="#' + + b.id + + '"],[data-toggle="collapse"][data-target="#' + + b.id + + '"]' + )), + (this.transitioning = null), + this.options.parent + ? (this.$parent = this.getParent()) + : this.addAriaAndCollapsedClass(this.$element, this.$trigger), + this.options.toggle && this.toggle() + } + ;(d.VERSION = '3.3.4'), + (d.TRANSITION_DURATION = 350), + (d.DEFAULTS = { toggle: !0 }), + (d.prototype.dimension = function() { + const a = this.$element.hasClass('width') + return a ? 'width' : 'height' + }), + (d.prototype.show = function() { + if (!this.transitioning && !this.$element.hasClass('in')) { + let b; + const e = + this.$parent && + this.$parent.children('.panel').children('.in, .collapsing') + if ( + !( + e && + e.length && + ((b = e.data('bs.collapse')), b && b.transitioning) + ) + ) { + const f = a.Event('show.bs.collapse') + if ((this.$element.trigger(f), !f.isDefaultPrevented())) { + e && + e.length && + (c.call(e, 'hide'), b || e.data('bs.collapse', null)) + const g = this.dimension() + this.$element + .removeClass('collapse') + .addClass('collapsing') + [g](0) + .attr('aria-expanded', !0), + this.$trigger + .removeClass('collapsed') + .attr('aria-expanded', !0), + (this.transitioning = 1) + const h = function() { + this.$element + .removeClass('collapsing') + .addClass('collapse in') + [g](''), + (this.transitioning = 0), + this.$element.trigger('shown.bs.collapse') + } + if (!a.support.transition) return h.call(this) + const i = a.camelCase(['scroll', g].join('-')) + this.$element + .one('bsTransitionEnd', a.proxy(h, this)) + .emulateTransitionEnd(d.TRANSITION_DURATION) + [g](this.$element[0][i]) + } + } + } + }), + (d.prototype.hide = function() { + if (!this.transitioning && this.$element.hasClass('in')) { + const b = a.Event('hide.bs.collapse') + if ((this.$element.trigger(b), !b.isDefaultPrevented())) { + const c = this.dimension() + this.$element[c](this.$element[c]())[0].offsetHeight, + this.$element + .addClass('collapsing') + .removeClass('collapse in') + .attr('aria-expanded', !1), + this.$trigger.addClass('collapsed').attr('aria-expanded', !1), + (this.transitioning = 1) + const e = function() { + ;(this.transitioning = 0), + this.$element + .removeClass('collapsing') + .addClass('collapse') + .trigger('hidden.bs.collapse') + } + return a.support.transition + ? void this.$element[c](0) + .one('bsTransitionEnd', a.proxy(e, this)) + .emulateTransitionEnd(d.TRANSITION_DURATION) + : e.call(this) + } + } + }), + (d.prototype.toggle = function() { + this[this.$element.hasClass('in') ? 'hide' : 'show']() + }), + (d.prototype.getParent = function() { + return a(this.options.parent) + .find( + '[data-toggle="collapse"][data-parent="' + + this.options.parent + + '"]' + ) + .each( + a.proxy(function(c, d) { + const e = a(d) + this.addAriaAndCollapsedClass(b(e), e) + }, this) + ) + .end() + }), + (d.prototype.addAriaAndCollapsedClass = function(a, b) { + const c = a.hasClass('in') + a.attr('aria-expanded', c), + b.toggleClass('collapsed', !c).attr('aria-expanded', c) + }) + const e = a.fn.collapse + ;(a.fn.collapse = c), + (a.fn.collapse.Constructor = d), + (a.fn.collapse.noConflict = function() { + return (a.fn.collapse = e), this + }), + a(document).on( + 'click.bs.collapse.data-api', + '[data-toggle="collapse"]', + function(d) { + const e = a(this) + e.attr('data-target') || d.preventDefault() + const f = b(e); + const g = f.data('bs.collapse'); + const h = g ? 'toggle' : e.data() + c.call(f, h) + } + ) + })(jQuery), + +(function(a) { + 'use strict' + function b(b) { + ;(b && b.which === 3) || + (a(e).remove(), + a(f).each(function() { + const d = a(this); + const e = c(d); + const f = { relatedTarget: this } + e.hasClass('open') && + (e.trigger((b = a.Event('hide.bs.dropdown', f))), + b.isDefaultPrevented() || + (d.attr('aria-expanded', 'false'), + e.removeClass('open').trigger('hidden.bs.dropdown', f))) + })) + } + function c(b) { + let c = b.attr('data-target') + c || + ((c = b.attr('href')), + (c = c && /#[A-Za-z]/.test(c) && c.replace(/.*(?=#[^\s]*$)/, ''))) + const d = c && a(c) + return d && d.length ? d : b.parent() + } + function d(b) { + return this.each(function() { + const c = a(this); + let d = c.data('bs.dropdown') + d || c.data('bs.dropdown', (d = new g(this))), + typeof b === 'string' && d[b].call(c) + }) + } + var e = '.dropdown-backdrop'; + var f = '[data-toggle="dropdown"]'; + var g = function(b) { + a(b).on('click.bs.dropdown', this.toggle) + } + ;(g.VERSION = '3.3.4'), + (g.prototype.toggle = function(d) { + const e = a(this) + if (!e.is('.disabled, :disabled')) { + const f = c(e); + const g = f.hasClass('open') + if ((b(), !g)) { + 'ontouchstart' in document.documentElement && + !f.closest('.navbar-nav').length && + a('