├── .docker ├── elasticsearch │ ├── Dockerfile │ └── config │ │ ├── elasticsearch.yml │ │ └── logging.yml ├── kibana │ └── Dockerfile ├── logstash │ ├── Dockerfile │ ├── conf │ │ ├── logstash.conf │ │ └── template.json │ └── connector │ │ └── mysql-connector-java-5.1.36-bin.jar ├── mysql │ └── mysqld.cnf └── redis │ └── redis.conf ├── .gitignore ├── README.md ├── app.js ├── bin └── www ├── data ├── .gitignore ├── mysql-data │ └── .gitkeep ├── nodes │ └── .gitkeep └── sample_data.sql ├── docker-compose.yml ├── libraries ├── database.js ├── elasticsearch.js ├── redis-client.js └── sample.database.js ├── node-es-example.sublime-project ├── package-lock.json ├── package.json ├── public └── stylesheets │ ├── style.css │ └── style.less ├── push-all-product-to-queue.js ├── queue-listener.js ├── routes ├── categories.js ├── graphs.js ├── index.js ├── products.js └── search.js ├── sample.env ├── services ├── categorySearchService.js ├── categoryService.js ├── productGraphService.js ├── productSearchService.js └── productService.js └── views ├── categories.twig ├── error.twig ├── graphs.twig ├── index.twig ├── layout.twig ├── product-form.twig ├── product.twig ├── products.twig ├── search.twig └── suggestions.twig /.docker/elasticsearch/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM docker.elastic.co/elasticsearch/elasticsearch-oss:6.2.4 2 | 3 | RUN bin/elasticsearch-plugin install analysis-icu --batch 4 | RUN bin/elasticsearch-plugin install ingest-attachment --batch 5 | 6 | ENV ES_JAVA_OPTS "-Xms1g -Xmx1g" 7 | 8 | EXPOSE 9200:9200 9300:9300 -------------------------------------------------------------------------------- /.docker/elasticsearch/config/elasticsearch.yml: -------------------------------------------------------------------------------- 1 | network.host: 0.0.0.0 2 | -------------------------------------------------------------------------------- /.docker/elasticsearch/config/logging.yml: -------------------------------------------------------------------------------- 1 | # you can override this using by setting a system property, for example -Des.logger.level=DEBUG 2 | es.logger.level: INFO 3 | rootLogger: ${es.logger.level}, console 4 | logger: 5 | # log action execution errors for easier debugging 6 | action: DEBUG 7 | # reduce the logging for aws, too much is logged under the default INFO 8 | com.amazonaws: WARN 9 | 10 | appender: 11 | console: 12 | type: console 13 | layout: 14 | type: consolePattern 15 | conversionPattern: "[%d{ISO8601}][%-5p][%-25c] %m%n" 16 | -------------------------------------------------------------------------------- /.docker/kibana/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM docker.elastic.co/kibana/kibana-oss:6.2.4 2 | 3 | ENV ELASTICSEARCH_URL "http://elasticsearch:9200" 4 | 5 | EXPOSE 5601:5601 -------------------------------------------------------------------------------- /.docker/logstash/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM docker.elastic.co/logstash/logstash:6.2.4 2 | 3 | WORKDIR /usr/share/logstash 4 | RUN bin/logstash-plugin install logstash-input-jdbc 5 | RUN bin/logstash-plugin install logstash-filter-json_encode 6 | RUN bin/logstash-plugin install logstash-filter-json 7 | RUN bin/logstash-plugin install logstash-filter-mutate 8 | 9 | COPY conf/logstash.conf /etc/logstash/conf.d/logstash.conf 10 | COPY conf/template.json /etc/logstash/conf.d/template.json 11 | COPY connector/* /usr/share/logstash/ 12 | 13 | # https://github.com/elastic/logstash-docker/issues/45 14 | RUN sed -i '/xpack/d' /usr/share/logstash/config/logstash.yml 15 | 16 | EXPOSE 5044:5044 17 | CMD ["logstash", "-f", "/etc/logstash/conf.d/logstash.conf", "--config.reload.automatic", "--debug", "--verbose"] -------------------------------------------------------------------------------- /.docker/logstash/conf/logstash.conf: -------------------------------------------------------------------------------- 1 | input { 2 | jdbc { 3 | jdbc_driver_library => "mysql-connector-java-5.1.36-bin.jar" 4 | jdbc_driver_class => "com.mysql.jdbc.Driver" 5 | jdbc_connection_string => "jdbc:mysql://127.0.0.1:33060/node_es_example" 6 | jdbc_user => "root" 7 | jdbc_password => "" 8 | schedule => "* * * * *" 9 | statement => "CALL fetchDataForElastic(:sql_last_value);" 10 | } 11 | } 12 | 13 | filter { 14 | json { 15 | source => "categories" 16 | target => "categories" 17 | } 18 | json { 19 | source => "completion" 20 | target => "completion" 21 | } 22 | mutate { remove_field => [ "@version", "@timestamp" ] } 23 | } 24 | 25 | output { 26 | stdout 27 | { 28 | codec => rubydebug 29 | } 30 | 31 | elasticsearch 32 | { 33 | hosts => ["127.0.0.1:9200"] 34 | index => "products" 35 | document_id => "%{id}" 36 | } 37 | } -------------------------------------------------------------------------------- /.docker/logstash/conf/template.json: -------------------------------------------------------------------------------- 1 | 2 | { 3 | "template": "myindex*", 4 | "settings": { 5 | "index.refresh_interval": "5s" 6 | }, 7 | "mappings": { 8 | "myindex": { 9 | "dynamic_templates": [ 10 | { 11 | "message_field": { 12 | "mapping": { 13 | "fielddata": { 14 | "format": "disabled" 15 | }, 16 | "omit_norms": true, 17 | "type": "text" 18 | }, 19 | "match_mapping_type": "string", 20 | "match": "message" 21 | } 22 | }, 23 | { 24 | "string_fields": { 25 | "match_mapping_type": "string", 26 | "match": "*", 27 | "mapping": { 28 | "fielddata": { 29 | "format": "disabled" 30 | }, 31 | "omit_norms": true, 32 | "type": "text", 33 | "fields": { 34 | "raw": { 35 | "ignore_above": 256, 36 | "type": "keyword" 37 | } 38 | } 39 | } 40 | } 41 | } 42 | ], 43 | "_all": { 44 | "enabled": true 45 | } 46 | } 47 | }, 48 | "aliases": {} 49 | } -------------------------------------------------------------------------------- /.docker/logstash/connector/mysql-connector-java-5.1.36-bin.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hkulekci/node-app-with-elasticsearch/a2ce09aaa64655a1fa9ad64cf6d2dd171c5bd7df/.docker/logstash/connector/mysql-connector-java-5.1.36-bin.jar -------------------------------------------------------------------------------- /.docker/mysql/mysqld.cnf: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. 2 | # 3 | # This program is free software; you can redistribute it and/or modify 4 | # it under the terms of the GNU General Public License as published by 5 | # the Free Software Foundation; version 2 of the License. 6 | # 7 | # This program is distributed in the hope that it will be useful, 8 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 | # GNU General Public License for more details. 11 | # 12 | # You should have received a copy of the GNU General Public License 13 | # along with this program; if not, write to the Free Software 14 | # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 15 | 16 | # 17 | # The MySQL Server configuration file. 18 | # 19 | # For explanations see 20 | # http://dev.mysql.com/doc/mysql/en/server-system-variables.html 21 | 22 | [mysqld] 23 | port = 33060 24 | pid-file = /var/run/mysqld/mysqld.pid 25 | socket = /var/run/mysqld/mysqld.sock 26 | datadir = /var/lib/mysql 27 | #log-error = /var/log/mysql/error.log 28 | # By default we only accept connections from localhost 29 | bind-address = 0.0.0.0 30 | # Disabling symbolic-links is recommended to prevent assorted security risks 31 | symbolic-links=0 -------------------------------------------------------------------------------- /.docker/redis/redis.conf: -------------------------------------------------------------------------------- 1 | bind 0.0.0.0 -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | 5 | # Runtime data 6 | pids 7 | *.pid 8 | *.seed 9 | 10 | # Directory for instrumented libs generated by jscoverage/JSCover 11 | lib-cov 12 | 13 | # Coverage directory used by tools like istanbul 14 | coverage 15 | 16 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 17 | .grunt 18 | 19 | # node-waf configuration 20 | .lock-wscript 21 | 22 | # Compiled binary addons (http://nodejs.org/api/addons.html) 23 | build/Release 24 | 25 | # Dependency directory 26 | # https://docs.npmjs.com/cli/shrinkwrap#caveats 27 | node_modules 28 | 29 | # Debug log from npm 30 | npm-debug.log 31 | 32 | .env -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Node Elasticsearch Example 2 | 3 | ## Starting Services 4 | 5 | ``` 6 | docker-compose up elasticsearch kibana 7 | docker-compose up mysql redis 8 | docker-compose up app listener 9 | ``` 10 | 11 | ## Database Structure and Initialization 12 | 13 | Connect the mysql container with following configuration: 14 | 15 | ``` 16 | Host: mysql 17 | User : root 18 | Password : 123456 19 | Port : 33060 20 | ``` 21 | 22 | And import `data/sample_data.sql` file for our sample data. 23 | 24 | Redis configuration : 25 | 26 | ``` 27 | Host: redis 28 | ``` 29 | 30 | 31 | ## Elastic Integration 32 | 33 | Then use Kibana Console interface to be able to create your index. First of all 34 | create your `products` index and `product` type. 35 | 36 | ``` 37 | DELETE products 38 | 39 | PUT products 40 | { 41 | "settings": { 42 | "number_of_shards": 1, 43 | "number_of_replicas": 0, 44 | "analysis": { 45 | "analyzer": { 46 | "autocomplete_analyzer" : { 47 | "type" : "custom", 48 | "tokenizer": "standard", 49 | "filter": ["lowercase", "autocomplete_filter"] 50 | }, 51 | "default_search": { 52 | "type": "custom", 53 | "tokenizer": "standard", 54 | "filter": [ 55 | "lowercase", 56 | "asciifolding" 57 | ] 58 | } 59 | }, 60 | "filter": { 61 | "autocomplete_filter": { 62 | "type": "edge_ngram", 63 | "min_gram": 2, 64 | "max_gram": 10 65 | } 66 | } 67 | } 68 | } 69 | } 70 | 71 | 72 | PUT products/_mapping 73 | { 74 | "properties": { 75 | "name": { 76 | "type": "text", 77 | "fields": { 78 | "autocomplete": { 79 | "type": "text", 80 | "analyzer": "autocomplete_analyzer", 81 | "search_analyzer": "standard" 82 | } 83 | } 84 | }, 85 | "description": { 86 | "type": "text", 87 | "fields": { 88 | "autocomplete": { 89 | "type": "text", 90 | "analyzer": "autocomplete_analyzer", 91 | "search_analyzer": "standard" 92 | } 93 | } 94 | }, 95 | "quantity": { 96 | "type": "long" 97 | }, 98 | "price": { 99 | "type": "double" 100 | }, 101 | "created_at": { 102 | "type": "date", 103 | "format": "strict_date_optional_time||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis" 104 | }, 105 | "updated_at": { 106 | "type": "date", 107 | "format": "strict_date_optional_time||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis" 108 | }, 109 | "categories": { 110 | "type": "object", 111 | "properties": { 112 | "id": { 113 | "type": "long" 114 | }, 115 | "name": { 116 | "type": "keyword", 117 | "fields": { 118 | "autocomplete": { 119 | "type": "text", 120 | "analyzer": "autocomplete_analyzer", 121 | "search_analyzer": "standard" 122 | } 123 | } 124 | } 125 | } 126 | }, 127 | "completion": { 128 | "type": "completion", 129 | "analyzer": "default_search", 130 | "search_analyzer": "default_search" 131 | } 132 | } 133 | } 134 | ``` 135 | 136 | Then check `data/logstash.conf` file and also last part of the 137 | `data/sample_data.sql`. There is a procedure in there. 138 | 139 | ``` 140 | DROP PROCEDURE fetchDataForElastic; 141 | 142 | DELIMITER // 143 | CREATE PROCEDURE fetchDataForElastic 144 | (IN currentdate Datetime) 145 | BEGIN 146 | SELECT 147 | p.*, 148 | 149 | CAST( (CONCAT ('[', GROUP_CONCAT(CONCAT('{"id":', c.id, ', "name":"',c.name,'"}')), ']')) AS JSON) categories 150 | FROM products p LEFT JOIN product_category pc ON pc.product_id = p.id LEFT JOIN categories c ON c.id = pc.category_id 151 | WHERE p.updated_at > currentdate GROUP BY p.id; 152 | END // 153 | DELIMITER ; 154 | ``` 155 | 156 | At the end, run logstash. `docker-compose up logstash` 157 | 158 | Known Issues : 159 | 160 | - Sometimes application stack without error while updating product -------------------------------------------------------------------------------- /app.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const path = require('path'); 3 | const logger = require('morgan'); 4 | const cookieParser = require('cookie-parser'); 5 | const bodyParser = require('body-parser'); 6 | const lessMiddleware = require('less-middleware'); 7 | 8 | // .env file configuration 9 | require('dotenv').config(); 10 | 11 | 12 | const index = require('./routes/index'); 13 | const products = require('./routes/products'); 14 | const categories = require('./routes/categories'); 15 | const search = require('./routes/search'); 16 | const graphs = require('./routes/graphs'); 17 | 18 | const app = express(); 19 | 20 | // view engine setup 21 | app.set('views', path.join(__dirname, 'views')); 22 | app.set('view engine', 'twig'); 23 | 24 | app.use(logger('dev')); 25 | app.use(bodyParser.json()); 26 | app.use(bodyParser.urlencoded({ extended: false })); 27 | app.use(cookieParser()); 28 | app.use(lessMiddleware(path.join(__dirname, 'public'))); 29 | app.use(express.static(path.join(__dirname, 'public'))); 30 | 31 | app.use('/', index); 32 | app.use('/product', products); 33 | app.use('/category', categories); 34 | app.use('/search', search); 35 | app.use('/graphs', graphs); 36 | 37 | // catch 404 and forward to error handler 38 | app.use(function(req, res, next) { 39 | const err = new Error('Not Found'); 40 | err.status = 404; 41 | next(err); 42 | }); 43 | 44 | // error handler 45 | app.use(function(err, req, res, next) { 46 | // set locals, only providing error in development 47 | res.locals.message = err.message; 48 | res.locals.error = req.app.get('env') === 'development' ? err : {}; 49 | 50 | // render the error page 51 | res.status(err.status || 500); 52 | res.render('error'); 53 | }); 54 | 55 | module.exports = app; 56 | -------------------------------------------------------------------------------- /bin/www: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | /** 4 | * Module dependencies. 5 | */ 6 | 7 | var app = require('../app'); 8 | var debug = require('debug')('node-es-example:server'); 9 | var http = require('http'); 10 | 11 | /** 12 | * Get port from environment and store in Express. 13 | */ 14 | 15 | var port = normalizePort(process.env.PORT || '3000'); 16 | app.set('port', port); 17 | 18 | /** 19 | * Create HTTP server. 20 | */ 21 | 22 | var server = http.createServer(app); 23 | 24 | /** 25 | * Listen on provided port, on all network interfaces. 26 | */ 27 | 28 | server.listen(port); 29 | server.on('error', onError); 30 | server.on('listening', onListening); 31 | 32 | /** 33 | * Normalize a port into a number, string, or false. 34 | */ 35 | 36 | function normalizePort(val) { 37 | var port = parseInt(val, 10); 38 | 39 | if (isNaN(port)) { 40 | // named pipe 41 | return val; 42 | } 43 | 44 | if (port >= 0) { 45 | // port number 46 | return port; 47 | } 48 | 49 | return false; 50 | } 51 | 52 | /** 53 | * Event listener for HTTP server "error" event. 54 | */ 55 | 56 | function onError(error) { 57 | if (error.syscall !== 'listen') { 58 | throw error; 59 | } 60 | 61 | var bind = typeof port === 'string' 62 | ? 'Pipe ' + port 63 | : 'Port ' + port; 64 | 65 | // handle specific listen errors with friendly messages 66 | switch (error.code) { 67 | case 'EACCES': 68 | console.error(bind + ' requires elevated privileges'); 69 | process.exit(1); 70 | break; 71 | case 'EADDRINUSE': 72 | console.error(bind + ' is already in use'); 73 | process.exit(1); 74 | break; 75 | default: 76 | throw error; 77 | } 78 | } 79 | 80 | /** 81 | * Event listener for HTTP server "listening" event. 82 | */ 83 | 84 | function onListening() { 85 | var addr = server.address(); 86 | var bind = typeof addr === 'string' 87 | ? 'pipe ' + addr 88 | : 'port ' + addr.port; 89 | debug('Listening on ' + bind); 90 | } 91 | -------------------------------------------------------------------------------- /data/.gitignore: -------------------------------------------------------------------------------- 1 | mysql-data/* 2 | nodes/* 3 | 4 | !mysql-data/.gitkeep 5 | !nodes/.gitkeep -------------------------------------------------------------------------------- /data/mysql-data/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hkulekci/node-app-with-elasticsearch/a2ce09aaa64655a1fa9ad64cf6d2dd171c5bd7df/data/mysql-data/.gitkeep -------------------------------------------------------------------------------- /data/nodes/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hkulekci/node-app-with-elasticsearch/a2ce09aaa64655a1fa9ad64cf6d2dd171c5bd7df/data/nodes/.gitkeep -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '2' 2 | 3 | services: 4 | elasticsearch: 5 | build: ./.docker/elasticsearch 6 | ports: 7 | - "9200:9200" 8 | - "9300:9300" 9 | volumes: 10 | - "./data:/usr/share/elasticsearch/data" 11 | 12 | kibana: 13 | build: ./.docker/kibana 14 | ports: 15 | - "5601:5601" 16 | links: 17 | - elasticsearch 18 | 19 | redis: 20 | image: redis:alpine 21 | ports: 22 | - "6379:6379" 23 | command: ["redis-server", "/etc/redis/redis.conf"] 24 | volumes: 25 | - "./.docker/redis/redis.conf:/etc/redis/redis.conf" 26 | 27 | logstash: 28 | build: ./.docker/logstash 29 | volumes: 30 | - "./sample:/tmp/data/" 31 | ports: 32 | - "5044:5044" 33 | links: 34 | - elasticsearch 35 | - mysql 36 | 37 | mysql: 38 | image: "mysql:5.7.19" 39 | restart: always 40 | ports: 41 | - "33060:33060" 42 | environment: 43 | MYSQL_ROOT_PASSWORD: "123456" 44 | volumes: 45 | - ./data/mysql-data:/var/lib/mysql 46 | - './.docker/mysql/mysqld.cnf:/etc/mysql/mysql.conf.d/mysqld.cnf' 47 | 48 | app: 49 | image: "node:8" 50 | user: "node" 51 | working_dir: /home/node/app 52 | environment: 53 | - NODE_ENV=production 54 | volumes: 55 | - ./:/home/node/app 56 | ports: 57 | - "3000:3000" 58 | command: "npm start" 59 | links: 60 | - elasticsearch 61 | - mysql 62 | - redis 63 | 64 | listener: 65 | image: "node:8" 66 | user: "node" 67 | working_dir: /home/node/app 68 | environment: 69 | - NODE_ENV=production 70 | volumes: 71 | - ./:/home/node/app 72 | command: "npm run listen" 73 | links: 74 | - elasticsearch 75 | - mysql 76 | - redis 77 | -------------------------------------------------------------------------------- /libraries/database.js: -------------------------------------------------------------------------------- 1 | const mysql = require('mysql2'); 2 | 3 | const pool = mysql.createPool({ 4 | host: process.env.MYSQL_HOST, 5 | user: process.env.MYSQL_USER, 6 | password: process.env.MYSQL_PASS, 7 | database: process.env.MYSQL_DB, 8 | port: process.env.MYSQL_PORT, 9 | debug: process.env.MYSQL_DEBUG == 'true' ? true : false, 10 | connectionLimit: 10, 11 | supportBigNumbers: true, 12 | insecureAuth: true, // *** dont use production. *** 13 | maxIdle: 10, 14 | idleTimeout: 60000, 15 | queueLimit: 0 16 | }); 17 | 18 | module.exports = pool; -------------------------------------------------------------------------------- /libraries/elasticsearch.js: -------------------------------------------------------------------------------- 1 | const { Client } = require('@elastic/elasticsearch'); 2 | const client = new Client({ 3 | node: process.env.ELASTIC_HOST, 4 | log: process.env.ELASTIC_LOG 5 | }); 6 | 7 | module.exports = client; -------------------------------------------------------------------------------- /libraries/redis-client.js: -------------------------------------------------------------------------------- 1 | const redis = require('redis'); 2 | client = redis.createClient({'url': process.env.REDIS_HOST}); 3 | 4 | const RedisClient = { 5 | getClient: function() { 6 | if (!client.isOpen) { 7 | client.connect().then() 8 | } 9 | return client; 10 | }, 11 | 12 | push: function(key, value, callback) { 13 | client.lpush(key, value, function(err, result) { 14 | callback(err, result); 15 | }); 16 | }, 17 | 18 | pop: function() { 19 | client.brpop(key, value, function(err, result) { 20 | callback(err, result); 21 | }); 22 | }, 23 | 24 | set: function(key, value, ttl) { 25 | if (value) { 26 | client.set(key, JSON.stringify(value), 'EX', ttl); 27 | } 28 | }, 29 | 30 | get: async function(key) { 31 | if (!client.isOpen) { 32 | await client.connect() 33 | } 34 | const value = await client.get(key); 35 | 36 | if (value !== null) { 37 | return JSON.parse(value); 38 | } 39 | 40 | return null; 41 | }, 42 | 43 | delete: function() { 44 | client.delete(key); 45 | } 46 | } 47 | 48 | 49 | module.exports = RedisClient; -------------------------------------------------------------------------------- /libraries/sample.database.js: -------------------------------------------------------------------------------- 1 | var db = require('database'); 2 | 3 | /** 4 | ## Products Table 5 | 6 | CREATE TABLE `products` ( 7 | `id` int(11) unsigned NOT NULL AUTO_INCREMENT, 8 | `name` varchar(255) DEFAULT NULL, 9 | `description` varchar(1024) DEFAULT NULL, 10 | `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, 11 | `updated_at` datetime NOT NULL ON UPDATE CURRENT_TIMESTAMP, 12 | `price` double NOT NULL DEFAULT '0', 13 | PRIMARY KEY (`id`) 14 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 15 | **/ -------------------------------------------------------------------------------- /node-es-example.sublime-project: -------------------------------------------------------------------------------- 1 | { 2 | "folders": 3 | [ 4 | { 5 | "path": "." 6 | } 7 | ], 8 | "settings": 9 | { 10 | "tab_size": 2 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "node-es-example", 3 | "version": "0.0.0", 4 | "lockfileVersion": 2, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "node-es-example", 9 | "version": "0.0.0", 10 | "dependencies": { 11 | "@elastic/elasticsearch": "^8.6.0", 12 | "async": "^2.6.2", 13 | "blueimp-md5": "^2.10.0", 14 | "body-parser": "^1.19.0", 15 | "cookie-parser": "^1.4.4", 16 | "debug": "~2.6.9", 17 | "dotenv": "^4.0.0", 18 | "express": "^4.16.4", 19 | "extend": ">=3.0.2", 20 | "hkulekci-simple-redis-queue": "^0.9.8", 21 | "less-middleware": "~3.0.1", 22 | "morgan": "^1.9.1", 23 | "mysql2": "^3.1.0", 24 | "node-datetime": "^2.1.2", 25 | "nodemon": "^2.0.20", 26 | "redis": "^4.6.4", 27 | "serve-favicon": "~2.4.5", 28 | "twig": "~0.10.3" 29 | } 30 | }, 31 | "node_modules/@elastic/elasticsearch": { 32 | "version": "8.6.0", 33 | "resolved": "https://registry.npmjs.org/@elastic/elasticsearch/-/elasticsearch-8.6.0.tgz", 34 | "integrity": "sha512-mN5EbbgSp1rfRmQ/5Hv7jqAK8xhGJxCg7G84xje8hSefE59P+HPPCv/+DgesCUSJdZpwXIo0DwOWHfHvktxxLw==", 35 | "dependencies": { 36 | "@elastic/transport": "^8.3.1", 37 | "tslib": "^2.4.0" 38 | }, 39 | "engines": { 40 | "node": ">=14" 41 | } 42 | }, 43 | "node_modules/@elastic/transport": { 44 | "version": "8.3.1", 45 | "resolved": "https://registry.npmjs.org/@elastic/transport/-/transport-8.3.1.tgz", 46 | "integrity": "sha512-jv/Yp2VLvv5tSMEOF8iGrtL2YsYHbpf4s+nDsItxUTLFTzuJGpnsB/xBlfsoT2kAYEnWHiSJuqrbRcpXEI/SEQ==", 47 | "dependencies": { 48 | "debug": "^4.3.4", 49 | "hpagent": "^1.0.0", 50 | "ms": "^2.1.3", 51 | "secure-json-parse": "^2.4.0", 52 | "tslib": "^2.4.0", 53 | "undici": "^5.5.1" 54 | }, 55 | "engines": { 56 | "node": ">=14" 57 | } 58 | }, 59 | "node_modules/@elastic/transport/node_modules/debug": { 60 | "version": "4.3.4", 61 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", 62 | "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", 63 | "dependencies": { 64 | "ms": "2.1.2" 65 | }, 66 | "engines": { 67 | "node": ">=6.0" 68 | }, 69 | "peerDependenciesMeta": { 70 | "supports-color": { 71 | "optional": true 72 | } 73 | } 74 | }, 75 | "node_modules/@elastic/transport/node_modules/debug/node_modules/ms": { 76 | "version": "2.1.2", 77 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 78 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" 79 | }, 80 | "node_modules/@redis/bloom": { 81 | "version": "1.2.0", 82 | "resolved": "https://registry.npmjs.org/@redis/bloom/-/bloom-1.2.0.tgz", 83 | "integrity": "sha512-HG2DFjYKbpNmVXsa0keLHp/3leGJz1mjh09f2RLGGLQZzSHpkmZWuwJbAvo3QcRY8p80m5+ZdXZdYOSBLlp7Cg==", 84 | "peerDependencies": { 85 | "@redis/client": "^1.0.0" 86 | } 87 | }, 88 | "node_modules/@redis/client": { 89 | "version": "1.5.5", 90 | "resolved": "https://registry.npmjs.org/@redis/client/-/client-1.5.5.tgz", 91 | "integrity": "sha512-fuMnpDYSjT5JXR9rrCW1YWA4L8N/9/uS4ImT3ZEC/hcaQRI1D/9FvwjriRj1UvepIgzZXthFVKMNRzP/LNL7BQ==", 92 | "dependencies": { 93 | "cluster-key-slot": "1.1.2", 94 | "generic-pool": "3.9.0", 95 | "yallist": "4.0.0" 96 | }, 97 | "engines": { 98 | "node": ">=14" 99 | } 100 | }, 101 | "node_modules/@redis/graph": { 102 | "version": "1.1.0", 103 | "resolved": "https://registry.npmjs.org/@redis/graph/-/graph-1.1.0.tgz", 104 | "integrity": "sha512-16yZWngxyXPd+MJxeSr0dqh2AIOi8j9yXKcKCwVaKDbH3HTuETpDVPcLujhFYVPtYrngSco31BUcSa9TH31Gqg==", 105 | "peerDependencies": { 106 | "@redis/client": "^1.0.0" 107 | } 108 | }, 109 | "node_modules/@redis/json": { 110 | "version": "1.0.4", 111 | "resolved": "https://registry.npmjs.org/@redis/json/-/json-1.0.4.tgz", 112 | "integrity": "sha512-LUZE2Gdrhg0Rx7AN+cZkb1e6HjoSKaeeW8rYnt89Tly13GBI5eP4CwDVr+MY8BAYfCg4/N15OUrtLoona9uSgw==", 113 | "peerDependencies": { 114 | "@redis/client": "^1.0.0" 115 | } 116 | }, 117 | "node_modules/@redis/search": { 118 | "version": "1.1.1", 119 | "resolved": "https://registry.npmjs.org/@redis/search/-/search-1.1.1.tgz", 120 | "integrity": "sha512-pqCXTc5e7wJJgUuJiC3hBgfoFRoPxYzwn0BEfKgejTM7M/9zP3IpUcqcjgfp8hF+LoV8rHZzcNTz7V+pEIY7LQ==", 121 | "peerDependencies": { 122 | "@redis/client": "^1.0.0" 123 | } 124 | }, 125 | "node_modules/@redis/time-series": { 126 | "version": "1.0.4", 127 | "resolved": "https://registry.npmjs.org/@redis/time-series/-/time-series-1.0.4.tgz", 128 | "integrity": "sha512-ThUIgo2U/g7cCuZavucQTQzA9g9JbDDY2f64u3AbAoz/8vE2lt2U37LamDUVChhaDA3IRT9R6VvJwqnUfTJzng==", 129 | "peerDependencies": { 130 | "@redis/client": "^1.0.0" 131 | } 132 | }, 133 | "node_modules/abbrev": { 134 | "version": "1.1.1", 135 | "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", 136 | "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" 137 | }, 138 | "node_modules/accepts": { 139 | "version": "1.3.8", 140 | "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", 141 | "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", 142 | "dependencies": { 143 | "mime-types": "~2.1.34", 144 | "negotiator": "0.6.3" 145 | }, 146 | "engines": { 147 | "node": ">= 0.6" 148 | } 149 | }, 150 | "node_modules/ajv": { 151 | "version": "6.12.6", 152 | "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", 153 | "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", 154 | "optional": true, 155 | "dependencies": { 156 | "fast-deep-equal": "^3.1.1", 157 | "fast-json-stable-stringify": "^2.0.0", 158 | "json-schema-traverse": "^0.4.1", 159 | "uri-js": "^4.2.2" 160 | }, 161 | "funding": { 162 | "type": "github", 163 | "url": "https://github.com/sponsors/epoberezkin" 164 | } 165 | }, 166 | "node_modules/anymatch": { 167 | "version": "3.1.3", 168 | "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", 169 | "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", 170 | "dependencies": { 171 | "normalize-path": "^3.0.0", 172 | "picomatch": "^2.0.4" 173 | }, 174 | "engines": { 175 | "node": ">= 8" 176 | } 177 | }, 178 | "node_modules/array-flatten": { 179 | "version": "1.1.1", 180 | "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", 181 | "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" 182 | }, 183 | "node_modules/asap": { 184 | "version": "2.0.6", 185 | "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", 186 | "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==", 187 | "optional": true 188 | }, 189 | "node_modules/asn1": { 190 | "version": "0.2.6", 191 | "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", 192 | "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", 193 | "optional": true, 194 | "dependencies": { 195 | "safer-buffer": "~2.1.0" 196 | } 197 | }, 198 | "node_modules/assert-plus": { 199 | "version": "1.0.0", 200 | "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", 201 | "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==", 202 | "optional": true, 203 | "engines": { 204 | "node": ">=0.8" 205 | } 206 | }, 207 | "node_modules/async": { 208 | "version": "2.6.4", 209 | "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", 210 | "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", 211 | "dependencies": { 212 | "lodash": "^4.17.14" 213 | } 214 | }, 215 | "node_modules/asynckit": { 216 | "version": "0.4.0", 217 | "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", 218 | "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", 219 | "optional": true 220 | }, 221 | "node_modules/aws-sign2": { 222 | "version": "0.7.0", 223 | "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", 224 | "integrity": "sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==", 225 | "optional": true, 226 | "engines": { 227 | "node": "*" 228 | } 229 | }, 230 | "node_modules/aws4": { 231 | "version": "1.12.0", 232 | "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.12.0.tgz", 233 | "integrity": "sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg==", 234 | "optional": true 235 | }, 236 | "node_modules/balanced-match": { 237 | "version": "1.0.2", 238 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", 239 | "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" 240 | }, 241 | "node_modules/basic-auth": { 242 | "version": "2.0.1", 243 | "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz", 244 | "integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==", 245 | "dependencies": { 246 | "safe-buffer": "5.1.2" 247 | }, 248 | "engines": { 249 | "node": ">= 0.8" 250 | } 251 | }, 252 | "node_modules/basic-auth/node_modules/safe-buffer": { 253 | "version": "5.1.2", 254 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", 255 | "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" 256 | }, 257 | "node_modules/bcrypt-pbkdf": { 258 | "version": "1.0.2", 259 | "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", 260 | "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==", 261 | "optional": true, 262 | "dependencies": { 263 | "tweetnacl": "^0.14.3" 264 | } 265 | }, 266 | "node_modules/binary-extensions": { 267 | "version": "2.2.0", 268 | "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", 269 | "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", 270 | "engines": { 271 | "node": ">=8" 272 | } 273 | }, 274 | "node_modules/blueimp-md5": { 275 | "version": "2.19.0", 276 | "resolved": "https://registry.npmjs.org/blueimp-md5/-/blueimp-md5-2.19.0.tgz", 277 | "integrity": "sha512-DRQrD6gJyy8FbiE4s+bDoXS9hiW3Vbx5uCdwvcCf3zLHL+Iv7LtGHLpr+GZV8rHG8tK766FGYBwRbu8pELTt+w==" 278 | }, 279 | "node_modules/body-parser": { 280 | "version": "1.20.1", 281 | "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", 282 | "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", 283 | "dependencies": { 284 | "bytes": "3.1.2", 285 | "content-type": "~1.0.4", 286 | "debug": "2.6.9", 287 | "depd": "2.0.0", 288 | "destroy": "1.2.0", 289 | "http-errors": "2.0.0", 290 | "iconv-lite": "0.4.24", 291 | "on-finished": "2.4.1", 292 | "qs": "6.11.0", 293 | "raw-body": "2.5.1", 294 | "type-is": "~1.6.18", 295 | "unpipe": "1.0.0" 296 | }, 297 | "engines": { 298 | "node": ">= 0.8", 299 | "npm": "1.2.8000 || >= 1.4.16" 300 | } 301 | }, 302 | "node_modules/brace-expansion": { 303 | "version": "1.1.11", 304 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", 305 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", 306 | "dependencies": { 307 | "balanced-match": "^1.0.0", 308 | "concat-map": "0.0.1" 309 | } 310 | }, 311 | "node_modules/braces": { 312 | "version": "3.0.2", 313 | "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", 314 | "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", 315 | "dependencies": { 316 | "fill-range": "^7.0.1" 317 | }, 318 | "engines": { 319 | "node": ">=8" 320 | } 321 | }, 322 | "node_modules/busboy": { 323 | "version": "1.6.0", 324 | "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", 325 | "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", 326 | "dependencies": { 327 | "streamsearch": "^1.1.0" 328 | }, 329 | "engines": { 330 | "node": ">=10.16.0" 331 | } 332 | }, 333 | "node_modules/bytes": { 334 | "version": "3.1.2", 335 | "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", 336 | "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", 337 | "engines": { 338 | "node": ">= 0.8" 339 | } 340 | }, 341 | "node_modules/call-bind": { 342 | "version": "1.0.2", 343 | "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", 344 | "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", 345 | "dependencies": { 346 | "function-bind": "^1.1.1", 347 | "get-intrinsic": "^1.0.2" 348 | }, 349 | "funding": { 350 | "url": "https://github.com/sponsors/ljharb" 351 | } 352 | }, 353 | "node_modules/caseless": { 354 | "version": "0.12.0", 355 | "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", 356 | "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==", 357 | "optional": true 358 | }, 359 | "node_modules/chokidar": { 360 | "version": "3.5.3", 361 | "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", 362 | "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", 363 | "funding": [ 364 | { 365 | "type": "individual", 366 | "url": "https://paulmillr.com/funding/" 367 | } 368 | ], 369 | "dependencies": { 370 | "anymatch": "~3.1.2", 371 | "braces": "~3.0.2", 372 | "glob-parent": "~5.1.2", 373 | "is-binary-path": "~2.1.0", 374 | "is-glob": "~4.0.1", 375 | "normalize-path": "~3.0.0", 376 | "readdirp": "~3.6.0" 377 | }, 378 | "engines": { 379 | "node": ">= 8.10.0" 380 | }, 381 | "optionalDependencies": { 382 | "fsevents": "~2.3.2" 383 | } 384 | }, 385 | "node_modules/cluster-key-slot": { 386 | "version": "1.1.2", 387 | "resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.2.tgz", 388 | "integrity": "sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA==", 389 | "engines": { 390 | "node": ">=0.10.0" 391 | } 392 | }, 393 | "node_modules/combined-stream": { 394 | "version": "1.0.8", 395 | "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", 396 | "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", 397 | "optional": true, 398 | "dependencies": { 399 | "delayed-stream": "~1.0.0" 400 | }, 401 | "engines": { 402 | "node": ">= 0.8" 403 | } 404 | }, 405 | "node_modules/concat-map": { 406 | "version": "0.0.1", 407 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 408 | "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" 409 | }, 410 | "node_modules/content-disposition": { 411 | "version": "0.5.4", 412 | "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", 413 | "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", 414 | "dependencies": { 415 | "safe-buffer": "5.2.1" 416 | }, 417 | "engines": { 418 | "node": ">= 0.6" 419 | } 420 | }, 421 | "node_modules/content-type": { 422 | "version": "1.0.5", 423 | "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", 424 | "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", 425 | "engines": { 426 | "node": ">= 0.6" 427 | } 428 | }, 429 | "node_modules/cookie": { 430 | "version": "0.4.1", 431 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz", 432 | "integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==", 433 | "engines": { 434 | "node": ">= 0.6" 435 | } 436 | }, 437 | "node_modules/cookie-parser": { 438 | "version": "1.4.6", 439 | "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.6.tgz", 440 | "integrity": "sha512-z3IzaNjdwUC2olLIB5/ITd0/setiaFMLYiZJle7xg5Fe9KWAceil7xszYfHHBtDFYLSgJduS2Ty0P1uJdPDJeA==", 441 | "dependencies": { 442 | "cookie": "0.4.1", 443 | "cookie-signature": "1.0.6" 444 | }, 445 | "engines": { 446 | "node": ">= 0.8.0" 447 | } 448 | }, 449 | "node_modules/cookie-signature": { 450 | "version": "1.0.6", 451 | "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", 452 | "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" 453 | }, 454 | "node_modules/core-util-is": { 455 | "version": "1.0.2", 456 | "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", 457 | "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==", 458 | "optional": true 459 | }, 460 | "node_modules/dashdash": { 461 | "version": "1.14.1", 462 | "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", 463 | "integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==", 464 | "optional": true, 465 | "dependencies": { 466 | "assert-plus": "^1.0.0" 467 | }, 468 | "engines": { 469 | "node": ">=0.10" 470 | } 471 | }, 472 | "node_modules/debug": { 473 | "version": "2.6.9", 474 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 475 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 476 | "dependencies": { 477 | "ms": "2.0.0" 478 | } 479 | }, 480 | "node_modules/debug/node_modules/ms": { 481 | "version": "2.0.0", 482 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 483 | "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" 484 | }, 485 | "node_modules/delayed-stream": { 486 | "version": "1.0.0", 487 | "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", 488 | "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", 489 | "optional": true, 490 | "engines": { 491 | "node": ">=0.4.0" 492 | } 493 | }, 494 | "node_modules/denque": { 495 | "version": "2.1.0", 496 | "resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz", 497 | "integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==", 498 | "engines": { 499 | "node": ">=0.10" 500 | } 501 | }, 502 | "node_modules/depd": { 503 | "version": "2.0.0", 504 | "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", 505 | "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", 506 | "engines": { 507 | "node": ">= 0.8" 508 | } 509 | }, 510 | "node_modules/destroy": { 511 | "version": "1.2.0", 512 | "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", 513 | "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", 514 | "engines": { 515 | "node": ">= 0.8", 516 | "npm": "1.2.8000 || >= 1.4.16" 517 | } 518 | }, 519 | "node_modules/dotenv": { 520 | "version": "4.0.0", 521 | "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-4.0.0.tgz", 522 | "integrity": "sha512-XcaMACOr3JMVcEv0Y/iUM2XaOsATRZ3U1In41/1jjK6vJZ2PZbQ1bzCG8uvaByfaBpl9gqc9QWJovpUGBXLLYQ==", 523 | "engines": { 524 | "node": ">=4.6.0" 525 | } 526 | }, 527 | "node_modules/ecc-jsbn": { 528 | "version": "0.1.2", 529 | "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", 530 | "integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==", 531 | "optional": true, 532 | "dependencies": { 533 | "jsbn": "~0.1.0", 534 | "safer-buffer": "^2.1.0" 535 | } 536 | }, 537 | "node_modules/ee-first": { 538 | "version": "1.1.1", 539 | "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", 540 | "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" 541 | }, 542 | "node_modules/encodeurl": { 543 | "version": "1.0.2", 544 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", 545 | "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", 546 | "engines": { 547 | "node": ">= 0.8" 548 | } 549 | }, 550 | "node_modules/errno": { 551 | "version": "0.1.8", 552 | "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.8.tgz", 553 | "integrity": "sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==", 554 | "optional": true, 555 | "dependencies": { 556 | "prr": "~1.0.1" 557 | }, 558 | "bin": { 559 | "errno": "cli.js" 560 | } 561 | }, 562 | "node_modules/escape-html": { 563 | "version": "1.0.3", 564 | "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", 565 | "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" 566 | }, 567 | "node_modules/etag": { 568 | "version": "1.8.1", 569 | "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", 570 | "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", 571 | "engines": { 572 | "node": ">= 0.6" 573 | } 574 | }, 575 | "node_modules/express": { 576 | "version": "4.18.2", 577 | "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", 578 | "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==", 579 | "dependencies": { 580 | "accepts": "~1.3.8", 581 | "array-flatten": "1.1.1", 582 | "body-parser": "1.20.1", 583 | "content-disposition": "0.5.4", 584 | "content-type": "~1.0.4", 585 | "cookie": "0.5.0", 586 | "cookie-signature": "1.0.6", 587 | "debug": "2.6.9", 588 | "depd": "2.0.0", 589 | "encodeurl": "~1.0.2", 590 | "escape-html": "~1.0.3", 591 | "etag": "~1.8.1", 592 | "finalhandler": "1.2.0", 593 | "fresh": "0.5.2", 594 | "http-errors": "2.0.0", 595 | "merge-descriptors": "1.0.1", 596 | "methods": "~1.1.2", 597 | "on-finished": "2.4.1", 598 | "parseurl": "~1.3.3", 599 | "path-to-regexp": "0.1.7", 600 | "proxy-addr": "~2.0.7", 601 | "qs": "6.11.0", 602 | "range-parser": "~1.2.1", 603 | "safe-buffer": "5.2.1", 604 | "send": "0.18.0", 605 | "serve-static": "1.15.0", 606 | "setprototypeof": "1.2.0", 607 | "statuses": "2.0.1", 608 | "type-is": "~1.6.18", 609 | "utils-merge": "1.0.1", 610 | "vary": "~1.1.2" 611 | }, 612 | "engines": { 613 | "node": ">= 0.10.0" 614 | } 615 | }, 616 | "node_modules/express/node_modules/cookie": { 617 | "version": "0.5.0", 618 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", 619 | "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", 620 | "engines": { 621 | "node": ">= 0.6" 622 | } 623 | }, 624 | "node_modules/extend": { 625 | "version": "3.0.2", 626 | "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", 627 | "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" 628 | }, 629 | "node_modules/extsprintf": { 630 | "version": "1.3.0", 631 | "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", 632 | "integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==", 633 | "engines": [ 634 | "node >=0.6.0" 635 | ], 636 | "optional": true 637 | }, 638 | "node_modules/fast-deep-equal": { 639 | "version": "3.1.3", 640 | "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", 641 | "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", 642 | "optional": true 643 | }, 644 | "node_modules/fast-json-stable-stringify": { 645 | "version": "2.1.0", 646 | "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", 647 | "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", 648 | "optional": true 649 | }, 650 | "node_modules/fill-range": { 651 | "version": "7.0.1", 652 | "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", 653 | "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", 654 | "dependencies": { 655 | "to-regex-range": "^5.0.1" 656 | }, 657 | "engines": { 658 | "node": ">=8" 659 | } 660 | }, 661 | "node_modules/finalhandler": { 662 | "version": "1.2.0", 663 | "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", 664 | "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", 665 | "dependencies": { 666 | "debug": "2.6.9", 667 | "encodeurl": "~1.0.2", 668 | "escape-html": "~1.0.3", 669 | "on-finished": "2.4.1", 670 | "parseurl": "~1.3.3", 671 | "statuses": "2.0.1", 672 | "unpipe": "~1.0.0" 673 | }, 674 | "engines": { 675 | "node": ">= 0.8" 676 | } 677 | }, 678 | "node_modules/foreachasync": { 679 | "version": "3.0.0", 680 | "resolved": "https://registry.npmjs.org/foreachasync/-/foreachasync-3.0.0.tgz", 681 | "integrity": "sha512-J+ler7Ta54FwwNcx6wQRDhTIbNeyDcARMkOcguEqnEdtm0jKvN3Li3PDAb2Du3ubJYEWfYL83XMROXdsXAXycw==" 682 | }, 683 | "node_modules/forever-agent": { 684 | "version": "0.6.1", 685 | "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", 686 | "integrity": "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==", 687 | "optional": true, 688 | "engines": { 689 | "node": "*" 690 | } 691 | }, 692 | "node_modules/form-data": { 693 | "version": "2.3.3", 694 | "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", 695 | "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", 696 | "optional": true, 697 | "dependencies": { 698 | "asynckit": "^0.4.0", 699 | "combined-stream": "^1.0.6", 700 | "mime-types": "^2.1.12" 701 | }, 702 | "engines": { 703 | "node": ">= 0.12" 704 | } 705 | }, 706 | "node_modules/forwarded": { 707 | "version": "0.2.0", 708 | "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", 709 | "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", 710 | "engines": { 711 | "node": ">= 0.6" 712 | } 713 | }, 714 | "node_modules/fresh": { 715 | "version": "0.5.2", 716 | "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", 717 | "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", 718 | "engines": { 719 | "node": ">= 0.6" 720 | } 721 | }, 722 | "node_modules/fsevents": { 723 | "version": "2.3.2", 724 | "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", 725 | "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", 726 | "hasInstallScript": true, 727 | "optional": true, 728 | "os": [ 729 | "darwin" 730 | ], 731 | "engines": { 732 | "node": "^8.16.0 || ^10.6.0 || >=11.0.0" 733 | } 734 | }, 735 | "node_modules/function-bind": { 736 | "version": "1.1.1", 737 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", 738 | "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" 739 | }, 740 | "node_modules/generate-function": { 741 | "version": "2.3.1", 742 | "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.3.1.tgz", 743 | "integrity": "sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==", 744 | "dependencies": { 745 | "is-property": "^1.0.2" 746 | } 747 | }, 748 | "node_modules/generic-pool": { 749 | "version": "3.9.0", 750 | "resolved": "https://registry.npmjs.org/generic-pool/-/generic-pool-3.9.0.tgz", 751 | "integrity": "sha512-hymDOu5B53XvN4QT9dBmZxPX4CWhBPPLguTZ9MMFeFa/Kg0xWVfylOVNlJji/E7yTZWFd/q9GO5TxDLq156D7g==", 752 | "engines": { 753 | "node": ">= 4" 754 | } 755 | }, 756 | "node_modules/get-intrinsic": { 757 | "version": "1.2.0", 758 | "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.0.tgz", 759 | "integrity": "sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==", 760 | "dependencies": { 761 | "function-bind": "^1.1.1", 762 | "has": "^1.0.3", 763 | "has-symbols": "^1.0.3" 764 | }, 765 | "funding": { 766 | "url": "https://github.com/sponsors/ljharb" 767 | } 768 | }, 769 | "node_modules/getpass": { 770 | "version": "0.1.7", 771 | "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", 772 | "integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==", 773 | "optional": true, 774 | "dependencies": { 775 | "assert-plus": "^1.0.0" 776 | } 777 | }, 778 | "node_modules/glob-parent": { 779 | "version": "5.1.2", 780 | "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", 781 | "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", 782 | "dependencies": { 783 | "is-glob": "^4.0.1" 784 | }, 785 | "engines": { 786 | "node": ">= 6" 787 | } 788 | }, 789 | "node_modules/graceful-fs": { 790 | "version": "4.2.10", 791 | "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", 792 | "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", 793 | "optional": true 794 | }, 795 | "node_modules/har-schema": { 796 | "version": "2.0.0", 797 | "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", 798 | "integrity": "sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q==", 799 | "optional": true, 800 | "engines": { 801 | "node": ">=4" 802 | } 803 | }, 804 | "node_modules/har-validator": { 805 | "version": "5.1.5", 806 | "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", 807 | "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", 808 | "deprecated": "this library is no longer supported", 809 | "optional": true, 810 | "dependencies": { 811 | "ajv": "^6.12.3", 812 | "har-schema": "^2.0.0" 813 | }, 814 | "engines": { 815 | "node": ">=6" 816 | } 817 | }, 818 | "node_modules/has": { 819 | "version": "1.0.3", 820 | "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", 821 | "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", 822 | "dependencies": { 823 | "function-bind": "^1.1.1" 824 | }, 825 | "engines": { 826 | "node": ">= 0.4.0" 827 | } 828 | }, 829 | "node_modules/has-flag": { 830 | "version": "3.0.0", 831 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", 832 | "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", 833 | "engines": { 834 | "node": ">=4" 835 | } 836 | }, 837 | "node_modules/has-symbols": { 838 | "version": "1.0.3", 839 | "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", 840 | "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", 841 | "engines": { 842 | "node": ">= 0.4" 843 | }, 844 | "funding": { 845 | "url": "https://github.com/sponsors/ljharb" 846 | } 847 | }, 848 | "node_modules/hkulekci-simple-redis-queue": { 849 | "version": "0.9.8", 850 | "resolved": "https://registry.npmjs.org/hkulekci-simple-redis-queue/-/hkulekci-simple-redis-queue-0.9.8.tgz", 851 | "integrity": "sha512-fbIoHJUoh4cWAnpyrenEKDqnGFgLHekHMsz0TTAZz/9QZeuVh1qPdEVrTizy8h32PAoE0zgMfdsWmlwjn7doGQ==", 852 | "dependencies": { 853 | "redis": "^4.6.4" 854 | } 855 | }, 856 | "node_modules/hpagent": { 857 | "version": "1.2.0", 858 | "resolved": "https://registry.npmjs.org/hpagent/-/hpagent-1.2.0.tgz", 859 | "integrity": "sha512-A91dYTeIB6NoXG+PxTQpCCDDnfHsW9kc06Lvpu1TEe9gnd6ZFeiBoRO9JvzEv6xK7EX97/dUE8g/vBMTqTS3CA==", 860 | "engines": { 861 | "node": ">=14" 862 | } 863 | }, 864 | "node_modules/http-errors": { 865 | "version": "2.0.0", 866 | "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", 867 | "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", 868 | "dependencies": { 869 | "depd": "2.0.0", 870 | "inherits": "2.0.4", 871 | "setprototypeof": "1.2.0", 872 | "statuses": "2.0.1", 873 | "toidentifier": "1.0.1" 874 | }, 875 | "engines": { 876 | "node": ">= 0.8" 877 | } 878 | }, 879 | "node_modules/http-signature": { 880 | "version": "1.2.0", 881 | "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", 882 | "integrity": "sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ==", 883 | "optional": true, 884 | "dependencies": { 885 | "assert-plus": "^1.0.0", 886 | "jsprim": "^1.2.2", 887 | "sshpk": "^1.7.0" 888 | }, 889 | "engines": { 890 | "node": ">=0.8", 891 | "npm": ">=1.3.7" 892 | } 893 | }, 894 | "node_modules/iconv-lite": { 895 | "version": "0.4.24", 896 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", 897 | "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", 898 | "dependencies": { 899 | "safer-buffer": ">= 2.1.2 < 3" 900 | }, 901 | "engines": { 902 | "node": ">=0.10.0" 903 | } 904 | }, 905 | "node_modules/ignore-by-default": { 906 | "version": "1.0.1", 907 | "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", 908 | "integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==" 909 | }, 910 | "node_modules/image-size": { 911 | "version": "0.5.5", 912 | "resolved": "https://registry.npmjs.org/image-size/-/image-size-0.5.5.tgz", 913 | "integrity": "sha512-6TDAlDPZxUFCv+fuOkIoXT/V/f3Qbq8e37p+YOiYrUv3v9cc3/6x78VdfPgFVaB9dZYeLUfKgHRebpkm/oP2VQ==", 914 | "optional": true, 915 | "bin": { 916 | "image-size": "bin/image-size.js" 917 | }, 918 | "engines": { 919 | "node": ">=0.10.0" 920 | } 921 | }, 922 | "node_modules/inherits": { 923 | "version": "2.0.4", 924 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 925 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" 926 | }, 927 | "node_modules/ipaddr.js": { 928 | "version": "1.9.1", 929 | "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", 930 | "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", 931 | "engines": { 932 | "node": ">= 0.10" 933 | } 934 | }, 935 | "node_modules/is": { 936 | "version": "3.3.0", 937 | "resolved": "https://registry.npmjs.org/is/-/is-3.3.0.tgz", 938 | "integrity": "sha512-nW24QBoPcFGGHJGUwnfpI7Yc5CdqWNdsyHQszVE/z2pKHXzh7FZ5GWhJqSyaQ9wMkQnsTx+kAI8bHlCX4tKdbg==", 939 | "engines": { 940 | "node": "*" 941 | } 942 | }, 943 | "node_modules/is-binary-path": { 944 | "version": "2.1.0", 945 | "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", 946 | "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", 947 | "dependencies": { 948 | "binary-extensions": "^2.0.0" 949 | }, 950 | "engines": { 951 | "node": ">=8" 952 | } 953 | }, 954 | "node_modules/is-extglob": { 955 | "version": "2.1.1", 956 | "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", 957 | "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", 958 | "engines": { 959 | "node": ">=0.10.0" 960 | } 961 | }, 962 | "node_modules/is-glob": { 963 | "version": "4.0.3", 964 | "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", 965 | "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", 966 | "dependencies": { 967 | "is-extglob": "^2.1.1" 968 | }, 969 | "engines": { 970 | "node": ">=0.10.0" 971 | } 972 | }, 973 | "node_modules/is-number": { 974 | "version": "7.0.0", 975 | "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", 976 | "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", 977 | "engines": { 978 | "node": ">=0.12.0" 979 | } 980 | }, 981 | "node_modules/is-property": { 982 | "version": "1.0.2", 983 | "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", 984 | "integrity": "sha512-Ks/IoX00TtClbGQr4TWXemAnktAQvYB7HzcCxDGqEZU6oCmb2INHuOoKxbtR+HFkmYWBKv/dOZtGRiAjDhj92g==" 985 | }, 986 | "node_modules/is-typedarray": { 987 | "version": "1.0.0", 988 | "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", 989 | "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==", 990 | "optional": true 991 | }, 992 | "node_modules/isstream": { 993 | "version": "0.1.2", 994 | "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", 995 | "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==", 996 | "optional": true 997 | }, 998 | "node_modules/jsbn": { 999 | "version": "0.1.1", 1000 | "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", 1001 | "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==", 1002 | "optional": true 1003 | }, 1004 | "node_modules/json-schema": { 1005 | "version": "0.4.0", 1006 | "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", 1007 | "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==", 1008 | "optional": true 1009 | }, 1010 | "node_modules/json-schema-traverse": { 1011 | "version": "0.4.1", 1012 | "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", 1013 | "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", 1014 | "optional": true 1015 | }, 1016 | "node_modules/json-stringify-safe": { 1017 | "version": "5.0.1", 1018 | "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", 1019 | "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", 1020 | "optional": true 1021 | }, 1022 | "node_modules/jsprim": { 1023 | "version": "1.4.2", 1024 | "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz", 1025 | "integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==", 1026 | "optional": true, 1027 | "dependencies": { 1028 | "assert-plus": "1.0.0", 1029 | "extsprintf": "1.3.0", 1030 | "json-schema": "0.4.0", 1031 | "verror": "1.10.0" 1032 | }, 1033 | "engines": { 1034 | "node": ">=0.6.0" 1035 | } 1036 | }, 1037 | "node_modules/less": { 1038 | "version": "3.0.4", 1039 | "resolved": "https://registry.npmjs.org/less/-/less-3.0.4.tgz", 1040 | "integrity": "sha512-q3SyEnPKbk9zh4l36PGeW2fgynKu+FpbhiUNx/yaiBUQ3V0CbACCgb9FzYWcRgI2DJlP6eI4jc8XPrCTi55YcQ==", 1041 | "bin": { 1042 | "lessc": "bin/lessc" 1043 | }, 1044 | "engines": { 1045 | "node": ">=4" 1046 | }, 1047 | "optionalDependencies": { 1048 | "errno": "^0.1.1", 1049 | "graceful-fs": "^4.1.2", 1050 | "image-size": "~0.5.0", 1051 | "mime": "^1.4.1", 1052 | "mkdirp": "^0.5.0", 1053 | "promise": "^7.1.1", 1054 | "request": "^2.83.0", 1055 | "source-map": "~0.6.0" 1056 | } 1057 | }, 1058 | "node_modules/less-middleware": { 1059 | "version": "3.0.1", 1060 | "resolved": "https://registry.npmjs.org/less-middleware/-/less-middleware-3.0.1.tgz", 1061 | "integrity": "sha512-FCG4zGd7c/lKMWGDzzkfU9Lcndfjc4TcSnuRwUtJ4E+NxPMuDGe7lJA1rOn+SI9x2lak+s4b6sQkcPa45eqKiw==", 1062 | "dependencies": { 1063 | "less": "~3.0.4", 1064 | "mkdirp": "~0.5.1", 1065 | "node.extend": "~2.0.0" 1066 | }, 1067 | "engines": { 1068 | "node": ">= 0.7.1" 1069 | } 1070 | }, 1071 | "node_modules/locutus": { 1072 | "version": "2.0.16", 1073 | "resolved": "https://registry.npmjs.org/locutus/-/locutus-2.0.16.tgz", 1074 | "integrity": "sha512-pGfl6Hb/1mXLzrX5kl5lH7gz25ey0vwQssZp8Qo2CEF59di6KrAgdFm+0pW8ghLnvNzzJGj5tlWhhv2QbK3jeQ==", 1075 | "engines": { 1076 | "node": ">= 10" 1077 | } 1078 | }, 1079 | "node_modules/lodash": { 1080 | "version": "4.17.21", 1081 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", 1082 | "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" 1083 | }, 1084 | "node_modules/long": { 1085 | "version": "5.2.1", 1086 | "resolved": "https://registry.npmjs.org/long/-/long-5.2.1.tgz", 1087 | "integrity": "sha512-GKSNGeNAtw8IryjjkhZxuKB3JzlcLTwjtiQCHKvqQet81I93kXslhDQruGI/QsddO83mcDToBVy7GqGS/zYf/A==" 1088 | }, 1089 | "node_modules/lru-cache": { 1090 | "version": "7.14.1", 1091 | "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.14.1.tgz", 1092 | "integrity": "sha512-ysxwsnTKdAx96aTRdhDOCQfDgbHnt8SK0KY8SEjO0wHinhWOFTESbjVCMPbU1uGXg/ch4lifqx0wfjOawU2+WA==", 1093 | "engines": { 1094 | "node": ">=12" 1095 | } 1096 | }, 1097 | "node_modules/media-typer": { 1098 | "version": "0.3.0", 1099 | "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", 1100 | "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", 1101 | "engines": { 1102 | "node": ">= 0.6" 1103 | } 1104 | }, 1105 | "node_modules/merge-descriptors": { 1106 | "version": "1.0.1", 1107 | "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", 1108 | "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" 1109 | }, 1110 | "node_modules/methods": { 1111 | "version": "1.1.2", 1112 | "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", 1113 | "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", 1114 | "engines": { 1115 | "node": ">= 0.6" 1116 | } 1117 | }, 1118 | "node_modules/mime": { 1119 | "version": "1.6.0", 1120 | "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", 1121 | "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", 1122 | "bin": { 1123 | "mime": "cli.js" 1124 | }, 1125 | "engines": { 1126 | "node": ">=4" 1127 | } 1128 | }, 1129 | "node_modules/mime-db": { 1130 | "version": "1.52.0", 1131 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", 1132 | "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", 1133 | "engines": { 1134 | "node": ">= 0.6" 1135 | } 1136 | }, 1137 | "node_modules/mime-types": { 1138 | "version": "2.1.35", 1139 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", 1140 | "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", 1141 | "dependencies": { 1142 | "mime-db": "1.52.0" 1143 | }, 1144 | "engines": { 1145 | "node": ">= 0.6" 1146 | } 1147 | }, 1148 | "node_modules/minimatch": { 1149 | "version": "3.1.2", 1150 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", 1151 | "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", 1152 | "dependencies": { 1153 | "brace-expansion": "^1.1.7" 1154 | }, 1155 | "engines": { 1156 | "node": "*" 1157 | } 1158 | }, 1159 | "node_modules/minimist": { 1160 | "version": "1.2.7", 1161 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.7.tgz", 1162 | "integrity": "sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g==", 1163 | "funding": { 1164 | "url": "https://github.com/sponsors/ljharb" 1165 | } 1166 | }, 1167 | "node_modules/mkdirp": { 1168 | "version": "0.5.6", 1169 | "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", 1170 | "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", 1171 | "dependencies": { 1172 | "minimist": "^1.2.6" 1173 | }, 1174 | "bin": { 1175 | "mkdirp": "bin/cmd.js" 1176 | } 1177 | }, 1178 | "node_modules/morgan": { 1179 | "version": "1.10.0", 1180 | "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.10.0.tgz", 1181 | "integrity": "sha512-AbegBVI4sh6El+1gNwvD5YIck7nSA36weD7xvIxG4in80j/UoK8AEGaWnnz8v1GxonMCltmlNs5ZKbGvl9b1XQ==", 1182 | "dependencies": { 1183 | "basic-auth": "~2.0.1", 1184 | "debug": "2.6.9", 1185 | "depd": "~2.0.0", 1186 | "on-finished": "~2.3.0", 1187 | "on-headers": "~1.0.2" 1188 | }, 1189 | "engines": { 1190 | "node": ">= 0.8.0" 1191 | } 1192 | }, 1193 | "node_modules/morgan/node_modules/on-finished": { 1194 | "version": "2.3.0", 1195 | "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", 1196 | "integrity": "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==", 1197 | "dependencies": { 1198 | "ee-first": "1.1.1" 1199 | }, 1200 | "engines": { 1201 | "node": ">= 0.8" 1202 | } 1203 | }, 1204 | "node_modules/ms": { 1205 | "version": "2.1.3", 1206 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", 1207 | "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" 1208 | }, 1209 | "node_modules/mysql2": { 1210 | "version": "3.1.0", 1211 | "resolved": "https://registry.npmjs.org/mysql2/-/mysql2-3.1.0.tgz", 1212 | "integrity": "sha512-woMeIog21X72RcFLhE/xajhUdnwRMd6Oq16S7/O2qJ5lPUDfFwgSW+xhx7TjzcM8PU3q+dVsryIaDi+HyQR/0A==", 1213 | "dependencies": { 1214 | "denque": "^2.1.0", 1215 | "generate-function": "^2.3.1", 1216 | "iconv-lite": "^0.6.3", 1217 | "long": "^5.2.1", 1218 | "lru-cache": "^7.14.1", 1219 | "named-placeholders": "^1.1.3", 1220 | "seq-queue": "^0.0.5", 1221 | "sqlstring": "^2.3.2" 1222 | }, 1223 | "engines": { 1224 | "node": ">= 8.0" 1225 | } 1226 | }, 1227 | "node_modules/mysql2/node_modules/iconv-lite": { 1228 | "version": "0.6.3", 1229 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", 1230 | "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", 1231 | "dependencies": { 1232 | "safer-buffer": ">= 2.1.2 < 3.0.0" 1233 | }, 1234 | "engines": { 1235 | "node": ">=0.10.0" 1236 | } 1237 | }, 1238 | "node_modules/named-placeholders": { 1239 | "version": "1.1.3", 1240 | "resolved": "https://registry.npmjs.org/named-placeholders/-/named-placeholders-1.1.3.tgz", 1241 | "integrity": "sha512-eLoBxg6wE/rZkJPhU/xRX1WTpkFEwDJEN96oxFrTsqBdbT5ec295Q+CoHrL9IT0DipqKhmGcaZmwOt8OON5x1w==", 1242 | "dependencies": { 1243 | "lru-cache": "^7.14.1" 1244 | }, 1245 | "engines": { 1246 | "node": ">=12.0.0" 1247 | } 1248 | }, 1249 | "node_modules/negotiator": { 1250 | "version": "0.6.3", 1251 | "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", 1252 | "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", 1253 | "engines": { 1254 | "node": ">= 0.6" 1255 | } 1256 | }, 1257 | "node_modules/node-datetime": { 1258 | "version": "2.1.2", 1259 | "resolved": "https://registry.npmjs.org/node-datetime/-/node-datetime-2.1.2.tgz", 1260 | "integrity": "sha512-eev1F0IPKSu3zvASMtH8ic4znGpfXdq9yc8yc/EVx6bk57u7bS2iZKVZ8ll1ZeH/IEQ3qFb04FB70PCNXSIp4w==" 1261 | }, 1262 | "node_modules/node.extend": { 1263 | "version": "2.0.2", 1264 | "resolved": "https://registry.npmjs.org/node.extend/-/node.extend-2.0.2.tgz", 1265 | "integrity": "sha512-pDT4Dchl94/+kkgdwyS2PauDFjZG0Hk0IcHIB+LkW27HLDtdoeMxHTxZh39DYbPP8UflWXWj9JcdDozF+YDOpQ==", 1266 | "dependencies": { 1267 | "has": "^1.0.3", 1268 | "is": "^3.2.1" 1269 | }, 1270 | "engines": { 1271 | "node": ">=0.4.0" 1272 | } 1273 | }, 1274 | "node_modules/nodemon": { 1275 | "version": "2.0.20", 1276 | "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.20.tgz", 1277 | "integrity": "sha512-Km2mWHKKY5GzRg6i1j5OxOHQtuvVsgskLfigG25yTtbyfRGn/GNvIbRyOf1PSCKJ2aT/58TiuUsuOU5UToVViw==", 1278 | "dependencies": { 1279 | "chokidar": "^3.5.2", 1280 | "debug": "^3.2.7", 1281 | "ignore-by-default": "^1.0.1", 1282 | "minimatch": "^3.1.2", 1283 | "pstree.remy": "^1.1.8", 1284 | "semver": "^5.7.1", 1285 | "simple-update-notifier": "^1.0.7", 1286 | "supports-color": "^5.5.0", 1287 | "touch": "^3.1.0", 1288 | "undefsafe": "^2.0.5" 1289 | }, 1290 | "bin": { 1291 | "nodemon": "bin/nodemon.js" 1292 | }, 1293 | "engines": { 1294 | "node": ">=8.10.0" 1295 | }, 1296 | "funding": { 1297 | "type": "opencollective", 1298 | "url": "https://opencollective.com/nodemon" 1299 | } 1300 | }, 1301 | "node_modules/nodemon/node_modules/debug": { 1302 | "version": "3.2.7", 1303 | "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", 1304 | "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", 1305 | "dependencies": { 1306 | "ms": "^2.1.1" 1307 | } 1308 | }, 1309 | "node_modules/nopt": { 1310 | "version": "1.0.10", 1311 | "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", 1312 | "integrity": "sha512-NWmpvLSqUrgrAC9HCuxEvb+PSloHpqVu+FqcO4eeF2h5qYRhA7ev6KvelyQAKtegUbC6RypJnlEOhd8vloNKYg==", 1313 | "dependencies": { 1314 | "abbrev": "1" 1315 | }, 1316 | "bin": { 1317 | "nopt": "bin/nopt.js" 1318 | }, 1319 | "engines": { 1320 | "node": "*" 1321 | } 1322 | }, 1323 | "node_modules/normalize-path": { 1324 | "version": "3.0.0", 1325 | "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", 1326 | "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", 1327 | "engines": { 1328 | "node": ">=0.10.0" 1329 | } 1330 | }, 1331 | "node_modules/oauth-sign": { 1332 | "version": "0.9.0", 1333 | "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", 1334 | "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", 1335 | "optional": true, 1336 | "engines": { 1337 | "node": "*" 1338 | } 1339 | }, 1340 | "node_modules/object-inspect": { 1341 | "version": "1.12.3", 1342 | "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", 1343 | "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==", 1344 | "funding": { 1345 | "url": "https://github.com/sponsors/ljharb" 1346 | } 1347 | }, 1348 | "node_modules/on-finished": { 1349 | "version": "2.4.1", 1350 | "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", 1351 | "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", 1352 | "dependencies": { 1353 | "ee-first": "1.1.1" 1354 | }, 1355 | "engines": { 1356 | "node": ">= 0.8" 1357 | } 1358 | }, 1359 | "node_modules/on-headers": { 1360 | "version": "1.0.2", 1361 | "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", 1362 | "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", 1363 | "engines": { 1364 | "node": ">= 0.8" 1365 | } 1366 | }, 1367 | "node_modules/parseurl": { 1368 | "version": "1.3.3", 1369 | "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", 1370 | "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", 1371 | "engines": { 1372 | "node": ">= 0.8" 1373 | } 1374 | }, 1375 | "node_modules/path-to-regexp": { 1376 | "version": "0.1.7", 1377 | "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", 1378 | "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" 1379 | }, 1380 | "node_modules/performance-now": { 1381 | "version": "2.1.0", 1382 | "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", 1383 | "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==", 1384 | "optional": true 1385 | }, 1386 | "node_modules/picomatch": { 1387 | "version": "2.3.1", 1388 | "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", 1389 | "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", 1390 | "engines": { 1391 | "node": ">=8.6" 1392 | }, 1393 | "funding": { 1394 | "url": "https://github.com/sponsors/jonschlinkert" 1395 | } 1396 | }, 1397 | "node_modules/promise": { 1398 | "version": "7.3.1", 1399 | "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz", 1400 | "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==", 1401 | "optional": true, 1402 | "dependencies": { 1403 | "asap": "~2.0.3" 1404 | } 1405 | }, 1406 | "node_modules/proxy-addr": { 1407 | "version": "2.0.7", 1408 | "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", 1409 | "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", 1410 | "dependencies": { 1411 | "forwarded": "0.2.0", 1412 | "ipaddr.js": "1.9.1" 1413 | }, 1414 | "engines": { 1415 | "node": ">= 0.10" 1416 | } 1417 | }, 1418 | "node_modules/prr": { 1419 | "version": "1.0.1", 1420 | "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", 1421 | "integrity": "sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw==", 1422 | "optional": true 1423 | }, 1424 | "node_modules/psl": { 1425 | "version": "1.9.0", 1426 | "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", 1427 | "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==", 1428 | "optional": true 1429 | }, 1430 | "node_modules/pstree.remy": { 1431 | "version": "1.1.8", 1432 | "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", 1433 | "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==" 1434 | }, 1435 | "node_modules/punycode": { 1436 | "version": "2.3.0", 1437 | "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", 1438 | "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", 1439 | "optional": true, 1440 | "engines": { 1441 | "node": ">=6" 1442 | } 1443 | }, 1444 | "node_modules/qs": { 1445 | "version": "6.11.0", 1446 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", 1447 | "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", 1448 | "dependencies": { 1449 | "side-channel": "^1.0.4" 1450 | }, 1451 | "engines": { 1452 | "node": ">=0.6" 1453 | }, 1454 | "funding": { 1455 | "url": "https://github.com/sponsors/ljharb" 1456 | } 1457 | }, 1458 | "node_modules/range-parser": { 1459 | "version": "1.2.1", 1460 | "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", 1461 | "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", 1462 | "engines": { 1463 | "node": ">= 0.6" 1464 | } 1465 | }, 1466 | "node_modules/raw-body": { 1467 | "version": "2.5.1", 1468 | "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", 1469 | "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", 1470 | "dependencies": { 1471 | "bytes": "3.1.2", 1472 | "http-errors": "2.0.0", 1473 | "iconv-lite": "0.4.24", 1474 | "unpipe": "1.0.0" 1475 | }, 1476 | "engines": { 1477 | "node": ">= 0.8" 1478 | } 1479 | }, 1480 | "node_modules/readdirp": { 1481 | "version": "3.6.0", 1482 | "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", 1483 | "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", 1484 | "dependencies": { 1485 | "picomatch": "^2.2.1" 1486 | }, 1487 | "engines": { 1488 | "node": ">=8.10.0" 1489 | } 1490 | }, 1491 | "node_modules/redis": { 1492 | "version": "4.6.4", 1493 | "resolved": "https://registry.npmjs.org/redis/-/redis-4.6.4.tgz", 1494 | "integrity": "sha512-wi2tgDdQ+Q8q+PR5FLRx4QvDiWaA+PoJbrzsyFqlClN5R4LplHqN3scs/aGjE//mbz++W19SgxiEnQ27jnCRaA==", 1495 | "dependencies": { 1496 | "@redis/bloom": "1.2.0", 1497 | "@redis/client": "1.5.5", 1498 | "@redis/graph": "1.1.0", 1499 | "@redis/json": "1.0.4", 1500 | "@redis/search": "1.1.1", 1501 | "@redis/time-series": "1.0.4" 1502 | } 1503 | }, 1504 | "node_modules/request": { 1505 | "version": "2.88.2", 1506 | "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", 1507 | "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", 1508 | "deprecated": "request has been deprecated, see https://github.com/request/request/issues/3142", 1509 | "optional": true, 1510 | "dependencies": { 1511 | "aws-sign2": "~0.7.0", 1512 | "aws4": "^1.8.0", 1513 | "caseless": "~0.12.0", 1514 | "combined-stream": "~1.0.6", 1515 | "extend": "~3.0.2", 1516 | "forever-agent": "~0.6.1", 1517 | "form-data": "~2.3.2", 1518 | "har-validator": "~5.1.3", 1519 | "http-signature": "~1.2.0", 1520 | "is-typedarray": "~1.0.0", 1521 | "isstream": "~0.1.2", 1522 | "json-stringify-safe": "~5.0.1", 1523 | "mime-types": "~2.1.19", 1524 | "oauth-sign": "~0.9.0", 1525 | "performance-now": "^2.1.0", 1526 | "qs": "~6.5.2", 1527 | "safe-buffer": "^5.1.2", 1528 | "tough-cookie": "~2.5.0", 1529 | "tunnel-agent": "^0.6.0", 1530 | "uuid": "^3.3.2" 1531 | }, 1532 | "engines": { 1533 | "node": ">= 6" 1534 | } 1535 | }, 1536 | "node_modules/request/node_modules/qs": { 1537 | "version": "6.5.3", 1538 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz", 1539 | "integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==", 1540 | "optional": true, 1541 | "engines": { 1542 | "node": ">=0.6" 1543 | } 1544 | }, 1545 | "node_modules/safe-buffer": { 1546 | "version": "5.2.1", 1547 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", 1548 | "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", 1549 | "funding": [ 1550 | { 1551 | "type": "github", 1552 | "url": "https://github.com/sponsors/feross" 1553 | }, 1554 | { 1555 | "type": "patreon", 1556 | "url": "https://www.patreon.com/feross" 1557 | }, 1558 | { 1559 | "type": "consulting", 1560 | "url": "https://feross.org/support" 1561 | } 1562 | ] 1563 | }, 1564 | "node_modules/safer-buffer": { 1565 | "version": "2.1.2", 1566 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 1567 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" 1568 | }, 1569 | "node_modules/secure-json-parse": { 1570 | "version": "2.7.0", 1571 | "resolved": "https://registry.npmjs.org/secure-json-parse/-/secure-json-parse-2.7.0.tgz", 1572 | "integrity": "sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw==" 1573 | }, 1574 | "node_modules/semver": { 1575 | "version": "5.7.1", 1576 | "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", 1577 | "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", 1578 | "bin": { 1579 | "semver": "bin/semver" 1580 | } 1581 | }, 1582 | "node_modules/send": { 1583 | "version": "0.18.0", 1584 | "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", 1585 | "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", 1586 | "dependencies": { 1587 | "debug": "2.6.9", 1588 | "depd": "2.0.0", 1589 | "destroy": "1.2.0", 1590 | "encodeurl": "~1.0.2", 1591 | "escape-html": "~1.0.3", 1592 | "etag": "~1.8.1", 1593 | "fresh": "0.5.2", 1594 | "http-errors": "2.0.0", 1595 | "mime": "1.6.0", 1596 | "ms": "2.1.3", 1597 | "on-finished": "2.4.1", 1598 | "range-parser": "~1.2.1", 1599 | "statuses": "2.0.1" 1600 | }, 1601 | "engines": { 1602 | "node": ">= 0.8.0" 1603 | } 1604 | }, 1605 | "node_modules/seq-queue": { 1606 | "version": "0.0.5", 1607 | "resolved": "https://registry.npmjs.org/seq-queue/-/seq-queue-0.0.5.tgz", 1608 | "integrity": "sha512-hr3Wtp/GZIc/6DAGPDcV4/9WoZhjrkXsi5B/07QgX8tsdc6ilr7BFM6PM6rbdAX1kFSDYeZGLipIZZKyQP0O5Q==" 1609 | }, 1610 | "node_modules/serve-favicon": { 1611 | "version": "2.4.5", 1612 | "resolved": "https://registry.npmjs.org/serve-favicon/-/serve-favicon-2.4.5.tgz", 1613 | "integrity": "sha512-s7F8h2NrslMkG50KxvlGdj+ApSwaLex0vexuJ9iFf3GLTIp1ph/l1qZvRe9T9TJEYZgmq72ZwJ2VYiAEtChknw==", 1614 | "dependencies": { 1615 | "etag": "~1.8.1", 1616 | "fresh": "0.5.2", 1617 | "ms": "2.0.0", 1618 | "parseurl": "~1.3.2", 1619 | "safe-buffer": "5.1.1" 1620 | }, 1621 | "engines": { 1622 | "node": ">= 0.8.0" 1623 | } 1624 | }, 1625 | "node_modules/serve-favicon/node_modules/ms": { 1626 | "version": "2.0.0", 1627 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 1628 | "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" 1629 | }, 1630 | "node_modules/serve-favicon/node_modules/safe-buffer": { 1631 | "version": "5.1.1", 1632 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", 1633 | "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==" 1634 | }, 1635 | "node_modules/serve-static": { 1636 | "version": "1.15.0", 1637 | "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", 1638 | "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", 1639 | "dependencies": { 1640 | "encodeurl": "~1.0.2", 1641 | "escape-html": "~1.0.3", 1642 | "parseurl": "~1.3.3", 1643 | "send": "0.18.0" 1644 | }, 1645 | "engines": { 1646 | "node": ">= 0.8.0" 1647 | } 1648 | }, 1649 | "node_modules/setprototypeof": { 1650 | "version": "1.2.0", 1651 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", 1652 | "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" 1653 | }, 1654 | "node_modules/side-channel": { 1655 | "version": "1.0.4", 1656 | "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", 1657 | "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", 1658 | "dependencies": { 1659 | "call-bind": "^1.0.0", 1660 | "get-intrinsic": "^1.0.2", 1661 | "object-inspect": "^1.9.0" 1662 | }, 1663 | "funding": { 1664 | "url": "https://github.com/sponsors/ljharb" 1665 | } 1666 | }, 1667 | "node_modules/simple-update-notifier": { 1668 | "version": "1.1.0", 1669 | "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-1.1.0.tgz", 1670 | "integrity": "sha512-VpsrsJSUcJEseSbMHkrsrAVSdvVS5I96Qo1QAQ4FxQ9wXFcB+pjj7FB7/us9+GcgfW4ziHtYMc1J0PLczb55mg==", 1671 | "dependencies": { 1672 | "semver": "~7.0.0" 1673 | }, 1674 | "engines": { 1675 | "node": ">=8.10.0" 1676 | } 1677 | }, 1678 | "node_modules/simple-update-notifier/node_modules/semver": { 1679 | "version": "7.0.0", 1680 | "resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz", 1681 | "integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==", 1682 | "bin": { 1683 | "semver": "bin/semver.js" 1684 | } 1685 | }, 1686 | "node_modules/source-map": { 1687 | "version": "0.6.1", 1688 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", 1689 | "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", 1690 | "optional": true, 1691 | "engines": { 1692 | "node": ">=0.10.0" 1693 | } 1694 | }, 1695 | "node_modules/sqlstring": { 1696 | "version": "2.3.3", 1697 | "resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.3.tgz", 1698 | "integrity": "sha512-qC9iz2FlN7DQl3+wjwn3802RTyjCx7sDvfQEXchwa6CWOx07/WVfh91gBmQ9fahw8snwGEWU3xGzOt4tFyHLxg==", 1699 | "engines": { 1700 | "node": ">= 0.6" 1701 | } 1702 | }, 1703 | "node_modules/sshpk": { 1704 | "version": "1.17.0", 1705 | "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.17.0.tgz", 1706 | "integrity": "sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ==", 1707 | "optional": true, 1708 | "dependencies": { 1709 | "asn1": "~0.2.3", 1710 | "assert-plus": "^1.0.0", 1711 | "bcrypt-pbkdf": "^1.0.0", 1712 | "dashdash": "^1.12.0", 1713 | "ecc-jsbn": "~0.1.1", 1714 | "getpass": "^0.1.1", 1715 | "jsbn": "~0.1.0", 1716 | "safer-buffer": "^2.0.2", 1717 | "tweetnacl": "~0.14.0" 1718 | }, 1719 | "bin": { 1720 | "sshpk-conv": "bin/sshpk-conv", 1721 | "sshpk-sign": "bin/sshpk-sign", 1722 | "sshpk-verify": "bin/sshpk-verify" 1723 | }, 1724 | "engines": { 1725 | "node": ">=0.10.0" 1726 | } 1727 | }, 1728 | "node_modules/statuses": { 1729 | "version": "2.0.1", 1730 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", 1731 | "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", 1732 | "engines": { 1733 | "node": ">= 0.8" 1734 | } 1735 | }, 1736 | "node_modules/streamsearch": { 1737 | "version": "1.1.0", 1738 | "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", 1739 | "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", 1740 | "engines": { 1741 | "node": ">=10.0.0" 1742 | } 1743 | }, 1744 | "node_modules/supports-color": { 1745 | "version": "5.5.0", 1746 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", 1747 | "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", 1748 | "dependencies": { 1749 | "has-flag": "^3.0.0" 1750 | }, 1751 | "engines": { 1752 | "node": ">=4" 1753 | } 1754 | }, 1755 | "node_modules/to-regex-range": { 1756 | "version": "5.0.1", 1757 | "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", 1758 | "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", 1759 | "dependencies": { 1760 | "is-number": "^7.0.0" 1761 | }, 1762 | "engines": { 1763 | "node": ">=8.0" 1764 | } 1765 | }, 1766 | "node_modules/toidentifier": { 1767 | "version": "1.0.1", 1768 | "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", 1769 | "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", 1770 | "engines": { 1771 | "node": ">=0.6" 1772 | } 1773 | }, 1774 | "node_modules/touch": { 1775 | "version": "3.1.0", 1776 | "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz", 1777 | "integrity": "sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==", 1778 | "dependencies": { 1779 | "nopt": "~1.0.10" 1780 | }, 1781 | "bin": { 1782 | "nodetouch": "bin/nodetouch.js" 1783 | } 1784 | }, 1785 | "node_modules/tough-cookie": { 1786 | "version": "2.5.0", 1787 | "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", 1788 | "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", 1789 | "optional": true, 1790 | "dependencies": { 1791 | "psl": "^1.1.28", 1792 | "punycode": "^2.1.1" 1793 | }, 1794 | "engines": { 1795 | "node": ">=0.8" 1796 | } 1797 | }, 1798 | "node_modules/tslib": { 1799 | "version": "2.5.0", 1800 | "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", 1801 | "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" 1802 | }, 1803 | "node_modules/tunnel-agent": { 1804 | "version": "0.6.0", 1805 | "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", 1806 | "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", 1807 | "optional": true, 1808 | "dependencies": { 1809 | "safe-buffer": "^5.0.1" 1810 | }, 1811 | "engines": { 1812 | "node": "*" 1813 | } 1814 | }, 1815 | "node_modules/tweetnacl": { 1816 | "version": "0.14.5", 1817 | "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", 1818 | "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==", 1819 | "optional": true 1820 | }, 1821 | "node_modules/twig": { 1822 | "version": "0.10.3", 1823 | "resolved": "https://registry.npmjs.org/twig/-/twig-0.10.3.tgz", 1824 | "integrity": "sha512-e/OJTus3EUYWbeMTPQm2DYRTsiQq8ru7uMOg69ohfwzJHpzHfme7AfytPiUJwSX66tPdFOqVBGaO1jZf2Dtmng==", 1825 | "dependencies": { 1826 | "locutus": "^2.0.5", 1827 | "minimatch": "3.0.x", 1828 | "walk": "2.3.x" 1829 | }, 1830 | "bin": { 1831 | "twigjs": "bin/twigjs" 1832 | }, 1833 | "engines": { 1834 | "node": "*" 1835 | } 1836 | }, 1837 | "node_modules/twig/node_modules/minimatch": { 1838 | "version": "3.0.8", 1839 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.8.tgz", 1840 | "integrity": "sha512-6FsRAQsxQ61mw+qP1ZzbL9Bc78x2p5OqNgNpnoAFLTrX8n5Kxph0CsnhmKKNXTWjXqU5L0pGPR7hYk+XWZr60Q==", 1841 | "dependencies": { 1842 | "brace-expansion": "^1.1.7" 1843 | }, 1844 | "engines": { 1845 | "node": "*" 1846 | } 1847 | }, 1848 | "node_modules/type-is": { 1849 | "version": "1.6.18", 1850 | "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", 1851 | "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", 1852 | "dependencies": { 1853 | "media-typer": "0.3.0", 1854 | "mime-types": "~2.1.24" 1855 | }, 1856 | "engines": { 1857 | "node": ">= 0.6" 1858 | } 1859 | }, 1860 | "node_modules/undefsafe": { 1861 | "version": "2.0.5", 1862 | "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", 1863 | "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==" 1864 | }, 1865 | "node_modules/undici": { 1866 | "version": "5.16.0", 1867 | "resolved": "https://registry.npmjs.org/undici/-/undici-5.16.0.tgz", 1868 | "integrity": "sha512-KWBOXNv6VX+oJQhchXieUznEmnJMqgXMbs0xxH2t8q/FUAWSJvOSr/rMaZKnX5RIVq7JDn0JbP4BOnKG2SGXLQ==", 1869 | "dependencies": { 1870 | "busboy": "^1.6.0" 1871 | }, 1872 | "engines": { 1873 | "node": ">=12.18" 1874 | } 1875 | }, 1876 | "node_modules/unpipe": { 1877 | "version": "1.0.0", 1878 | "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", 1879 | "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", 1880 | "engines": { 1881 | "node": ">= 0.8" 1882 | } 1883 | }, 1884 | "node_modules/uri-js": { 1885 | "version": "4.4.1", 1886 | "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", 1887 | "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", 1888 | "optional": true, 1889 | "dependencies": { 1890 | "punycode": "^2.1.0" 1891 | } 1892 | }, 1893 | "node_modules/utils-merge": { 1894 | "version": "1.0.1", 1895 | "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", 1896 | "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", 1897 | "engines": { 1898 | "node": ">= 0.4.0" 1899 | } 1900 | }, 1901 | "node_modules/uuid": { 1902 | "version": "3.4.0", 1903 | "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", 1904 | "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", 1905 | "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.", 1906 | "optional": true, 1907 | "bin": { 1908 | "uuid": "bin/uuid" 1909 | } 1910 | }, 1911 | "node_modules/vary": { 1912 | "version": "1.1.2", 1913 | "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", 1914 | "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", 1915 | "engines": { 1916 | "node": ">= 0.8" 1917 | } 1918 | }, 1919 | "node_modules/verror": { 1920 | "version": "1.10.0", 1921 | "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", 1922 | "integrity": "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==", 1923 | "engines": [ 1924 | "node >=0.6.0" 1925 | ], 1926 | "optional": true, 1927 | "dependencies": { 1928 | "assert-plus": "^1.0.0", 1929 | "core-util-is": "1.0.2", 1930 | "extsprintf": "^1.2.0" 1931 | } 1932 | }, 1933 | "node_modules/walk": { 1934 | "version": "2.3.15", 1935 | "resolved": "https://registry.npmjs.org/walk/-/walk-2.3.15.tgz", 1936 | "integrity": "sha512-4eRTBZljBfIISK1Vnt69Gvr2w/wc3U6Vtrw7qiN5iqYJPH7LElcYh/iU4XWhdCy2dZqv1ToMyYlybDylfG/5Vg==", 1937 | "dependencies": { 1938 | "foreachasync": "^3.0.0" 1939 | } 1940 | }, 1941 | "node_modules/yallist": { 1942 | "version": "4.0.0", 1943 | "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", 1944 | "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" 1945 | } 1946 | }, 1947 | "dependencies": { 1948 | "@elastic/elasticsearch": { 1949 | "version": "8.6.0", 1950 | "resolved": "https://registry.npmjs.org/@elastic/elasticsearch/-/elasticsearch-8.6.0.tgz", 1951 | "integrity": "sha512-mN5EbbgSp1rfRmQ/5Hv7jqAK8xhGJxCg7G84xje8hSefE59P+HPPCv/+DgesCUSJdZpwXIo0DwOWHfHvktxxLw==", 1952 | "requires": { 1953 | "@elastic/transport": "^8.3.1", 1954 | "tslib": "^2.4.0" 1955 | } 1956 | }, 1957 | "@elastic/transport": { 1958 | "version": "8.3.1", 1959 | "resolved": "https://registry.npmjs.org/@elastic/transport/-/transport-8.3.1.tgz", 1960 | "integrity": "sha512-jv/Yp2VLvv5tSMEOF8iGrtL2YsYHbpf4s+nDsItxUTLFTzuJGpnsB/xBlfsoT2kAYEnWHiSJuqrbRcpXEI/SEQ==", 1961 | "requires": { 1962 | "debug": "^4.3.4", 1963 | "hpagent": "^1.0.0", 1964 | "ms": "^2.1.3", 1965 | "secure-json-parse": "^2.4.0", 1966 | "tslib": "^2.4.0", 1967 | "undici": "^5.5.1" 1968 | }, 1969 | "dependencies": { 1970 | "debug": { 1971 | "version": "4.3.4", 1972 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", 1973 | "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", 1974 | "requires": { 1975 | "ms": "2.1.2" 1976 | }, 1977 | "dependencies": { 1978 | "ms": { 1979 | "version": "2.1.2", 1980 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 1981 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" 1982 | } 1983 | } 1984 | } 1985 | } 1986 | }, 1987 | "@redis/bloom": { 1988 | "version": "1.2.0", 1989 | "resolved": "https://registry.npmjs.org/@redis/bloom/-/bloom-1.2.0.tgz", 1990 | "integrity": "sha512-HG2DFjYKbpNmVXsa0keLHp/3leGJz1mjh09f2RLGGLQZzSHpkmZWuwJbAvo3QcRY8p80m5+ZdXZdYOSBLlp7Cg==", 1991 | "requires": {} 1992 | }, 1993 | "@redis/client": { 1994 | "version": "1.5.5", 1995 | "resolved": "https://registry.npmjs.org/@redis/client/-/client-1.5.5.tgz", 1996 | "integrity": "sha512-fuMnpDYSjT5JXR9rrCW1YWA4L8N/9/uS4ImT3ZEC/hcaQRI1D/9FvwjriRj1UvepIgzZXthFVKMNRzP/LNL7BQ==", 1997 | "requires": { 1998 | "cluster-key-slot": "1.1.2", 1999 | "generic-pool": "3.9.0", 2000 | "yallist": "4.0.0" 2001 | } 2002 | }, 2003 | "@redis/graph": { 2004 | "version": "1.1.0", 2005 | "resolved": "https://registry.npmjs.org/@redis/graph/-/graph-1.1.0.tgz", 2006 | "integrity": "sha512-16yZWngxyXPd+MJxeSr0dqh2AIOi8j9yXKcKCwVaKDbH3HTuETpDVPcLujhFYVPtYrngSco31BUcSa9TH31Gqg==", 2007 | "requires": {} 2008 | }, 2009 | "@redis/json": { 2010 | "version": "1.0.4", 2011 | "resolved": "https://registry.npmjs.org/@redis/json/-/json-1.0.4.tgz", 2012 | "integrity": "sha512-LUZE2Gdrhg0Rx7AN+cZkb1e6HjoSKaeeW8rYnt89Tly13GBI5eP4CwDVr+MY8BAYfCg4/N15OUrtLoona9uSgw==", 2013 | "requires": {} 2014 | }, 2015 | "@redis/search": { 2016 | "version": "1.1.1", 2017 | "resolved": "https://registry.npmjs.org/@redis/search/-/search-1.1.1.tgz", 2018 | "integrity": "sha512-pqCXTc5e7wJJgUuJiC3hBgfoFRoPxYzwn0BEfKgejTM7M/9zP3IpUcqcjgfp8hF+LoV8rHZzcNTz7V+pEIY7LQ==", 2019 | "requires": {} 2020 | }, 2021 | "@redis/time-series": { 2022 | "version": "1.0.4", 2023 | "resolved": "https://registry.npmjs.org/@redis/time-series/-/time-series-1.0.4.tgz", 2024 | "integrity": "sha512-ThUIgo2U/g7cCuZavucQTQzA9g9JbDDY2f64u3AbAoz/8vE2lt2U37LamDUVChhaDA3IRT9R6VvJwqnUfTJzng==", 2025 | "requires": {} 2026 | }, 2027 | "abbrev": { 2028 | "version": "1.1.1", 2029 | "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", 2030 | "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" 2031 | }, 2032 | "accepts": { 2033 | "version": "1.3.8", 2034 | "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", 2035 | "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", 2036 | "requires": { 2037 | "mime-types": "~2.1.34", 2038 | "negotiator": "0.6.3" 2039 | } 2040 | }, 2041 | "ajv": { 2042 | "version": "6.12.6", 2043 | "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", 2044 | "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", 2045 | "optional": true, 2046 | "requires": { 2047 | "fast-deep-equal": "^3.1.1", 2048 | "fast-json-stable-stringify": "^2.0.0", 2049 | "json-schema-traverse": "^0.4.1", 2050 | "uri-js": "^4.2.2" 2051 | } 2052 | }, 2053 | "anymatch": { 2054 | "version": "3.1.3", 2055 | "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", 2056 | "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", 2057 | "requires": { 2058 | "normalize-path": "^3.0.0", 2059 | "picomatch": "^2.0.4" 2060 | } 2061 | }, 2062 | "array-flatten": { 2063 | "version": "1.1.1", 2064 | "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", 2065 | "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" 2066 | }, 2067 | "asap": { 2068 | "version": "2.0.6", 2069 | "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", 2070 | "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==", 2071 | "optional": true 2072 | }, 2073 | "asn1": { 2074 | "version": "0.2.6", 2075 | "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", 2076 | "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", 2077 | "optional": true, 2078 | "requires": { 2079 | "safer-buffer": "~2.1.0" 2080 | } 2081 | }, 2082 | "assert-plus": { 2083 | "version": "1.0.0", 2084 | "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", 2085 | "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==", 2086 | "optional": true 2087 | }, 2088 | "async": { 2089 | "version": "2.6.4", 2090 | "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", 2091 | "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", 2092 | "requires": { 2093 | "lodash": "^4.17.14" 2094 | } 2095 | }, 2096 | "asynckit": { 2097 | "version": "0.4.0", 2098 | "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", 2099 | "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", 2100 | "optional": true 2101 | }, 2102 | "aws-sign2": { 2103 | "version": "0.7.0", 2104 | "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", 2105 | "integrity": "sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==", 2106 | "optional": true 2107 | }, 2108 | "aws4": { 2109 | "version": "1.12.0", 2110 | "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.12.0.tgz", 2111 | "integrity": "sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg==", 2112 | "optional": true 2113 | }, 2114 | "balanced-match": { 2115 | "version": "1.0.2", 2116 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", 2117 | "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" 2118 | }, 2119 | "basic-auth": { 2120 | "version": "2.0.1", 2121 | "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz", 2122 | "integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==", 2123 | "requires": { 2124 | "safe-buffer": "5.1.2" 2125 | }, 2126 | "dependencies": { 2127 | "safe-buffer": { 2128 | "version": "5.1.2", 2129 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", 2130 | "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" 2131 | } 2132 | } 2133 | }, 2134 | "bcrypt-pbkdf": { 2135 | "version": "1.0.2", 2136 | "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", 2137 | "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==", 2138 | "optional": true, 2139 | "requires": { 2140 | "tweetnacl": "^0.14.3" 2141 | } 2142 | }, 2143 | "binary-extensions": { 2144 | "version": "2.2.0", 2145 | "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", 2146 | "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==" 2147 | }, 2148 | "blueimp-md5": { 2149 | "version": "2.19.0", 2150 | "resolved": "https://registry.npmjs.org/blueimp-md5/-/blueimp-md5-2.19.0.tgz", 2151 | "integrity": "sha512-DRQrD6gJyy8FbiE4s+bDoXS9hiW3Vbx5uCdwvcCf3zLHL+Iv7LtGHLpr+GZV8rHG8tK766FGYBwRbu8pELTt+w==" 2152 | }, 2153 | "body-parser": { 2154 | "version": "1.20.1", 2155 | "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", 2156 | "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", 2157 | "requires": { 2158 | "bytes": "3.1.2", 2159 | "content-type": "~1.0.4", 2160 | "debug": "2.6.9", 2161 | "depd": "2.0.0", 2162 | "destroy": "1.2.0", 2163 | "http-errors": "2.0.0", 2164 | "iconv-lite": "0.4.24", 2165 | "on-finished": "2.4.1", 2166 | "qs": "6.11.0", 2167 | "raw-body": "2.5.1", 2168 | "type-is": "~1.6.18", 2169 | "unpipe": "1.0.0" 2170 | } 2171 | }, 2172 | "brace-expansion": { 2173 | "version": "1.1.11", 2174 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", 2175 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", 2176 | "requires": { 2177 | "balanced-match": "^1.0.0", 2178 | "concat-map": "0.0.1" 2179 | } 2180 | }, 2181 | "braces": { 2182 | "version": "3.0.2", 2183 | "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", 2184 | "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", 2185 | "requires": { 2186 | "fill-range": "^7.0.1" 2187 | } 2188 | }, 2189 | "busboy": { 2190 | "version": "1.6.0", 2191 | "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", 2192 | "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", 2193 | "requires": { 2194 | "streamsearch": "^1.1.0" 2195 | } 2196 | }, 2197 | "bytes": { 2198 | "version": "3.1.2", 2199 | "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", 2200 | "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==" 2201 | }, 2202 | "call-bind": { 2203 | "version": "1.0.2", 2204 | "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", 2205 | "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", 2206 | "requires": { 2207 | "function-bind": "^1.1.1", 2208 | "get-intrinsic": "^1.0.2" 2209 | } 2210 | }, 2211 | "caseless": { 2212 | "version": "0.12.0", 2213 | "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", 2214 | "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==", 2215 | "optional": true 2216 | }, 2217 | "chokidar": { 2218 | "version": "3.5.3", 2219 | "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", 2220 | "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", 2221 | "requires": { 2222 | "anymatch": "~3.1.2", 2223 | "braces": "~3.0.2", 2224 | "fsevents": "~2.3.2", 2225 | "glob-parent": "~5.1.2", 2226 | "is-binary-path": "~2.1.0", 2227 | "is-glob": "~4.0.1", 2228 | "normalize-path": "~3.0.0", 2229 | "readdirp": "~3.6.0" 2230 | } 2231 | }, 2232 | "cluster-key-slot": { 2233 | "version": "1.1.2", 2234 | "resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.2.tgz", 2235 | "integrity": "sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA==" 2236 | }, 2237 | "combined-stream": { 2238 | "version": "1.0.8", 2239 | "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", 2240 | "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", 2241 | "optional": true, 2242 | "requires": { 2243 | "delayed-stream": "~1.0.0" 2244 | } 2245 | }, 2246 | "concat-map": { 2247 | "version": "0.0.1", 2248 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 2249 | "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" 2250 | }, 2251 | "content-disposition": { 2252 | "version": "0.5.4", 2253 | "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", 2254 | "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", 2255 | "requires": { 2256 | "safe-buffer": "5.2.1" 2257 | } 2258 | }, 2259 | "content-type": { 2260 | "version": "1.0.5", 2261 | "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", 2262 | "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==" 2263 | }, 2264 | "cookie": { 2265 | "version": "0.4.1", 2266 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz", 2267 | "integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==" 2268 | }, 2269 | "cookie-parser": { 2270 | "version": "1.4.6", 2271 | "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.6.tgz", 2272 | "integrity": "sha512-z3IzaNjdwUC2olLIB5/ITd0/setiaFMLYiZJle7xg5Fe9KWAceil7xszYfHHBtDFYLSgJduS2Ty0P1uJdPDJeA==", 2273 | "requires": { 2274 | "cookie": "0.4.1", 2275 | "cookie-signature": "1.0.6" 2276 | } 2277 | }, 2278 | "cookie-signature": { 2279 | "version": "1.0.6", 2280 | "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", 2281 | "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" 2282 | }, 2283 | "core-util-is": { 2284 | "version": "1.0.2", 2285 | "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", 2286 | "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==", 2287 | "optional": true 2288 | }, 2289 | "dashdash": { 2290 | "version": "1.14.1", 2291 | "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", 2292 | "integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==", 2293 | "optional": true, 2294 | "requires": { 2295 | "assert-plus": "^1.0.0" 2296 | } 2297 | }, 2298 | "debug": { 2299 | "version": "2.6.9", 2300 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 2301 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 2302 | "requires": { 2303 | "ms": "2.0.0" 2304 | }, 2305 | "dependencies": { 2306 | "ms": { 2307 | "version": "2.0.0", 2308 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 2309 | "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" 2310 | } 2311 | } 2312 | }, 2313 | "delayed-stream": { 2314 | "version": "1.0.0", 2315 | "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", 2316 | "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", 2317 | "optional": true 2318 | }, 2319 | "denque": { 2320 | "version": "2.1.0", 2321 | "resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz", 2322 | "integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==" 2323 | }, 2324 | "depd": { 2325 | "version": "2.0.0", 2326 | "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", 2327 | "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" 2328 | }, 2329 | "destroy": { 2330 | "version": "1.2.0", 2331 | "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", 2332 | "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==" 2333 | }, 2334 | "dotenv": { 2335 | "version": "4.0.0", 2336 | "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-4.0.0.tgz", 2337 | "integrity": "sha512-XcaMACOr3JMVcEv0Y/iUM2XaOsATRZ3U1In41/1jjK6vJZ2PZbQ1bzCG8uvaByfaBpl9gqc9QWJovpUGBXLLYQ==" 2338 | }, 2339 | "ecc-jsbn": { 2340 | "version": "0.1.2", 2341 | "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", 2342 | "integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==", 2343 | "optional": true, 2344 | "requires": { 2345 | "jsbn": "~0.1.0", 2346 | "safer-buffer": "^2.1.0" 2347 | } 2348 | }, 2349 | "ee-first": { 2350 | "version": "1.1.1", 2351 | "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", 2352 | "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" 2353 | }, 2354 | "encodeurl": { 2355 | "version": "1.0.2", 2356 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", 2357 | "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==" 2358 | }, 2359 | "errno": { 2360 | "version": "0.1.8", 2361 | "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.8.tgz", 2362 | "integrity": "sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==", 2363 | "optional": true, 2364 | "requires": { 2365 | "prr": "~1.0.1" 2366 | } 2367 | }, 2368 | "escape-html": { 2369 | "version": "1.0.3", 2370 | "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", 2371 | "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" 2372 | }, 2373 | "etag": { 2374 | "version": "1.8.1", 2375 | "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", 2376 | "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==" 2377 | }, 2378 | "express": { 2379 | "version": "4.18.2", 2380 | "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", 2381 | "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==", 2382 | "requires": { 2383 | "accepts": "~1.3.8", 2384 | "array-flatten": "1.1.1", 2385 | "body-parser": "1.20.1", 2386 | "content-disposition": "0.5.4", 2387 | "content-type": "~1.0.4", 2388 | "cookie": "0.5.0", 2389 | "cookie-signature": "1.0.6", 2390 | "debug": "2.6.9", 2391 | "depd": "2.0.0", 2392 | "encodeurl": "~1.0.2", 2393 | "escape-html": "~1.0.3", 2394 | "etag": "~1.8.1", 2395 | "finalhandler": "1.2.0", 2396 | "fresh": "0.5.2", 2397 | "http-errors": "2.0.0", 2398 | "merge-descriptors": "1.0.1", 2399 | "methods": "~1.1.2", 2400 | "on-finished": "2.4.1", 2401 | "parseurl": "~1.3.3", 2402 | "path-to-regexp": "0.1.7", 2403 | "proxy-addr": "~2.0.7", 2404 | "qs": "6.11.0", 2405 | "range-parser": "~1.2.1", 2406 | "safe-buffer": "5.2.1", 2407 | "send": "0.18.0", 2408 | "serve-static": "1.15.0", 2409 | "setprototypeof": "1.2.0", 2410 | "statuses": "2.0.1", 2411 | "type-is": "~1.6.18", 2412 | "utils-merge": "1.0.1", 2413 | "vary": "~1.1.2" 2414 | }, 2415 | "dependencies": { 2416 | "cookie": { 2417 | "version": "0.5.0", 2418 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", 2419 | "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==" 2420 | } 2421 | } 2422 | }, 2423 | "extend": { 2424 | "version": "3.0.2", 2425 | "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", 2426 | "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" 2427 | }, 2428 | "extsprintf": { 2429 | "version": "1.3.0", 2430 | "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", 2431 | "integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==", 2432 | "optional": true 2433 | }, 2434 | "fast-deep-equal": { 2435 | "version": "3.1.3", 2436 | "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", 2437 | "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", 2438 | "optional": true 2439 | }, 2440 | "fast-json-stable-stringify": { 2441 | "version": "2.1.0", 2442 | "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", 2443 | "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", 2444 | "optional": true 2445 | }, 2446 | "fill-range": { 2447 | "version": "7.0.1", 2448 | "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", 2449 | "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", 2450 | "requires": { 2451 | "to-regex-range": "^5.0.1" 2452 | } 2453 | }, 2454 | "finalhandler": { 2455 | "version": "1.2.0", 2456 | "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", 2457 | "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", 2458 | "requires": { 2459 | "debug": "2.6.9", 2460 | "encodeurl": "~1.0.2", 2461 | "escape-html": "~1.0.3", 2462 | "on-finished": "2.4.1", 2463 | "parseurl": "~1.3.3", 2464 | "statuses": "2.0.1", 2465 | "unpipe": "~1.0.0" 2466 | } 2467 | }, 2468 | "foreachasync": { 2469 | "version": "3.0.0", 2470 | "resolved": "https://registry.npmjs.org/foreachasync/-/foreachasync-3.0.0.tgz", 2471 | "integrity": "sha512-J+ler7Ta54FwwNcx6wQRDhTIbNeyDcARMkOcguEqnEdtm0jKvN3Li3PDAb2Du3ubJYEWfYL83XMROXdsXAXycw==" 2472 | }, 2473 | "forever-agent": { 2474 | "version": "0.6.1", 2475 | "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", 2476 | "integrity": "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==", 2477 | "optional": true 2478 | }, 2479 | "form-data": { 2480 | "version": "2.3.3", 2481 | "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", 2482 | "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", 2483 | "optional": true, 2484 | "requires": { 2485 | "asynckit": "^0.4.0", 2486 | "combined-stream": "^1.0.6", 2487 | "mime-types": "^2.1.12" 2488 | } 2489 | }, 2490 | "forwarded": { 2491 | "version": "0.2.0", 2492 | "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", 2493 | "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==" 2494 | }, 2495 | "fresh": { 2496 | "version": "0.5.2", 2497 | "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", 2498 | "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==" 2499 | }, 2500 | "fsevents": { 2501 | "version": "2.3.2", 2502 | "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", 2503 | "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", 2504 | "optional": true 2505 | }, 2506 | "function-bind": { 2507 | "version": "1.1.1", 2508 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", 2509 | "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" 2510 | }, 2511 | "generate-function": { 2512 | "version": "2.3.1", 2513 | "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.3.1.tgz", 2514 | "integrity": "sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==", 2515 | "requires": { 2516 | "is-property": "^1.0.2" 2517 | } 2518 | }, 2519 | "generic-pool": { 2520 | "version": "3.9.0", 2521 | "resolved": "https://registry.npmjs.org/generic-pool/-/generic-pool-3.9.0.tgz", 2522 | "integrity": "sha512-hymDOu5B53XvN4QT9dBmZxPX4CWhBPPLguTZ9MMFeFa/Kg0xWVfylOVNlJji/E7yTZWFd/q9GO5TxDLq156D7g==" 2523 | }, 2524 | "get-intrinsic": { 2525 | "version": "1.2.0", 2526 | "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.0.tgz", 2527 | "integrity": "sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==", 2528 | "requires": { 2529 | "function-bind": "^1.1.1", 2530 | "has": "^1.0.3", 2531 | "has-symbols": "^1.0.3" 2532 | } 2533 | }, 2534 | "getpass": { 2535 | "version": "0.1.7", 2536 | "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", 2537 | "integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==", 2538 | "optional": true, 2539 | "requires": { 2540 | "assert-plus": "^1.0.0" 2541 | } 2542 | }, 2543 | "glob-parent": { 2544 | "version": "5.1.2", 2545 | "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", 2546 | "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", 2547 | "requires": { 2548 | "is-glob": "^4.0.1" 2549 | } 2550 | }, 2551 | "graceful-fs": { 2552 | "version": "4.2.10", 2553 | "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", 2554 | "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", 2555 | "optional": true 2556 | }, 2557 | "har-schema": { 2558 | "version": "2.0.0", 2559 | "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", 2560 | "integrity": "sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q==", 2561 | "optional": true 2562 | }, 2563 | "har-validator": { 2564 | "version": "5.1.5", 2565 | "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", 2566 | "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", 2567 | "optional": true, 2568 | "requires": { 2569 | "ajv": "^6.12.3", 2570 | "har-schema": "^2.0.0" 2571 | } 2572 | }, 2573 | "has": { 2574 | "version": "1.0.3", 2575 | "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", 2576 | "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", 2577 | "requires": { 2578 | "function-bind": "^1.1.1" 2579 | } 2580 | }, 2581 | "has-flag": { 2582 | "version": "3.0.0", 2583 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", 2584 | "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==" 2585 | }, 2586 | "has-symbols": { 2587 | "version": "1.0.3", 2588 | "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", 2589 | "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==" 2590 | }, 2591 | "hkulekci-simple-redis-queue": { 2592 | "version": "0.9.8", 2593 | "resolved": "https://registry.npmjs.org/hkulekci-simple-redis-queue/-/hkulekci-simple-redis-queue-0.9.8.tgz", 2594 | "integrity": "sha512-fbIoHJUoh4cWAnpyrenEKDqnGFgLHekHMsz0TTAZz/9QZeuVh1qPdEVrTizy8h32PAoE0zgMfdsWmlwjn7doGQ==", 2595 | "requires": { 2596 | "redis": "^4.6.4" 2597 | } 2598 | }, 2599 | "hpagent": { 2600 | "version": "1.2.0", 2601 | "resolved": "https://registry.npmjs.org/hpagent/-/hpagent-1.2.0.tgz", 2602 | "integrity": "sha512-A91dYTeIB6NoXG+PxTQpCCDDnfHsW9kc06Lvpu1TEe9gnd6ZFeiBoRO9JvzEv6xK7EX97/dUE8g/vBMTqTS3CA==" 2603 | }, 2604 | "http-errors": { 2605 | "version": "2.0.0", 2606 | "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", 2607 | "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", 2608 | "requires": { 2609 | "depd": "2.0.0", 2610 | "inherits": "2.0.4", 2611 | "setprototypeof": "1.2.0", 2612 | "statuses": "2.0.1", 2613 | "toidentifier": "1.0.1" 2614 | } 2615 | }, 2616 | "http-signature": { 2617 | "version": "1.2.0", 2618 | "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", 2619 | "integrity": "sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ==", 2620 | "optional": true, 2621 | "requires": { 2622 | "assert-plus": "^1.0.0", 2623 | "jsprim": "^1.2.2", 2624 | "sshpk": "^1.7.0" 2625 | } 2626 | }, 2627 | "iconv-lite": { 2628 | "version": "0.4.24", 2629 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", 2630 | "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", 2631 | "requires": { 2632 | "safer-buffer": ">= 2.1.2 < 3" 2633 | } 2634 | }, 2635 | "ignore-by-default": { 2636 | "version": "1.0.1", 2637 | "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", 2638 | "integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==" 2639 | }, 2640 | "image-size": { 2641 | "version": "0.5.5", 2642 | "resolved": "https://registry.npmjs.org/image-size/-/image-size-0.5.5.tgz", 2643 | "integrity": "sha512-6TDAlDPZxUFCv+fuOkIoXT/V/f3Qbq8e37p+YOiYrUv3v9cc3/6x78VdfPgFVaB9dZYeLUfKgHRebpkm/oP2VQ==", 2644 | "optional": true 2645 | }, 2646 | "inherits": { 2647 | "version": "2.0.4", 2648 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 2649 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" 2650 | }, 2651 | "ipaddr.js": { 2652 | "version": "1.9.1", 2653 | "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", 2654 | "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==" 2655 | }, 2656 | "is": { 2657 | "version": "3.3.0", 2658 | "resolved": "https://registry.npmjs.org/is/-/is-3.3.0.tgz", 2659 | "integrity": "sha512-nW24QBoPcFGGHJGUwnfpI7Yc5CdqWNdsyHQszVE/z2pKHXzh7FZ5GWhJqSyaQ9wMkQnsTx+kAI8bHlCX4tKdbg==" 2660 | }, 2661 | "is-binary-path": { 2662 | "version": "2.1.0", 2663 | "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", 2664 | "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", 2665 | "requires": { 2666 | "binary-extensions": "^2.0.0" 2667 | } 2668 | }, 2669 | "is-extglob": { 2670 | "version": "2.1.1", 2671 | "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", 2672 | "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==" 2673 | }, 2674 | "is-glob": { 2675 | "version": "4.0.3", 2676 | "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", 2677 | "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", 2678 | "requires": { 2679 | "is-extglob": "^2.1.1" 2680 | } 2681 | }, 2682 | "is-number": { 2683 | "version": "7.0.0", 2684 | "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", 2685 | "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" 2686 | }, 2687 | "is-property": { 2688 | "version": "1.0.2", 2689 | "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", 2690 | "integrity": "sha512-Ks/IoX00TtClbGQr4TWXemAnktAQvYB7HzcCxDGqEZU6oCmb2INHuOoKxbtR+HFkmYWBKv/dOZtGRiAjDhj92g==" 2691 | }, 2692 | "is-typedarray": { 2693 | "version": "1.0.0", 2694 | "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", 2695 | "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==", 2696 | "optional": true 2697 | }, 2698 | "isstream": { 2699 | "version": "0.1.2", 2700 | "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", 2701 | "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==", 2702 | "optional": true 2703 | }, 2704 | "jsbn": { 2705 | "version": "0.1.1", 2706 | "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", 2707 | "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==", 2708 | "optional": true 2709 | }, 2710 | "json-schema": { 2711 | "version": "0.4.0", 2712 | "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", 2713 | "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==", 2714 | "optional": true 2715 | }, 2716 | "json-schema-traverse": { 2717 | "version": "0.4.1", 2718 | "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", 2719 | "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", 2720 | "optional": true 2721 | }, 2722 | "json-stringify-safe": { 2723 | "version": "5.0.1", 2724 | "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", 2725 | "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", 2726 | "optional": true 2727 | }, 2728 | "jsprim": { 2729 | "version": "1.4.2", 2730 | "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz", 2731 | "integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==", 2732 | "optional": true, 2733 | "requires": { 2734 | "assert-plus": "1.0.0", 2735 | "extsprintf": "1.3.0", 2736 | "json-schema": "0.4.0", 2737 | "verror": "1.10.0" 2738 | } 2739 | }, 2740 | "less": { 2741 | "version": "3.0.4", 2742 | "resolved": "https://registry.npmjs.org/less/-/less-3.0.4.tgz", 2743 | "integrity": "sha512-q3SyEnPKbk9zh4l36PGeW2fgynKu+FpbhiUNx/yaiBUQ3V0CbACCgb9FzYWcRgI2DJlP6eI4jc8XPrCTi55YcQ==", 2744 | "requires": { 2745 | "errno": "^0.1.1", 2746 | "graceful-fs": "^4.1.2", 2747 | "image-size": "~0.5.0", 2748 | "mime": "^1.4.1", 2749 | "mkdirp": "^0.5.0", 2750 | "promise": "^7.1.1", 2751 | "request": "^2.83.0", 2752 | "source-map": "~0.6.0" 2753 | } 2754 | }, 2755 | "less-middleware": { 2756 | "version": "3.0.1", 2757 | "resolved": "https://registry.npmjs.org/less-middleware/-/less-middleware-3.0.1.tgz", 2758 | "integrity": "sha512-FCG4zGd7c/lKMWGDzzkfU9Lcndfjc4TcSnuRwUtJ4E+NxPMuDGe7lJA1rOn+SI9x2lak+s4b6sQkcPa45eqKiw==", 2759 | "requires": { 2760 | "less": "~3.0.4", 2761 | "mkdirp": "~0.5.1", 2762 | "node.extend": "~2.0.0" 2763 | } 2764 | }, 2765 | "locutus": { 2766 | "version": "2.0.16", 2767 | "resolved": "https://registry.npmjs.org/locutus/-/locutus-2.0.16.tgz", 2768 | "integrity": "sha512-pGfl6Hb/1mXLzrX5kl5lH7gz25ey0vwQssZp8Qo2CEF59di6KrAgdFm+0pW8ghLnvNzzJGj5tlWhhv2QbK3jeQ==" 2769 | }, 2770 | "lodash": { 2771 | "version": "4.17.21", 2772 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", 2773 | "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" 2774 | }, 2775 | "long": { 2776 | "version": "5.2.1", 2777 | "resolved": "https://registry.npmjs.org/long/-/long-5.2.1.tgz", 2778 | "integrity": "sha512-GKSNGeNAtw8IryjjkhZxuKB3JzlcLTwjtiQCHKvqQet81I93kXslhDQruGI/QsddO83mcDToBVy7GqGS/zYf/A==" 2779 | }, 2780 | "lru-cache": { 2781 | "version": "7.14.1", 2782 | "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.14.1.tgz", 2783 | "integrity": "sha512-ysxwsnTKdAx96aTRdhDOCQfDgbHnt8SK0KY8SEjO0wHinhWOFTESbjVCMPbU1uGXg/ch4lifqx0wfjOawU2+WA==" 2784 | }, 2785 | "media-typer": { 2786 | "version": "0.3.0", 2787 | "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", 2788 | "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==" 2789 | }, 2790 | "merge-descriptors": { 2791 | "version": "1.0.1", 2792 | "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", 2793 | "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" 2794 | }, 2795 | "methods": { 2796 | "version": "1.1.2", 2797 | "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", 2798 | "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==" 2799 | }, 2800 | "mime": { 2801 | "version": "1.6.0", 2802 | "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", 2803 | "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" 2804 | }, 2805 | "mime-db": { 2806 | "version": "1.52.0", 2807 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", 2808 | "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" 2809 | }, 2810 | "mime-types": { 2811 | "version": "2.1.35", 2812 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", 2813 | "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", 2814 | "requires": { 2815 | "mime-db": "1.52.0" 2816 | } 2817 | }, 2818 | "minimatch": { 2819 | "version": "3.1.2", 2820 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", 2821 | "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", 2822 | "requires": { 2823 | "brace-expansion": "^1.1.7" 2824 | } 2825 | }, 2826 | "minimist": { 2827 | "version": "1.2.7", 2828 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.7.tgz", 2829 | "integrity": "sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g==" 2830 | }, 2831 | "mkdirp": { 2832 | "version": "0.5.6", 2833 | "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", 2834 | "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", 2835 | "requires": { 2836 | "minimist": "^1.2.6" 2837 | } 2838 | }, 2839 | "morgan": { 2840 | "version": "1.10.0", 2841 | "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.10.0.tgz", 2842 | "integrity": "sha512-AbegBVI4sh6El+1gNwvD5YIck7nSA36weD7xvIxG4in80j/UoK8AEGaWnnz8v1GxonMCltmlNs5ZKbGvl9b1XQ==", 2843 | "requires": { 2844 | "basic-auth": "~2.0.1", 2845 | "debug": "2.6.9", 2846 | "depd": "~2.0.0", 2847 | "on-finished": "~2.3.0", 2848 | "on-headers": "~1.0.2" 2849 | }, 2850 | "dependencies": { 2851 | "on-finished": { 2852 | "version": "2.3.0", 2853 | "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", 2854 | "integrity": "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==", 2855 | "requires": { 2856 | "ee-first": "1.1.1" 2857 | } 2858 | } 2859 | } 2860 | }, 2861 | "ms": { 2862 | "version": "2.1.3", 2863 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", 2864 | "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" 2865 | }, 2866 | "mysql2": { 2867 | "version": "3.1.0", 2868 | "resolved": "https://registry.npmjs.org/mysql2/-/mysql2-3.1.0.tgz", 2869 | "integrity": "sha512-woMeIog21X72RcFLhE/xajhUdnwRMd6Oq16S7/O2qJ5lPUDfFwgSW+xhx7TjzcM8PU3q+dVsryIaDi+HyQR/0A==", 2870 | "requires": { 2871 | "denque": "^2.1.0", 2872 | "generate-function": "^2.3.1", 2873 | "iconv-lite": "^0.6.3", 2874 | "long": "^5.2.1", 2875 | "lru-cache": "^7.14.1", 2876 | "named-placeholders": "^1.1.3", 2877 | "seq-queue": "^0.0.5", 2878 | "sqlstring": "^2.3.2" 2879 | }, 2880 | "dependencies": { 2881 | "iconv-lite": { 2882 | "version": "0.6.3", 2883 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", 2884 | "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", 2885 | "requires": { 2886 | "safer-buffer": ">= 2.1.2 < 3.0.0" 2887 | } 2888 | } 2889 | } 2890 | }, 2891 | "named-placeholders": { 2892 | "version": "1.1.3", 2893 | "resolved": "https://registry.npmjs.org/named-placeholders/-/named-placeholders-1.1.3.tgz", 2894 | "integrity": "sha512-eLoBxg6wE/rZkJPhU/xRX1WTpkFEwDJEN96oxFrTsqBdbT5ec295Q+CoHrL9IT0DipqKhmGcaZmwOt8OON5x1w==", 2895 | "requires": { 2896 | "lru-cache": "^7.14.1" 2897 | } 2898 | }, 2899 | "negotiator": { 2900 | "version": "0.6.3", 2901 | "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", 2902 | "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==" 2903 | }, 2904 | "node-datetime": { 2905 | "version": "2.1.2", 2906 | "resolved": "https://registry.npmjs.org/node-datetime/-/node-datetime-2.1.2.tgz", 2907 | "integrity": "sha512-eev1F0IPKSu3zvASMtH8ic4znGpfXdq9yc8yc/EVx6bk57u7bS2iZKVZ8ll1ZeH/IEQ3qFb04FB70PCNXSIp4w==" 2908 | }, 2909 | "node.extend": { 2910 | "version": "2.0.2", 2911 | "resolved": "https://registry.npmjs.org/node.extend/-/node.extend-2.0.2.tgz", 2912 | "integrity": "sha512-pDT4Dchl94/+kkgdwyS2PauDFjZG0Hk0IcHIB+LkW27HLDtdoeMxHTxZh39DYbPP8UflWXWj9JcdDozF+YDOpQ==", 2913 | "requires": { 2914 | "has": "^1.0.3", 2915 | "is": "^3.2.1" 2916 | } 2917 | }, 2918 | "nodemon": { 2919 | "version": "2.0.20", 2920 | "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.20.tgz", 2921 | "integrity": "sha512-Km2mWHKKY5GzRg6i1j5OxOHQtuvVsgskLfigG25yTtbyfRGn/GNvIbRyOf1PSCKJ2aT/58TiuUsuOU5UToVViw==", 2922 | "requires": { 2923 | "chokidar": "^3.5.2", 2924 | "debug": "^3.2.7", 2925 | "ignore-by-default": "^1.0.1", 2926 | "minimatch": "^3.1.2", 2927 | "pstree.remy": "^1.1.8", 2928 | "semver": "^5.7.1", 2929 | "simple-update-notifier": "^1.0.7", 2930 | "supports-color": "^5.5.0", 2931 | "touch": "^3.1.0", 2932 | "undefsafe": "^2.0.5" 2933 | }, 2934 | "dependencies": { 2935 | "debug": { 2936 | "version": "3.2.7", 2937 | "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", 2938 | "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", 2939 | "requires": { 2940 | "ms": "^2.1.1" 2941 | } 2942 | } 2943 | } 2944 | }, 2945 | "nopt": { 2946 | "version": "1.0.10", 2947 | "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", 2948 | "integrity": "sha512-NWmpvLSqUrgrAC9HCuxEvb+PSloHpqVu+FqcO4eeF2h5qYRhA7ev6KvelyQAKtegUbC6RypJnlEOhd8vloNKYg==", 2949 | "requires": { 2950 | "abbrev": "1" 2951 | } 2952 | }, 2953 | "normalize-path": { 2954 | "version": "3.0.0", 2955 | "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", 2956 | "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==" 2957 | }, 2958 | "oauth-sign": { 2959 | "version": "0.9.0", 2960 | "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", 2961 | "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", 2962 | "optional": true 2963 | }, 2964 | "object-inspect": { 2965 | "version": "1.12.3", 2966 | "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", 2967 | "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==" 2968 | }, 2969 | "on-finished": { 2970 | "version": "2.4.1", 2971 | "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", 2972 | "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", 2973 | "requires": { 2974 | "ee-first": "1.1.1" 2975 | } 2976 | }, 2977 | "on-headers": { 2978 | "version": "1.0.2", 2979 | "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", 2980 | "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==" 2981 | }, 2982 | "parseurl": { 2983 | "version": "1.3.3", 2984 | "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", 2985 | "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" 2986 | }, 2987 | "path-to-regexp": { 2988 | "version": "0.1.7", 2989 | "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", 2990 | "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" 2991 | }, 2992 | "performance-now": { 2993 | "version": "2.1.0", 2994 | "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", 2995 | "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==", 2996 | "optional": true 2997 | }, 2998 | "picomatch": { 2999 | "version": "2.3.1", 3000 | "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", 3001 | "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==" 3002 | }, 3003 | "promise": { 3004 | "version": "7.3.1", 3005 | "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz", 3006 | "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==", 3007 | "optional": true, 3008 | "requires": { 3009 | "asap": "~2.0.3" 3010 | } 3011 | }, 3012 | "proxy-addr": { 3013 | "version": "2.0.7", 3014 | "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", 3015 | "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", 3016 | "requires": { 3017 | "forwarded": "0.2.0", 3018 | "ipaddr.js": "1.9.1" 3019 | } 3020 | }, 3021 | "prr": { 3022 | "version": "1.0.1", 3023 | "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", 3024 | "integrity": "sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw==", 3025 | "optional": true 3026 | }, 3027 | "psl": { 3028 | "version": "1.9.0", 3029 | "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", 3030 | "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==", 3031 | "optional": true 3032 | }, 3033 | "pstree.remy": { 3034 | "version": "1.1.8", 3035 | "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", 3036 | "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==" 3037 | }, 3038 | "punycode": { 3039 | "version": "2.3.0", 3040 | "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", 3041 | "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", 3042 | "optional": true 3043 | }, 3044 | "qs": { 3045 | "version": "6.11.0", 3046 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", 3047 | "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", 3048 | "requires": { 3049 | "side-channel": "^1.0.4" 3050 | } 3051 | }, 3052 | "range-parser": { 3053 | "version": "1.2.1", 3054 | "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", 3055 | "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" 3056 | }, 3057 | "raw-body": { 3058 | "version": "2.5.1", 3059 | "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", 3060 | "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", 3061 | "requires": { 3062 | "bytes": "3.1.2", 3063 | "http-errors": "2.0.0", 3064 | "iconv-lite": "0.4.24", 3065 | "unpipe": "1.0.0" 3066 | } 3067 | }, 3068 | "readdirp": { 3069 | "version": "3.6.0", 3070 | "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", 3071 | "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", 3072 | "requires": { 3073 | "picomatch": "^2.2.1" 3074 | } 3075 | }, 3076 | "redis": { 3077 | "version": "4.6.4", 3078 | "resolved": "https://registry.npmjs.org/redis/-/redis-4.6.4.tgz", 3079 | "integrity": "sha512-wi2tgDdQ+Q8q+PR5FLRx4QvDiWaA+PoJbrzsyFqlClN5R4LplHqN3scs/aGjE//mbz++W19SgxiEnQ27jnCRaA==", 3080 | "requires": { 3081 | "@redis/bloom": "1.2.0", 3082 | "@redis/client": "1.5.5", 3083 | "@redis/graph": "1.1.0", 3084 | "@redis/json": "1.0.4", 3085 | "@redis/search": "1.1.1", 3086 | "@redis/time-series": "1.0.4" 3087 | } 3088 | }, 3089 | "request": { 3090 | "version": "2.88.2", 3091 | "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", 3092 | "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", 3093 | "optional": true, 3094 | "requires": { 3095 | "aws-sign2": "~0.7.0", 3096 | "aws4": "^1.8.0", 3097 | "caseless": "~0.12.0", 3098 | "combined-stream": "~1.0.6", 3099 | "extend": "~3.0.2", 3100 | "forever-agent": "~0.6.1", 3101 | "form-data": "~2.3.2", 3102 | "har-validator": "~5.1.3", 3103 | "http-signature": "~1.2.0", 3104 | "is-typedarray": "~1.0.0", 3105 | "isstream": "~0.1.2", 3106 | "json-stringify-safe": "~5.0.1", 3107 | "mime-types": "~2.1.19", 3108 | "oauth-sign": "~0.9.0", 3109 | "performance-now": "^2.1.0", 3110 | "qs": "~6.5.2", 3111 | "safe-buffer": "^5.1.2", 3112 | "tough-cookie": "~2.5.0", 3113 | "tunnel-agent": "^0.6.0", 3114 | "uuid": "^3.3.2" 3115 | }, 3116 | "dependencies": { 3117 | "qs": { 3118 | "version": "6.5.3", 3119 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz", 3120 | "integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==", 3121 | "optional": true 3122 | } 3123 | } 3124 | }, 3125 | "safe-buffer": { 3126 | "version": "5.2.1", 3127 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", 3128 | "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" 3129 | }, 3130 | "safer-buffer": { 3131 | "version": "2.1.2", 3132 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 3133 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" 3134 | }, 3135 | "secure-json-parse": { 3136 | "version": "2.7.0", 3137 | "resolved": "https://registry.npmjs.org/secure-json-parse/-/secure-json-parse-2.7.0.tgz", 3138 | "integrity": "sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw==" 3139 | }, 3140 | "semver": { 3141 | "version": "5.7.1", 3142 | "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", 3143 | "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" 3144 | }, 3145 | "send": { 3146 | "version": "0.18.0", 3147 | "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", 3148 | "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", 3149 | "requires": { 3150 | "debug": "2.6.9", 3151 | "depd": "2.0.0", 3152 | "destroy": "1.2.0", 3153 | "encodeurl": "~1.0.2", 3154 | "escape-html": "~1.0.3", 3155 | "etag": "~1.8.1", 3156 | "fresh": "0.5.2", 3157 | "http-errors": "2.0.0", 3158 | "mime": "1.6.0", 3159 | "ms": "2.1.3", 3160 | "on-finished": "2.4.1", 3161 | "range-parser": "~1.2.1", 3162 | "statuses": "2.0.1" 3163 | } 3164 | }, 3165 | "seq-queue": { 3166 | "version": "0.0.5", 3167 | "resolved": "https://registry.npmjs.org/seq-queue/-/seq-queue-0.0.5.tgz", 3168 | "integrity": "sha512-hr3Wtp/GZIc/6DAGPDcV4/9WoZhjrkXsi5B/07QgX8tsdc6ilr7BFM6PM6rbdAX1kFSDYeZGLipIZZKyQP0O5Q==" 3169 | }, 3170 | "serve-favicon": { 3171 | "version": "2.4.5", 3172 | "resolved": "https://registry.npmjs.org/serve-favicon/-/serve-favicon-2.4.5.tgz", 3173 | "integrity": "sha512-s7F8h2NrslMkG50KxvlGdj+ApSwaLex0vexuJ9iFf3GLTIp1ph/l1qZvRe9T9TJEYZgmq72ZwJ2VYiAEtChknw==", 3174 | "requires": { 3175 | "etag": "~1.8.1", 3176 | "fresh": "0.5.2", 3177 | "ms": "2.0.0", 3178 | "parseurl": "~1.3.2", 3179 | "safe-buffer": "5.1.1" 3180 | }, 3181 | "dependencies": { 3182 | "ms": { 3183 | "version": "2.0.0", 3184 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 3185 | "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" 3186 | }, 3187 | "safe-buffer": { 3188 | "version": "5.1.1", 3189 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", 3190 | "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==" 3191 | } 3192 | } 3193 | }, 3194 | "serve-static": { 3195 | "version": "1.15.0", 3196 | "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", 3197 | "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", 3198 | "requires": { 3199 | "encodeurl": "~1.0.2", 3200 | "escape-html": "~1.0.3", 3201 | "parseurl": "~1.3.3", 3202 | "send": "0.18.0" 3203 | } 3204 | }, 3205 | "setprototypeof": { 3206 | "version": "1.2.0", 3207 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", 3208 | "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" 3209 | }, 3210 | "side-channel": { 3211 | "version": "1.0.4", 3212 | "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", 3213 | "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", 3214 | "requires": { 3215 | "call-bind": "^1.0.0", 3216 | "get-intrinsic": "^1.0.2", 3217 | "object-inspect": "^1.9.0" 3218 | } 3219 | }, 3220 | "simple-update-notifier": { 3221 | "version": "1.1.0", 3222 | "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-1.1.0.tgz", 3223 | "integrity": "sha512-VpsrsJSUcJEseSbMHkrsrAVSdvVS5I96Qo1QAQ4FxQ9wXFcB+pjj7FB7/us9+GcgfW4ziHtYMc1J0PLczb55mg==", 3224 | "requires": { 3225 | "semver": "~7.0.0" 3226 | }, 3227 | "dependencies": { 3228 | "semver": { 3229 | "version": "7.0.0", 3230 | "resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz", 3231 | "integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==" 3232 | } 3233 | } 3234 | }, 3235 | "source-map": { 3236 | "version": "0.6.1", 3237 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", 3238 | "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", 3239 | "optional": true 3240 | }, 3241 | "sqlstring": { 3242 | "version": "2.3.3", 3243 | "resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.3.tgz", 3244 | "integrity": "sha512-qC9iz2FlN7DQl3+wjwn3802RTyjCx7sDvfQEXchwa6CWOx07/WVfh91gBmQ9fahw8snwGEWU3xGzOt4tFyHLxg==" 3245 | }, 3246 | "sshpk": { 3247 | "version": "1.17.0", 3248 | "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.17.0.tgz", 3249 | "integrity": "sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ==", 3250 | "optional": true, 3251 | "requires": { 3252 | "asn1": "~0.2.3", 3253 | "assert-plus": "^1.0.0", 3254 | "bcrypt-pbkdf": "^1.0.0", 3255 | "dashdash": "^1.12.0", 3256 | "ecc-jsbn": "~0.1.1", 3257 | "getpass": "^0.1.1", 3258 | "jsbn": "~0.1.0", 3259 | "safer-buffer": "^2.0.2", 3260 | "tweetnacl": "~0.14.0" 3261 | } 3262 | }, 3263 | "statuses": { 3264 | "version": "2.0.1", 3265 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", 3266 | "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==" 3267 | }, 3268 | "streamsearch": { 3269 | "version": "1.1.0", 3270 | "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", 3271 | "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==" 3272 | }, 3273 | "supports-color": { 3274 | "version": "5.5.0", 3275 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", 3276 | "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", 3277 | "requires": { 3278 | "has-flag": "^3.0.0" 3279 | } 3280 | }, 3281 | "to-regex-range": { 3282 | "version": "5.0.1", 3283 | "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", 3284 | "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", 3285 | "requires": { 3286 | "is-number": "^7.0.0" 3287 | } 3288 | }, 3289 | "toidentifier": { 3290 | "version": "1.0.1", 3291 | "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", 3292 | "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==" 3293 | }, 3294 | "touch": { 3295 | "version": "3.1.0", 3296 | "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz", 3297 | "integrity": "sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==", 3298 | "requires": { 3299 | "nopt": "~1.0.10" 3300 | } 3301 | }, 3302 | "tough-cookie": { 3303 | "version": "2.5.0", 3304 | "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", 3305 | "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", 3306 | "optional": true, 3307 | "requires": { 3308 | "psl": "^1.1.28", 3309 | "punycode": "^2.1.1" 3310 | } 3311 | }, 3312 | "tslib": { 3313 | "version": "2.5.0", 3314 | "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", 3315 | "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" 3316 | }, 3317 | "tunnel-agent": { 3318 | "version": "0.6.0", 3319 | "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", 3320 | "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", 3321 | "optional": true, 3322 | "requires": { 3323 | "safe-buffer": "^5.0.1" 3324 | } 3325 | }, 3326 | "tweetnacl": { 3327 | "version": "0.14.5", 3328 | "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", 3329 | "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==", 3330 | "optional": true 3331 | }, 3332 | "twig": { 3333 | "version": "0.10.3", 3334 | "resolved": "https://registry.npmjs.org/twig/-/twig-0.10.3.tgz", 3335 | "integrity": "sha512-e/OJTus3EUYWbeMTPQm2DYRTsiQq8ru7uMOg69ohfwzJHpzHfme7AfytPiUJwSX66tPdFOqVBGaO1jZf2Dtmng==", 3336 | "requires": { 3337 | "locutus": "^2.0.5", 3338 | "minimatch": "3.0.x", 3339 | "walk": "2.3.x" 3340 | }, 3341 | "dependencies": { 3342 | "minimatch": { 3343 | "version": "3.0.8", 3344 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.8.tgz", 3345 | "integrity": "sha512-6FsRAQsxQ61mw+qP1ZzbL9Bc78x2p5OqNgNpnoAFLTrX8n5Kxph0CsnhmKKNXTWjXqU5L0pGPR7hYk+XWZr60Q==", 3346 | "requires": { 3347 | "brace-expansion": "^1.1.7" 3348 | } 3349 | } 3350 | } 3351 | }, 3352 | "type-is": { 3353 | "version": "1.6.18", 3354 | "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", 3355 | "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", 3356 | "requires": { 3357 | "media-typer": "0.3.0", 3358 | "mime-types": "~2.1.24" 3359 | } 3360 | }, 3361 | "undefsafe": { 3362 | "version": "2.0.5", 3363 | "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", 3364 | "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==" 3365 | }, 3366 | "undici": { 3367 | "version": "5.16.0", 3368 | "resolved": "https://registry.npmjs.org/undici/-/undici-5.16.0.tgz", 3369 | "integrity": "sha512-KWBOXNv6VX+oJQhchXieUznEmnJMqgXMbs0xxH2t8q/FUAWSJvOSr/rMaZKnX5RIVq7JDn0JbP4BOnKG2SGXLQ==", 3370 | "requires": { 3371 | "busboy": "^1.6.0" 3372 | } 3373 | }, 3374 | "unpipe": { 3375 | "version": "1.0.0", 3376 | "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", 3377 | "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==" 3378 | }, 3379 | "uri-js": { 3380 | "version": "4.4.1", 3381 | "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", 3382 | "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", 3383 | "optional": true, 3384 | "requires": { 3385 | "punycode": "^2.1.0" 3386 | } 3387 | }, 3388 | "utils-merge": { 3389 | "version": "1.0.1", 3390 | "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", 3391 | "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==" 3392 | }, 3393 | "uuid": { 3394 | "version": "3.4.0", 3395 | "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", 3396 | "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", 3397 | "optional": true 3398 | }, 3399 | "vary": { 3400 | "version": "1.1.2", 3401 | "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", 3402 | "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==" 3403 | }, 3404 | "verror": { 3405 | "version": "1.10.0", 3406 | "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", 3407 | "integrity": "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==", 3408 | "optional": true, 3409 | "requires": { 3410 | "assert-plus": "^1.0.0", 3411 | "core-util-is": "1.0.2", 3412 | "extsprintf": "^1.2.0" 3413 | } 3414 | }, 3415 | "walk": { 3416 | "version": "2.3.15", 3417 | "resolved": "https://registry.npmjs.org/walk/-/walk-2.3.15.tgz", 3418 | "integrity": "sha512-4eRTBZljBfIISK1Vnt69Gvr2w/wc3U6Vtrw7qiN5iqYJPH7LElcYh/iU4XWhdCy2dZqv1ToMyYlybDylfG/5Vg==", 3419 | "requires": { 3420 | "foreachasync": "^3.0.0" 3421 | } 3422 | }, 3423 | "yallist": { 3424 | "version": "4.0.0", 3425 | "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", 3426 | "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" 3427 | } 3428 | } 3429 | } 3430 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "node-es-example", 3 | "version": "0.0.0", 4 | "private": true, 5 | "scripts": { 6 | "start": "nodemon -e js,twig,css ./bin/www", 7 | "listen": "nodemon -e queue-listener.js ./queue-listener.js" 8 | }, 9 | "dependencies": { 10 | "@elastic/elasticsearch": "^8.6.0", 11 | "async": "^2.6.2", 12 | "blueimp-md5": "^2.10.0", 13 | "body-parser": "^1.19.0", 14 | "cookie-parser": "^1.4.4", 15 | "debug": "~2.6.9", 16 | "dotenv": "^4.0.0", 17 | "express": "^4.16.4", 18 | "extend": ">=3.0.2", 19 | "hkulekci-simple-redis-queue": "^0.9.8", 20 | "less-middleware": "~3.0.1", 21 | "morgan": "^1.9.1", 22 | "mysql2": "^3.1.0", 23 | "node-datetime": "^2.1.2", 24 | "nodemon": "^2.0.20", 25 | "redis": "^4.6.4", 26 | "serve-favicon": "~2.4.5", 27 | "twig": "~0.10.3" 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /public/stylesheets/style.css: -------------------------------------------------------------------------------- 1 | body{padding:50px;font:14px "Lucida Grande",Helvetica,Arial,sans-serif}a{color:#00B7FF} -------------------------------------------------------------------------------- /public/stylesheets/style.less: -------------------------------------------------------------------------------- 1 | body { 2 | padding: 50px; 3 | font: 14px "Lucida Grande", Helvetica, Arial, sans-serif; 4 | } 5 | 6 | a { 7 | color: #00B7FF; 8 | } 9 | -------------------------------------------------------------------------------- /push-all-product-to-queue.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | require('dotenv').config(); 4 | const db = require('./libraries/database'); 5 | const redisClient = require('./libraries/redis-client'); 6 | const RedisQueue = require('hkulekci-simple-redis-queue'); 7 | 8 | const push_queue = new RedisQueue(redisClient.getClient()); 9 | 10 | const getAllProductIds = (callback) => { 11 | let sql = "SELECT p.id FROM products p"; 12 | 13 | db.getConnection(function(err, connection) { 14 | if(err) { console.log(err); callback(true); return; } 15 | // make the query 16 | connection.query(sql, {}, function(err, results) { 17 | connection.release(); 18 | if(err) { console.log(err); callback(true); return; } 19 | callback(false, results); 20 | }); 21 | }); 22 | } 23 | 24 | 25 | console.log(getAllProductIds((err, response) => { 26 | if (!err) { 27 | for (const index in response) { 28 | const product = response[index] 29 | push_queue.push('product_updates', {'action':'insert', 'productId': product.id}, ((err, res) => { 30 | console.log('Product sent to queue : ' + product.id) 31 | })); 32 | } 33 | } 34 | })) -------------------------------------------------------------------------------- /queue-listener.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | require('dotenv').config(); 4 | const productService = require('./services/productService'); 5 | const categoryService = require('./services/categoryService'); 6 | const productSearchService = require('./services/productSearchService'); 7 | const waterfall = require('async/waterfall'); 8 | const RedisQueue = require('hkulekci-simple-redis-queue'); 9 | const redisClient = require("./libraries/redis-client"); 10 | 11 | const pop_queue = new RedisQueue(redisClient.getClient()); 12 | 13 | 14 | const upsertOperation = function(productId, functionCallback) { 15 | waterfall([ 16 | // Insert Operation 17 | function(waterfallCallback) { // Getting Product Category From DB (Preparing for Elasticsearch) 18 | let result = {}; 19 | categoryService.getProductCategories(productId, function(err, productCategories) { 20 | if (err) {} 21 | result.productCategories = productCategories; 22 | waterfallCallback(false, result); 23 | }); 24 | }, 25 | function(result, waterfallCallback) { // Getting Product Data From MySQL DB (Preparing for Elasticsearch) 26 | productService.getRecord(productId, function(err, product) { 27 | if (err) {} 28 | result.product = product; 29 | waterfallCallback(false, result); 30 | }); 31 | }, 32 | function(result, waterfallCallback) { // Saving Product to Elasticsearch 33 | let product = result.product; 34 | product.categories = result.productCategories; 35 | 36 | let input = product.name.trim().split(' '); 37 | product.completion = { 38 | "input": input 39 | }; 40 | productSearchService.insert(product, function() { 41 | waterfallCallback(false, product); 42 | }); 43 | }, 44 | ], 45 | function(err, result) { 46 | functionCallback(err, result); 47 | }); 48 | }; 49 | 50 | const deleteOperation = function(productId, functionCallback) { 51 | // Delete Operation 52 | productSearchService.delete(productId, function(err, result) { 53 | functionCallback(false); 54 | }); 55 | }; 56 | 57 | /***** Redis Message Queue Listener ******/ 58 | pop_queue.on('message', (queueName, payload) => { 59 | const messageData = JSON.parse(payload); 60 | 61 | if (messageData.action === 'update' || messageData.action === 'insert') { 62 | upsertOperation(messageData.productId, function() { 63 | console.log('[product_updates] - Processed! - ' + payload); 64 | pop_queue.next(queueName) 65 | }); 66 | } else if (messageData.action === 'delete') { 67 | deleteOperation(messageData.productId, function() { 68 | console.log('[product_updates] - Processed! - ' + payload); 69 | pop_queue.next(queueName) 70 | }); 71 | } else { 72 | console.log('[product_updates] - Not Processed! - ' + payload); 73 | pop_queue.next(queueName) 74 | } 75 | }); 76 | 77 | pop_queue.on('error', (err) => { 78 | console.log(err) 79 | }); 80 | 81 | pop_queue.next('product_updates'); -------------------------------------------------------------------------------- /routes/categories.js: -------------------------------------------------------------------------------- 1 | var express = require('express'); 2 | var router = express.Router(); 3 | var waterfall = require('async/waterfall'); 4 | var categoryService = require('../services/categoryService'); 5 | var categorySearchService = require('../services/categorySearchService'); 6 | 7 | /* GET categories listing. */ 8 | router.get('/', function(req, res, next) { 9 | waterfall( 10 | [ 11 | function(waterfallCallback) { 12 | categoryService.getRecords(function(err, categories) { 13 | if(err) { res.send(500,"Server Error"); return; } 14 | var results = { 15 | 'categories': categories 16 | }; 17 | waterfallCallback(false, results); 18 | }); 19 | }, 20 | function(results, waterfallCallback) { 21 | categorySearchService.getRecords(function(err, esCategories) { 22 | results.esCategories = esCategories; 23 | waterfallCallback(false, results); 24 | }); 25 | 26 | } 27 | ], 28 | function(err, results) { 29 | if (err) {} 30 | res.render('categories', {'title': 'Categories', categories: results.categories, esCategories: results.esCategories }); 31 | } 32 | ); 33 | }); 34 | 35 | module.exports = router; 36 | -------------------------------------------------------------------------------- /routes/graphs.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const router = express.Router(); 3 | const productGraphService = require('../services/productGraphService'); 4 | const waterfall = require('async/waterfall'); 5 | 6 | var dynamicColors = function() { 7 | var r = Math.floor(Math.random() * 255); 8 | var g = Math.floor(Math.random() * 255); 9 | var b = Math.floor(Math.random() * 255); 10 | return "rgb(" + r + "," + g + "," + b + ")"; 11 | }; 12 | 13 | 14 | router.get('/', function(req, res, next) { 15 | 16 | waterfall( 17 | [ 18 | function(waterfallCallback) { 19 | productGraphService.getProductCountByDate({}, function(err, result) { 20 | if(err) { waterfallCallback(true, {}); } 21 | let colors = []; 22 | for (let i in result['vals']) { 23 | colors.push(dynamicColors()); 24 | } 25 | waterfallCallback(false, {"chart1": {'labels':'"' + result['keys'].join('","') + '"', 'datasets': [ {'data': result['vals'].join(','), 'label': 'Num of Product', 'colors': '"'+colors.join('","')+'"'} ]}}); 26 | return; 27 | }); 28 | }, 29 | function(data, waterfallCallback) { 30 | productGraphService.getProductQuantities({}, function(err, result) { 31 | if(err) { waterfallCallback(true, {}); } 32 | let colors = []; 33 | for (let i in result['vals']) { 34 | colors.push(dynamicColors()); 35 | } 36 | data['chart2'] = {'labels':'"' + result['keys'].join('","') + '"', 'datasets': [ {'data': result['vals'].join(','), 'label': 'Total Product Quantity', 'colors': '"'+colors.join('","')+'"'}, {'data': result['counts'].join(','), 'label': 'Num of Product'} ]}; 37 | waterfallCallback(false, data); 38 | return; 39 | }); 40 | }, 41 | function(data, waterfallCallback) { 42 | productGraphService.getCategoriyQuantitySum({}, function(err, result) { 43 | if(err) { waterfallCallback(true, {}); } 44 | let colors1 = []; 45 | let colors2 = []; 46 | for (let i in result['vals']) { 47 | colors1.push(dynamicColors()); 48 | } 49 | 50 | for (let i in result['counts']) { 51 | colors2.push(dynamicColors()); 52 | } 53 | data['chart3'] = {'labels':'"' + result['keys'].join('","') + '"', 'datasets': [ {'data': result['vals'].join(','), 'label': 'Total Quantity of Category', 'colors': '"'+colors1.join('","')+'"' }, {'data': result['counts'].join(','), 'label': 'Num of Product by Category', 'colors': '"'+colors2.join('","')+'"'} ]}; 54 | waterfallCallback(false, data); 55 | return; 56 | }); 57 | } 58 | ], 59 | function(err, data) { 60 | if(err) { res.send(500,"Server Error"); return; } 61 | console.log(data); 62 | res.render('graphs', data); 63 | } 64 | ); 65 | return; 66 | }); 67 | 68 | module.exports = router; 69 | -------------------------------------------------------------------------------- /routes/index.js: -------------------------------------------------------------------------------- 1 | var express = require('express'); 2 | var router = express.Router(); 3 | 4 | /* GET home page. */ 5 | router.get('/', function(req, res, next) { 6 | res.render('index', { title: 'Sample E-Commerce' }); 7 | }); 8 | 9 | module.exports = router; 10 | -------------------------------------------------------------------------------- /routes/products.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const router = express.Router(); 3 | const productService = require('../services/productService'); 4 | const categoryService = require('../services/categoryService'); 5 | const waterfall = require('async/waterfall'); 6 | const productSearchService = require('../services/productSearchService'); 7 | const redisClient = require('../libraries/redis-client'); 8 | const md5 = require('blueimp-md5'); 9 | const RedisQueue = require('hkulekci-simple-redis-queue'); 10 | 11 | const push_queue = new RedisQueue(redisClient.getClient()); 12 | 13 | /* GET products listing. */ 14 | router.get('/', async function(req, res, next) { 15 | const queryParams = req.query; 16 | 17 | const value = await redisClient.get(md5(queryParams)); 18 | if (value !== null) { 19 | res.render('products', {'title': 'Products', products: value, 'totalCount': value.length, 'cache': true}); 20 | return; 21 | } 22 | 23 | productService.getRecords(queryParams, function(err, results) { 24 | if(err) { res.status(500).send("Server Error"); return; } 25 | redisClient.set(md5(queryParams), results, 100); 26 | // Respond with results as JSON 27 | res.render('products', {'title': 'Products', products: results, 'totalCount': results.length, 'cache': false}); 28 | }); 29 | 30 | return; 31 | }); 32 | 33 | /* GET products listing. */ 34 | router.get('/id/:id', function(req, res, next) { 35 | let params = req.params; 36 | productService.getRecord(params.id, function(err, product) { 37 | if(err) { 38 | res.status(500).send("Server Error"); 39 | return; 40 | } 41 | // Respond with results as JSON 42 | if (product === undefined) { 43 | res.status(400).send("Not Found"); 44 | return; 45 | } 46 | res.render('product', {'title': product['name'], product: product }); 47 | return; 48 | }); 49 | }); 50 | 51 | router.get('/new', function(req, res, next) { 52 | const product = { 53 | 'id': 0, 54 | 'name': '', 55 | 'description': '', 56 | 'price': '', 57 | 'quantity': '' 58 | }; 59 | categoryService.getRecords(function(err, results) { 60 | res.render('product-form', {'product': product, 'url': '/product/new', categories: results}); 61 | }); 62 | }); 63 | 64 | router.post('/new', function(req, res, next) { 65 | const params = req.body; 66 | const categories = params.categories; 67 | delete params['categories']; 68 | 69 | //TODO: Form filter&validation opearation required! 70 | 71 | waterfall( 72 | [ 73 | function(waterfallCallback) { // Saving Product to MySQL DB 74 | let result = {}; 75 | productService.insert(params, function(err, insertId) { 76 | if (err) { res.redirect('/product'); } 77 | productService.upsertCategories(insertId, categories, function(err) { 78 | result.insertId = insertId; 79 | waterfallCallback(false, result); 80 | }) 81 | }); 82 | }, 83 | function(result, waterfallCallback) { 84 | push_queue.push('product_updates', {'action':'insert', 'productId': result.insertId}, (err, result) => { 85 | waterfallCallback(false, result); 86 | }); 87 | } 88 | ], 89 | function(err, result) { 90 | if (err) {} 91 | res.redirect('/product/id/'+result.insertId); 92 | } 93 | ); 94 | }); 95 | 96 | router.get('/:id/delete', function(req, res, next) { 97 | var params = req.params; 98 | 99 | waterfall( 100 | [ 101 | function(waterfallCallback) { 102 | productService.delete(params.id, function(err, result) { 103 | //TODO: check error status 104 | waterfallCallback(false); 105 | }); 106 | }, 107 | function(waterfallCallback) { 108 | push_queue.push('product_updates', {'action':'delete', 'productId': params.id}, (err, result) => { 109 | waterfallCallback(false, result); 110 | }); 111 | } 112 | ], 113 | function(err, result) { 114 | res.redirect('/product'); 115 | } 116 | ); 117 | }); 118 | 119 | router.get('/:id/edit', function(req, res, next) { 120 | var params = req.params; 121 | 122 | waterfall( 123 | [ 124 | function(waterfallCallback) { 125 | productService.getRecord(params.id, function(err, product) { 126 | if (err) { 127 | waterfallCallback(err); 128 | return; 129 | } 130 | waterfallCallback(false, {'product': product}); 131 | }); 132 | }, 133 | function(result, waterfallCallback) { 134 | categoryService.getRecords(function(err, categories) { 135 | result.categories = categories; 136 | waterfallCallback(false, result); 137 | }); 138 | }, 139 | function(result, waterfallCallback) { 140 | categoryService.getProductCategories(params.id, function(err, productCategories) { 141 | result.productCategories = productCategories; 142 | waterfallCallback(false, result); 143 | }); 144 | }, 145 | function(result, waterfallCallback) { 146 | for (let i in result.categories) { 147 | for (let j in result.productCategories) { 148 | if (result.categories[i].id === result.productCategories[j].id) { 149 | result.categories[i].selected = true; 150 | break; 151 | } else { 152 | result.categories[i].selected = false; 153 | } 154 | } 155 | } 156 | waterfallCallback(false, result); 157 | } 158 | ], 159 | function(err, results) { 160 | if (err) { 161 | res.send("Not Found").status(400); 162 | return; 163 | } 164 | res.render('product-form', { 165 | 'product': results.product, 166 | 'categories': results.categories, 167 | 'productCategories': results.productCategories, 168 | 'url': '/product/'+params.id+'/edit' 169 | }); 170 | } 171 | ); 172 | }); 173 | 174 | 175 | router.post('/:id/edit', function(req, res, next) { 176 | const params = req.body; 177 | const queryParams = req.params; 178 | params.id = queryParams.id; 179 | const categories = params.categories; 180 | delete params['categories']; 181 | 182 | //TODO: Form filter&validation operation required! 183 | 184 | waterfall( 185 | [ 186 | function(waterfallCallback) { // Saving Product Data to MySQL DB 187 | productService.update(params, function(err, changedRows) { 188 | if (err) { res.redirect('/product'); } 189 | productService.upsertCategories(queryParams.id, categories, function(err) { 190 | waterfallCallback(false); 191 | return; 192 | }); 193 | }); 194 | }, 195 | function(waterfallCallback) { 196 | push_queue.push('product_updates', {'action':'update', 'productId': queryParams.id}, () => { 197 | waterfallCallback(false); 198 | }); 199 | } 200 | ], 201 | function(err, product) { 202 | if (err) {} 203 | res.redirect('/product/id/' + queryParams.id); 204 | return; 205 | } 206 | ); 207 | }); 208 | 209 | module.exports = router; 210 | -------------------------------------------------------------------------------- /routes/search.js: -------------------------------------------------------------------------------- 1 | var express = require('express'); 2 | var router = express.Router(); 3 | var productService = require('../services/productService'); 4 | var productSearchService = require('../services/productSearchService'); 5 | var parallel = require('async/parallel'); 6 | 7 | /* WITH DATABASE QUERY */ 8 | /* GET product searching. */ 9 | router.get('/', function(req, res, next) { 10 | var queryParams = req.query 11 | 12 | parallel({ 13 | db: function(callback) { 14 | 15 | productService.getRecords(queryParams, function(err, results) { 16 | if(err) { res.send(500, "Server Error"); return; } 17 | callback(null, {'products': results, 'totalCount': results.length}); 18 | }); 19 | 20 | }, 21 | elastic: function(callback) { 22 | productSearchService.getRecords(queryParams, function(err, results) { 23 | if(err) { res.send(500, "Server Error"); return; } 24 | var products = []; 25 | for (p in results.hits) { 26 | products.push(results.hits[p]._source); 27 | } 28 | callback(null, {'products': products, 'totalCount': results.total.value}); 29 | }); 30 | 31 | } 32 | }, function(err, results) { 33 | res.render('search', results); 34 | }); 35 | 36 | return; 37 | }); 38 | 39 | router.get('/suggest', function(req, res, next) { 40 | let queryParams = req.query 41 | let terms = queryParams.keyword.trim().split(' '); 42 | let keyword = terms.pop(); 43 | 44 | productSearchService.getSuggestions(keyword, function(err, results) { 45 | if (err) { res.send(500, "Server Error"); return; } 46 | let data = {'suggestions':[]}; 47 | for (p in results.options) { 48 | let tempTerms = terms.slice(0); 49 | tempTerms.push(results.options[p].text); 50 | let searchText = tempTerms.join(' '); 51 | 52 | data.suggestions.push({ 53 | 'search-text': searchText, 54 | 'suggest': results.options[p].text 55 | }); 56 | } 57 | 58 | res.render('suggestions', data); 59 | }); 60 | 61 | return; 62 | }); 63 | 64 | module.exports = router; 65 | -------------------------------------------------------------------------------- /sample.env: -------------------------------------------------------------------------------- 1 | MYSQL_HOST=mysql 2 | MYSQL_USER=root 3 | MYSQL_PASS=123456 4 | MYSQL_PORT=33060 5 | MYSQL_DB=node_es_example 6 | MYSQL_DEBUG=false 7 | 8 | REDIS_HOST="127.0.0.1" 9 | ELASTIC_HOST="http://elasticsearch:9200" 10 | ELASTIC_LOG=trace -------------------------------------------------------------------------------- /services/categorySearchService.js: -------------------------------------------------------------------------------- 1 | var db = require('./../libraries/elasticsearch'); 2 | 3 | exports.getRecords = function(callback) { 4 | const body = { 5 | size: 0, 6 | aggs: { 7 | categories: { 8 | terms: { 9 | field: "categories.name", 10 | size: 20 11 | }, 12 | aggs: { 13 | categoryId: { 14 | terms: { 15 | field: "categories.id", 16 | size: 1 17 | } 18 | } 19 | } 20 | } 21 | } 22 | }; 23 | 24 | db.search({ 25 | index: 'products', 26 | body: body 27 | }).then(function (resp) { 28 | const categories = []; 29 | const aggs = resp.aggregations.categories.buckets; 30 | for (let index in aggs) { 31 | const obj = { 32 | 'name': aggs[index].key, 33 | 'id': aggs[index].categoryId.buckets[0].key, 34 | 'count': aggs[index].doc_count 35 | }; 36 | categories.push(obj); 37 | } 38 | callback(false, categories); 39 | return; 40 | }, function (err) { 41 | callback(true); 42 | console.trace(err.message); 43 | return; 44 | }); 45 | }; -------------------------------------------------------------------------------- /services/categoryService.js: -------------------------------------------------------------------------------- 1 | var db = require('./../libraries/database'); 2 | 3 | exports.getRecords = function(callback) { 4 | var sql = "SELECT * FROM categories"; 5 | // get a connection from the pool 6 | db.getConnection(function(err, connection) { 7 | if(err) { console.log(err); callback(true); return; } 8 | // make the query 9 | connection.query(sql, [], function(err, results) { 10 | connection.release(); 11 | if(err) { console.log(err); callback(true); return; } 12 | callback(false, results); 13 | }); 14 | }); 15 | }; 16 | 17 | 18 | exports.getProductCategories = function(productId, callback) { 19 | var sql = "SELECT * FROM product_category WHERE product_id = ?;"; 20 | // get a connection from the pool 21 | db.getConnection(function(err, connection) { 22 | if(err) { console.log(err); callback(true); return; } 23 | // make the query 24 | connection.query(sql, [productId], function(err, results) { 25 | connection.release(); 26 | if(err) { console.log(err); callback(true); return; } 27 | categories = []; 28 | for (index in results) { 29 | categories.push(results[index]['category_id']); 30 | } 31 | connection.query("SELECT * FROM categories WHERE id IN (?)", [categories], function(err, productCategories) { 32 | callback(false, productCategories); 33 | }); 34 | }); 35 | }); 36 | }; -------------------------------------------------------------------------------- /services/productGraphService.js: -------------------------------------------------------------------------------- 1 | const db = require('./../libraries/elasticsearch'); 2 | 3 | exports.getProductCountByDate = function(params, callback) { 4 | const body = { 5 | "size": 0, 6 | "aggs": { 7 | "product_counts": { 8 | "date_histogram": { 9 | "field": "created_at", 10 | "calendar_interval": "week" 11 | } 12 | } 13 | } 14 | }; 15 | 16 | db.search({ 17 | index: 'products', 18 | body: body 19 | }).then(function (resp) { 20 | let aggs = resp.aggregations.product_counts.buckets; 21 | let result = { 22 | "keys": [], 23 | "vals": [] 24 | }; 25 | for (const i in aggs) { 26 | result['keys'].push(aggs[i].key_as_string); 27 | result['vals'].push(aggs[i].doc_count); 28 | } 29 | callback(false, result); 30 | return; 31 | }, function (err) { 32 | callback(true); 33 | console.trace(err.message); 34 | return; 35 | }); 36 | }; 37 | 38 | exports.getCategoriyQuantitySum = function(params, callback) { 39 | const body = { 40 | "size": 0, 41 | "aggs": { 42 | "product_categories": { 43 | "terms": { 44 | "field": "categories.id", 45 | "size": 10 46 | }, 47 | "aggs": { 48 | "sum": { 49 | "sum": { 50 | "field": "quantity" 51 | } 52 | } 53 | } 54 | } 55 | } 56 | }; 57 | 58 | db.search({ 59 | index: 'products', 60 | body: body 61 | }).then(function (resp) { 62 | var aggs = resp.aggregations.product_categories.buckets; 63 | var result = { 64 | "keys": [], 65 | "vals": [], 66 | "counts": [] 67 | }; 68 | for (i in aggs) { 69 | result['keys'].push(aggs[i].key); 70 | result['counts'].push(aggs[i].doc_count); 71 | result['vals'].push(aggs[i].sum.value); 72 | } 73 | callback(false, result); 74 | return; 75 | }, function (err) { 76 | callback(true); 77 | console.trace(err.message); 78 | return; 79 | }); 80 | }; 81 | 82 | 83 | exports.getProductQuantities = function(params, callback) { 84 | const body = { 85 | "size": 0, 86 | "aggs": { 87 | "product_counts": { 88 | "date_histogram": { 89 | "field": "created_at", 90 | "calendar_interval": "week" 91 | }, 92 | "aggs": { 93 | "product_quantities": { 94 | "sum": { 95 | "field": "quantity" 96 | } 97 | } 98 | } 99 | } 100 | } 101 | }; 102 | 103 | db.search({ 104 | index: 'products', 105 | body: body 106 | }).then(function (resp) { 107 | var aggs = resp.aggregations.product_counts.buckets; 108 | var result = { 109 | "keys": [], 110 | "vals": [], 111 | "counts": [] 112 | }; 113 | for (i in aggs) { 114 | result['keys'].push(aggs[i].key_as_string); 115 | result['counts'].push(aggs[i].doc_count); 116 | result['vals'].push(aggs[i].product_quantities.value); 117 | } 118 | callback(false, result); 119 | return; 120 | }, function (err) { 121 | console.trace(err); 122 | callback(true); 123 | return; 124 | }); 125 | }; -------------------------------------------------------------------------------- /services/productSearchService.js: -------------------------------------------------------------------------------- 1 | var db = require('./../libraries/elasticsearch'); 2 | 3 | exports.getSuggestions = function(keyword, callback) { 4 | body = { 5 | "suggest": { 6 | "suggest": { 7 | "completion": { 8 | "field": "completion", 9 | "size": 10, 10 | "skip_duplicates": true 11 | }, 12 | "text": keyword 13 | } 14 | } 15 | }; 16 | 17 | db.search({ 18 | index: 'products', 19 | body: body 20 | }).then(function (resp) { 21 | let hits = resp.suggest.suggest[0]; 22 | callback(false, hits); 23 | return; 24 | }, function (err) { 25 | callback(true); 26 | console.trace(err.message); 27 | return; 28 | }); 29 | } 30 | 31 | exports.getRecords = function(params, callback) { 32 | body = { 33 | query: {}, 34 | size: 50 35 | }; 36 | 37 | if (params.category) { 38 | body.query.term = { 39 | "categories.id": { 40 | "value": params.category 41 | } 42 | }; 43 | } 44 | 45 | if (params.keyword) { 46 | body.query.bool = { 47 | "must": [] 48 | }; 49 | 50 | let terms = params.keyword.split(' '); 51 | for (let i = 0; i < terms.length; i++) { 52 | if (!terms[i]) { 53 | // ignore empty term 54 | continue; 55 | } 56 | body.query.bool.must.push({ 57 | "bool": { 58 | "should": [ 59 | { 60 | "fuzzy" : { 61 | "name.autocomplete" : { 62 | "value": terms[i], 63 | "boost": 10.0, 64 | "fuzziness": 1, 65 | "prefix_length": 0, 66 | "max_expansions": 100 67 | } 68 | } 69 | }, 70 | { 71 | "fuzzy" : { 72 | "description.autocomplete" : { 73 | "value": terms[i], 74 | "boost": 2.0, 75 | "fuzziness": 1, 76 | "prefix_length": 0, 77 | "max_expansions": 100 78 | } 79 | } 80 | }, 81 | { 82 | "fuzzy" : { 83 | "category.name.autocomplete" : { 84 | "value": terms[i], 85 | "boost": 3.0, 86 | "fuzziness": 1, 87 | "prefix_length": 0, 88 | "max_expansions": 100 89 | } 90 | } 91 | } 92 | ] 93 | } 94 | }); 95 | } // end of for 96 | } 97 | 98 | db.search({ 99 | index: 'products', 100 | body: body 101 | }).then(function (resp) { 102 | let hits = resp.hits; 103 | callback(false, hits); 104 | return; 105 | }, function (err) { 106 | callback(true); 107 | console.trace(err.message); 108 | return; 109 | }); 110 | }; 111 | 112 | exports.insert = async function(product, callback) { 113 | const response = await db.index({ 114 | index: 'products', 115 | id: product.id, 116 | body: product 117 | }); 118 | callback(false, response); 119 | }; 120 | 121 | 122 | exports.delete = function(productId, callback) { 123 | db.delete({ 124 | index: 'products', 125 | id: productId, 126 | }, function (error, response) { 127 | if (error) { callback(true, error); return; } 128 | callback(false, response); 129 | }); 130 | }; -------------------------------------------------------------------------------- /services/productService.js: -------------------------------------------------------------------------------- 1 | const db = require('./../libraries/database'); 2 | const dateTime = require('node-datetime'); 3 | const every = require('async/every'); 4 | const waterfall = require('async/waterfall'); 5 | 6 | exports.getRecords = function(params, callback) { 7 | let sql = "SELECT p.* FROM products p LEFT JOIN product_category pc ON pc.product_id = p.id LEFT JOIN categories c ON c.id = pc.category_id"; 8 | let sqlParams = []; 9 | 10 | let sqlExtras = []; 11 | if (params.category) { 12 | sqlExtras.push({'sql': ' WHERE pc.category_id = ?', 'params': [params.category]}); 13 | } 14 | if (params.keyword) { 15 | sqlExtras.push({'sql': ' WHERE (p.name LIKE ? OR p.description LIKE ?)', 'params': ['%'+params.keyword+'%', '%'+params.keyword+'%']}); 16 | } 17 | if (sqlExtras.length >= 1) { 18 | for (let e in sqlExtras) { 19 | sql += sqlExtras[e].sql; 20 | for (let p in sqlExtras[e].params) { 21 | sqlParams.push(sqlExtras[e].params[p]); 22 | } 23 | } 24 | } 25 | sql += ' GROUP BY p.id LIMIT 50'; 26 | 27 | // get a connection from the pool 28 | db.getConnection(function(err, connection) { 29 | if(err) { console.log(err); callback(true); return; } 30 | // make the query 31 | connection.query(sql, sqlParams, function(err, results) { 32 | connection.release(); 33 | if(err) { console.log(err); callback(true); return; } 34 | callback(false, results); 35 | }); 36 | }); 37 | }; 38 | 39 | exports.getRecord = function(id, callback) { 40 | const sql = "SELECT * FROM products WHERE id = ?"; 41 | // get a connection from the pool 42 | db.getConnection(function(err, connection) { 43 | if(err) { console.log(err); callback(true); return; } 44 | // make the query 45 | connection.query(sql, [id], function(err, results) { 46 | connection.release(); 47 | if(err) { console.log(err); callback(true); return; } 48 | if (results.length >= 1) { 49 | callback(false, results[0]); 50 | return; 51 | } 52 | callback(false, undefined); 53 | return; 54 | }); 55 | }); 56 | }; 57 | 58 | exports.insert = function(sqlData, callback) { 59 | const dt = dateTime.create(); 60 | const formatted = dt.format('Y-m-d H:M:S'); 61 | 62 | sqlData.updated_at = formatted; 63 | const sql = "INSERT INTO products SET ?"; 64 | db.getConnection(function(err, connection) { 65 | if(err) { console.log(err); callback(true); return; } 66 | connection.query(sql, sqlData, function(err, results, fields) { 67 | if(err) { console.log(err); callback(true); return; } 68 | callback(false, results.insertId); 69 | }); 70 | }); 71 | }; 72 | 73 | 74 | exports.upsertCategories = function(productId, categories, callback) { 75 | waterfall( 76 | [ 77 | function(waterfallCallback) { 78 | db.getConnection(function(err, connection) { 79 | if(err) { console.log(err); waterfallCallback(true); return; } 80 | connection.query("DELETE FROM product_category WHERE product_id = ?", [productId], function(err, results) { 81 | if(err) { console.log(err); waterfallCallback(true); return; } 82 | waterfallCallback(false); 83 | }); 84 | }); 85 | }, 86 | function(waterfallCallback) { 87 | every(categories, function(category, eachCallback) { 88 | let sql = "INSERT INTO product_category SET ?"; 89 | db.getConnection(function(err, connection) { 90 | if(err) { console.log(err); eachCallback(true); return; } 91 | connection.query(sql, {'product_id': productId, 'category_id': category}, function(err, results, fields) { 92 | if(err) { console.log(err); eachCallback(true); return; } 93 | eachCallback(false); 94 | }); 95 | }); 96 | }, 97 | function(err, result) { 98 | waterfallCallback(err); 99 | }); 100 | } 101 | ], 102 | function(err, results) { 103 | callback(err); 104 | } 105 | ); 106 | }; 107 | 108 | 109 | exports.update = function(sqlData, callback) { 110 | let sql = "UPDATE products SET name = ?, description = ?, price = ?, quantity = ? WHERE id = ?;"; 111 | let params = [sqlData.name, sqlData.description, sqlData.price, sqlData.quantity, sqlData.id]; 112 | db.getConnection(function(err, connection) { 113 | if (err) { console.log(err); callback(true); return; } 114 | connection.query(sql, params, function(err, results, fields) { 115 | if (err) { console.log(err); callback(true); return; } 116 | callback(false, results.changedRows); 117 | }); 118 | }); 119 | }; 120 | 121 | 122 | 123 | 124 | exports.delete = function(productId, callback) { 125 | let sql = "DELETE FROM product_category WHERE product_id = ?;"; 126 | let params = [productId]; 127 | db.getConnection(function(err, connection) { 128 | if(err) { console.log(err); callback(true); return; } 129 | connection.query(sql, params, function(err, results, fields) { 130 | if(err) { console.log(err); callback(true); return; } 131 | let psql = "DELETE FROM products WHERE id = ?;"; 132 | let pparams = [productId]; 133 | connection.query(psql, pparams, function(err, results, fields) { 134 | callback(false, results.changedRows); 135 | }); 136 | 137 | }); 138 | }); 139 | }; -------------------------------------------------------------------------------- /views/categories.twig: -------------------------------------------------------------------------------- 1 | {% extends 'layout.twig' %} 2 | 3 | {% block body %} 4 |
{{error.stack}}7 | {% endblock %} 8 | -------------------------------------------------------------------------------- /views/graphs.twig: -------------------------------------------------------------------------------- 1 | {% extends 'layout.twig' %} 2 | 3 | {% block body %} 4 |