first commit
This commit is contained in:
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
node_modules/
|
||||
package-lock.json
|
||||
1823
category.html
Executable file
1823
category.html
Executable file
File diff suppressed because one or more lines are too long
60
config/Config.js
Normal file
60
config/Config.js
Normal file
@@ -0,0 +1,60 @@
|
||||
const commandLineArgs = require('command-line-args'),
|
||||
logger = require("logops");
|
||||
|
||||
class Config {
|
||||
|
||||
constructor() {
|
||||
this.options = {}
|
||||
this.requires = ['env']
|
||||
this.init()
|
||||
process.env.TZ = 'Europe/Berlin'
|
||||
}
|
||||
|
||||
init() {
|
||||
try {
|
||||
this.options = commandLineArgs([
|
||||
{ name: 'env', alias: 'e', type: String, defaultValue: ['production'] },
|
||||
{ name: 'host', type: String },
|
||||
{ name: 'port', type: Number },
|
||||
{ name: 'database', alias: 'd', type: String },
|
||||
{ name: 'username', alias: 'u', type: String },
|
||||
{ name: 'password', alias: 'p', type: String },
|
||||
{ name: 'redis', alias: 'r', type: String }
|
||||
]);
|
||||
this.validate()
|
||||
} catch (e) {
|
||||
logger.debug('Command line arguments interpret failed :', e.message)
|
||||
logger.debug('expected arguments : ', JSON.stringify(this.requires))
|
||||
process.exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
validate() {
|
||||
let options = {}
|
||||
for (let key in this.options) {
|
||||
if (this.options[key]) {
|
||||
options[key] = this.options[key]
|
||||
delete this.requires[this.requires.indexOf(key)]
|
||||
}
|
||||
}
|
||||
if (options.env == 'development') {
|
||||
logger.setLevel("DEBUG")
|
||||
logger.format = logger.formatters.dev;
|
||||
}else {
|
||||
logger.setLevel("WARN")
|
||||
}
|
||||
console.log(options)
|
||||
this.requires = this.requires.filter(function (el) {
|
||||
return el != null;
|
||||
})
|
||||
|
||||
if (this.requires.length) {
|
||||
logger.debug('Process terminated invalid required arguments: ', JSON.stringify(requires))
|
||||
process.exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
let config = new Config;
|
||||
module.exports = config.options
|
||||
39
config/config.json
Normal file
39
config/config.json
Normal file
@@ -0,0 +1,39 @@
|
||||
{
|
||||
"development": {
|
||||
"username": "root",
|
||||
"password": null,
|
||||
"database": "iblogis_legacy",
|
||||
"host": "localhost",
|
||||
"dialect": "mysql",
|
||||
"pool": {
|
||||
"max": 5,
|
||||
"min": 0,
|
||||
"acquire": 30000,
|
||||
"idle": 10000,
|
||||
"charset": "utf8"
|
||||
},
|
||||
"timezone": "+02:00"
|
||||
},
|
||||
"test": {
|
||||
"username": "root",
|
||||
"password": null,
|
||||
"database": "database_test",
|
||||
"host": "127.0.0.1",
|
||||
"dialect": "mysql"
|
||||
},
|
||||
"production": {
|
||||
"username": "iblogis",
|
||||
"password": "dkrnffk73**",
|
||||
"database": "iblogis",
|
||||
"host": "87.106.21.246",
|
||||
"dialect": "mysql",
|
||||
"pool": {
|
||||
"max": 5,
|
||||
"min": 0,
|
||||
"acquire": 30000,
|
||||
"idle": 10000,
|
||||
"charset": "utf8"
|
||||
},
|
||||
"timezone": "+02:00"
|
||||
}
|
||||
}
|
||||
60
index.js
Executable file
60
index.js
Executable file
@@ -0,0 +1,60 @@
|
||||
const express = require("express")
|
||||
, expressLogging = require("express-logging")
|
||||
, logger = require("logops")
|
||||
, HttpStatus = require('http-status-codes')
|
||||
, hostname = require('os').hostname()
|
||||
, port = 22002
|
||||
, controllers = {};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Express web server starting
|
||||
*
|
||||
*/
|
||||
logger.getContext = function getContext() {
|
||||
return {
|
||||
// hostname: hostname,
|
||||
// pid: process.pid,
|
||||
port: port,
|
||||
app: 'Headless'
|
||||
};
|
||||
}
|
||||
var app = express();
|
||||
app.use(express.json());
|
||||
app.use(expressLogging(logger));
|
||||
app.listen(port, () => {
|
||||
logger.info({ app: 'Headless browser' }, 'Startup');
|
||||
});
|
||||
|
||||
/**
|
||||
* Request handlers
|
||||
*
|
||||
*/
|
||||
app.all('*', (req, res, next) => {
|
||||
let urlSegments = req.url.split('/');
|
||||
req.params.service = urlSegments[1]
|
||||
req.params.what = urlSegments.length > 2 ? urlSegments[2] : ''
|
||||
req.params.args = urlSegments.length > 3 ? urlSegments.slice(3) : []
|
||||
|
||||
if (!controllers.hasOwnProperty(req.params.service)) {
|
||||
let controller = req.params.service.charAt(0).toUpperCase() + req.params.service.slice(1) + 'Controller';
|
||||
try {
|
||||
controllers[req.params.service] = require('./src/controller/' + controller)
|
||||
logger.info('%s has been loaded', controller)
|
||||
} catch (err) {
|
||||
res.json({code: HttpStatus.NO_CONTENT, message: HttpStatus.getStatusText(HttpStatus.NO_CONTENT)})
|
||||
}
|
||||
}
|
||||
|
||||
if (controllers.hasOwnProperty(req.params.service)) {
|
||||
controllers[req.params.service][req.params.service](req, result => {
|
||||
res.json({
|
||||
code: HttpStatus.OK,
|
||||
message: HttpStatus.getStatusText(HttpStatus.OK),
|
||||
data: result
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
})
|
||||
914
package-lock.json
generated
Executable file
914
package-lock.json
generated
Executable file
@@ -0,0 +1,914 @@
|
||||
{
|
||||
"name": "cx-amazon-crawler",
|
||||
"version": "1.0.0",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
"@types/node": {
|
||||
"version": "14.6.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-14.6.0.tgz",
|
||||
"integrity": "sha512-mikldZQitV94akrc4sCcSjtJfsTKt4p+e/s0AGscVA6XArQ9kFclP+ZiYUMnq987rc6QlYxXv/EivqlfSLxpKA=="
|
||||
},
|
||||
"accepts": {
|
||||
"version": "1.3.7",
|
||||
"resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz",
|
||||
"integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==",
|
||||
"requires": {
|
||||
"mime-types": "~2.1.24",
|
||||
"negotiator": "0.6.2"
|
||||
}
|
||||
},
|
||||
"ansicolors": {
|
||||
"version": "0.3.2",
|
||||
"resolved": "https://registry.npmjs.org/ansicolors/-/ansicolors-0.3.2.tgz",
|
||||
"integrity": "sha1-ZlWX3oap/+Oqm/vmyuXG6kJrSXk="
|
||||
},
|
||||
"any-promise": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz",
|
||||
"integrity": "sha1-q8av7tzqUugJzcA3au0845Y10X8="
|
||||
},
|
||||
"array-back": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/array-back/-/array-back-3.1.0.tgz",
|
||||
"integrity": "sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q=="
|
||||
},
|
||||
"array-flatten": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
|
||||
"integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI="
|
||||
},
|
||||
"bluebird": {
|
||||
"version": "3.7.2",
|
||||
"resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz",
|
||||
"integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg=="
|
||||
},
|
||||
"body-parser": {
|
||||
"version": "1.19.0",
|
||||
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz",
|
||||
"integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==",
|
||||
"requires": {
|
||||
"bytes": "3.1.0",
|
||||
"content-type": "~1.0.4",
|
||||
"debug": "2.6.9",
|
||||
"depd": "~1.1.2",
|
||||
"http-errors": "1.7.2",
|
||||
"iconv-lite": "0.4.24",
|
||||
"on-finished": "~2.3.0",
|
||||
"qs": "6.7.0",
|
||||
"raw-body": "2.4.0",
|
||||
"type-is": "~1.6.17"
|
||||
},
|
||||
"dependencies": {
|
||||
"debug": {
|
||||
"version": "2.6.9",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
|
||||
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
|
||||
"requires": {
|
||||
"ms": "2.0.0"
|
||||
}
|
||||
},
|
||||
"ms": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
|
||||
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
|
||||
}
|
||||
}
|
||||
},
|
||||
"boolbase": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
|
||||
"integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24="
|
||||
},
|
||||
"bytes": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz",
|
||||
"integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg=="
|
||||
},
|
||||
"cardinal": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/cardinal/-/cardinal-2.1.1.tgz",
|
||||
"integrity": "sha1-fMEFXYItISlU0HsIXeolHMe8VQU=",
|
||||
"requires": {
|
||||
"ansicolors": "~0.3.2",
|
||||
"redeyed": "~2.1.0"
|
||||
}
|
||||
},
|
||||
"cheerio": {
|
||||
"version": "1.0.0-rc.3",
|
||||
"resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.3.tgz",
|
||||
"integrity": "sha512-0td5ijfUPuubwLUu0OBoe98gZj8C/AA+RW3v67GPlGOrvxWjZmBXiBCRU+I8VEiNyJzjth40POfHiz2RB3gImA==",
|
||||
"requires": {
|
||||
"css-select": "~1.2.0",
|
||||
"dom-serializer": "~0.1.1",
|
||||
"entities": "~1.1.1",
|
||||
"htmlparser2": "^3.9.1",
|
||||
"lodash": "^4.15.0",
|
||||
"parse5": "^3.0.1"
|
||||
}
|
||||
},
|
||||
"cls-bluebird": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/cls-bluebird/-/cls-bluebird-2.1.0.tgz",
|
||||
"integrity": "sha1-N+8eCAqP+1XC9BZPU28ZGeeWiu4=",
|
||||
"requires": {
|
||||
"is-bluebird": "^1.0.2",
|
||||
"shimmer": "^1.1.0"
|
||||
}
|
||||
},
|
||||
"colors": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz",
|
||||
"integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA=="
|
||||
},
|
||||
"command-line-args": {
|
||||
"version": "5.1.1",
|
||||
"resolved": "https://registry.npmjs.org/command-line-args/-/command-line-args-5.1.1.tgz",
|
||||
"integrity": "sha512-hL/eG8lrll1Qy1ezvkant+trihbGnaKaeEjj6Scyr3DN+RC7iQ5Rz84IeLERfAWDGo0HBSNAakczwgCilDXnWg==",
|
||||
"requires": {
|
||||
"array-back": "^3.0.1",
|
||||
"find-replace": "^3.0.0",
|
||||
"lodash.camelcase": "^4.3.0",
|
||||
"typical": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"content-disposition": {
|
||||
"version": "0.5.3",
|
||||
"resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz",
|
||||
"integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==",
|
||||
"requires": {
|
||||
"safe-buffer": "5.1.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"safe-buffer": {
|
||||
"version": "5.1.2",
|
||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
|
||||
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"content-type": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz",
|
||||
"integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA=="
|
||||
},
|
||||
"cookie": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz",
|
||||
"integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg=="
|
||||
},
|
||||
"cookie-signature": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
|
||||
"integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw="
|
||||
},
|
||||
"css-select": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/css-select/-/css-select-1.2.0.tgz",
|
||||
"integrity": "sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg=",
|
||||
"requires": {
|
||||
"boolbase": "~1.0.0",
|
||||
"css-what": "2.1",
|
||||
"domutils": "1.5.1",
|
||||
"nth-check": "~1.0.1"
|
||||
}
|
||||
},
|
||||
"css-what": {
|
||||
"version": "2.1.3",
|
||||
"resolved": "https://registry.npmjs.org/css-what/-/css-what-2.1.3.tgz",
|
||||
"integrity": "sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg=="
|
||||
},
|
||||
"debug": {
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
|
||||
"integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
|
||||
"requires": {
|
||||
"ms": "^2.1.1"
|
||||
}
|
||||
},
|
||||
"denque": {
|
||||
"version": "1.4.1",
|
||||
"resolved": "https://registry.npmjs.org/denque/-/denque-1.4.1.tgz",
|
||||
"integrity": "sha512-OfzPuSZKGcgr96rf1oODnfjqBFmr1DVoc/TrItj3Ohe0Ah1C5WX5Baquw/9U9KovnQ88EqmJbD66rKYUQYN1tQ=="
|
||||
},
|
||||
"depd": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
|
||||
"integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak="
|
||||
},
|
||||
"destroy": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz",
|
||||
"integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA="
|
||||
},
|
||||
"dom-serializer": {
|
||||
"version": "0.1.1",
|
||||
"resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.1.tgz",
|
||||
"integrity": "sha512-l0IU0pPzLWSHBcieZbpOKgkIn3ts3vAh7ZuFyXNwJxJXk/c4Gwj9xaTJwIDVQCXawWD0qb3IzMGH5rglQaO0XA==",
|
||||
"requires": {
|
||||
"domelementtype": "^1.3.0",
|
||||
"entities": "^1.1.1"
|
||||
}
|
||||
},
|
||||
"domelementtype": {
|
||||
"version": "1.3.1",
|
||||
"resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz",
|
||||
"integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w=="
|
||||
},
|
||||
"domhandler": {
|
||||
"version": "2.4.2",
|
||||
"resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.2.tgz",
|
||||
"integrity": "sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==",
|
||||
"requires": {
|
||||
"domelementtype": "1"
|
||||
}
|
||||
},
|
||||
"domutils": {
|
||||
"version": "1.5.1",
|
||||
"resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz",
|
||||
"integrity": "sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8=",
|
||||
"requires": {
|
||||
"dom-serializer": "0",
|
||||
"domelementtype": "1"
|
||||
}
|
||||
},
|
||||
"dottie": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/dottie/-/dottie-2.0.2.tgz",
|
||||
"integrity": "sha512-fmrwR04lsniq/uSr8yikThDTrM7epXHBAAjH9TbeH3rEA8tdCO7mRzB9hdmdGyJCxF8KERo9CITcm3kGuoyMhg=="
|
||||
},
|
||||
"ee-first": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
|
||||
"integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0="
|
||||
},
|
||||
"encodeurl": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
|
||||
"integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k="
|
||||
},
|
||||
"entities": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz",
|
||||
"integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w=="
|
||||
},
|
||||
"escape-html": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
|
||||
"integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg="
|
||||
},
|
||||
"esprima": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
|
||||
"integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A=="
|
||||
},
|
||||
"etag": {
|
||||
"version": "1.8.1",
|
||||
"resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
|
||||
"integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc="
|
||||
},
|
||||
"express": {
|
||||
"version": "4.17.1",
|
||||
"resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz",
|
||||
"integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==",
|
||||
"requires": {
|
||||
"accepts": "~1.3.7",
|
||||
"array-flatten": "1.1.1",
|
||||
"body-parser": "1.19.0",
|
||||
"content-disposition": "0.5.3",
|
||||
"content-type": "~1.0.4",
|
||||
"cookie": "0.4.0",
|
||||
"cookie-signature": "1.0.6",
|
||||
"debug": "2.6.9",
|
||||
"depd": "~1.1.2",
|
||||
"encodeurl": "~1.0.2",
|
||||
"escape-html": "~1.0.3",
|
||||
"etag": "~1.8.1",
|
||||
"finalhandler": "~1.1.2",
|
||||
"fresh": "0.5.2",
|
||||
"merge-descriptors": "1.0.1",
|
||||
"methods": "~1.1.2",
|
||||
"on-finished": "~2.3.0",
|
||||
"parseurl": "~1.3.3",
|
||||
"path-to-regexp": "0.1.7",
|
||||
"proxy-addr": "~2.0.5",
|
||||
"qs": "6.7.0",
|
||||
"range-parser": "~1.2.1",
|
||||
"safe-buffer": "5.1.2",
|
||||
"send": "0.17.1",
|
||||
"serve-static": "1.14.1",
|
||||
"setprototypeof": "1.1.1",
|
||||
"statuses": "~1.5.0",
|
||||
"type-is": "~1.6.18",
|
||||
"utils-merge": "1.0.1",
|
||||
"vary": "~1.1.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"debug": {
|
||||
"version": "2.6.9",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
|
||||
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
|
||||
"requires": {
|
||||
"ms": "2.0.0"
|
||||
}
|
||||
},
|
||||
"ms": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
|
||||
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
|
||||
},
|
||||
"safe-buffer": {
|
||||
"version": "5.1.2",
|
||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
|
||||
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"express-logging": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/express-logging/-/express-logging-1.1.1.tgz",
|
||||
"integrity": "sha1-YoOWGMurW7NhDxocFIU1L+nSbCo=",
|
||||
"requires": {
|
||||
"on-headers": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"finalhandler": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz",
|
||||
"integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==",
|
||||
"requires": {
|
||||
"debug": "2.6.9",
|
||||
"encodeurl": "~1.0.2",
|
||||
"escape-html": "~1.0.3",
|
||||
"on-finished": "~2.3.0",
|
||||
"parseurl": "~1.3.3",
|
||||
"statuses": "~1.5.0",
|
||||
"unpipe": "~1.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"debug": {
|
||||
"version": "2.6.9",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
|
||||
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
|
||||
"requires": {
|
||||
"ms": "2.0.0"
|
||||
}
|
||||
},
|
||||
"ms": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
|
||||
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
|
||||
}
|
||||
}
|
||||
},
|
||||
"find-replace": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/find-replace/-/find-replace-3.0.0.tgz",
|
||||
"integrity": "sha512-6Tb2myMioCAgv5kfvP5/PkZZ/ntTpVK39fHY7WkWBgvbeE+VHd/tZuZ4mrC+bxh4cfOZeYKVPaJIZtZXV7GNCQ==",
|
||||
"requires": {
|
||||
"array-back": "^3.0.1"
|
||||
}
|
||||
},
|
||||
"forwarded": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz",
|
||||
"integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ="
|
||||
},
|
||||
"fresh": {
|
||||
"version": "0.5.2",
|
||||
"resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
|
||||
"integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac="
|
||||
},
|
||||
"generate-function": {
|
||||
"version": "2.3.1",
|
||||
"resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.3.1.tgz",
|
||||
"integrity": "sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==",
|
||||
"requires": {
|
||||
"is-property": "^1.0.2"
|
||||
}
|
||||
},
|
||||
"htmlparser2": {
|
||||
"version": "3.10.1",
|
||||
"resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.10.1.tgz",
|
||||
"integrity": "sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ==",
|
||||
"requires": {
|
||||
"domelementtype": "^1.3.1",
|
||||
"domhandler": "^2.3.0",
|
||||
"domutils": "^1.5.1",
|
||||
"entities": "^1.1.1",
|
||||
"inherits": "^2.0.1",
|
||||
"readable-stream": "^3.1.1"
|
||||
}
|
||||
},
|
||||
"http-errors": {
|
||||
"version": "1.7.2",
|
||||
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz",
|
||||
"integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==",
|
||||
"requires": {
|
||||
"depd": "~1.1.2",
|
||||
"inherits": "2.0.3",
|
||||
"setprototypeof": "1.1.1",
|
||||
"statuses": ">= 1.5.0 < 2",
|
||||
"toidentifier": "1.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"inherits": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
|
||||
"integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
|
||||
}
|
||||
}
|
||||
},
|
||||
"http-status-codes": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/http-status-codes/-/http-status-codes-1.4.0.tgz",
|
||||
"integrity": "sha512-JrT3ua+WgH8zBD3HEJYbeEgnuQaAnUeRRko/YojPAJjGmIfGD3KPU/asLdsLwKjfxOmQe5nXMQ0pt/7MyapVbQ=="
|
||||
},
|
||||
"iconv-lite": {
|
||||
"version": "0.4.24",
|
||||
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
|
||||
"integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
|
||||
"requires": {
|
||||
"safer-buffer": ">= 2.1.2 < 3"
|
||||
}
|
||||
},
|
||||
"inflection": {
|
||||
"version": "1.12.0",
|
||||
"resolved": "https://registry.npmjs.org/inflection/-/inflection-1.12.0.tgz",
|
||||
"integrity": "sha1-ogCTVlbW9fa8TcdQLhrstwMihBY="
|
||||
},
|
||||
"inherits": {
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
|
||||
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
|
||||
},
|
||||
"ipaddr.js": {
|
||||
"version": "1.9.1",
|
||||
"resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
|
||||
"integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g=="
|
||||
},
|
||||
"is-bluebird": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/is-bluebird/-/is-bluebird-1.0.2.tgz",
|
||||
"integrity": "sha1-CWQ5Bg9KpBGr7hkUOoTWpVNG1uI="
|
||||
},
|
||||
"is-property": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz",
|
||||
"integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ="
|
||||
},
|
||||
"lodash": {
|
||||
"version": "4.17.20",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz",
|
||||
"integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA=="
|
||||
},
|
||||
"lodash.camelcase": {
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz",
|
||||
"integrity": "sha1-soqmKIorn8ZRA1x3EfZathkDMaY="
|
||||
},
|
||||
"logops": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/logops/-/logops-2.1.1.tgz",
|
||||
"integrity": "sha512-4VKuufobS4yzCsU3iyKJSudYhZfzg1aHO6j2aTdYf1K1kWz6+Mhfi91BqD+RXtokLpSfocc9vOkzbsun5U4OiQ==",
|
||||
"requires": {
|
||||
"colors": "^1.1.2",
|
||||
"lodash": "^4.17.15",
|
||||
"safe-json-stringify": "^1.2.0",
|
||||
"serr": "^1.0.1"
|
||||
}
|
||||
},
|
||||
"long": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz",
|
||||
"integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA=="
|
||||
},
|
||||
"lru-cache": {
|
||||
"version": "5.1.1",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
|
||||
"integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
|
||||
"requires": {
|
||||
"yallist": "^3.0.2"
|
||||
}
|
||||
},
|
||||
"media-typer": {
|
||||
"version": "0.3.0",
|
||||
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
|
||||
"integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g="
|
||||
},
|
||||
"merge-descriptors": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
|
||||
"integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E="
|
||||
},
|
||||
"methods": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
|
||||
"integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4="
|
||||
},
|
||||
"mime-db": {
|
||||
"version": "1.44.0",
|
||||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz",
|
||||
"integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg=="
|
||||
},
|
||||
"mime-types": {
|
||||
"version": "2.1.27",
|
||||
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz",
|
||||
"integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==",
|
||||
"requires": {
|
||||
"mime-db": "1.44.0"
|
||||
}
|
||||
},
|
||||
"moment": {
|
||||
"version": "2.27.0",
|
||||
"resolved": "https://registry.npmjs.org/moment/-/moment-2.27.0.tgz",
|
||||
"integrity": "sha512-al0MUK7cpIcglMv3YF13qSgdAIqxHTO7brRtaz3DlSULbqfazqkc5kEjNrLDOM7fsjshoFIihnU8snrP7zUvhQ=="
|
||||
},
|
||||
"moment-timezone": {
|
||||
"version": "0.5.31",
|
||||
"resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.31.tgz",
|
||||
"integrity": "sha512-+GgHNg8xRhMXfEbv81iDtrVeTcWt0kWmTEY1XQK14dICTXnWJnT0dxdlPspwqF3keKMVPXwayEsk1DI0AA/jdA==",
|
||||
"requires": {
|
||||
"moment": ">= 2.9.0"
|
||||
}
|
||||
},
|
||||
"ms": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
||||
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
|
||||
},
|
||||
"mysql2": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/mysql2/-/mysql2-2.1.0.tgz",
|
||||
"integrity": "sha512-9kGVyi930rG2KaHrz3sHwtc6K+GY9d8wWk1XRSYxQiunvGcn4DwuZxOwmK11ftuhhwrYDwGx9Ta4VBwznJn36A==",
|
||||
"requires": {
|
||||
"cardinal": "^2.1.1",
|
||||
"denque": "^1.4.1",
|
||||
"generate-function": "^2.3.1",
|
||||
"iconv-lite": "^0.5.0",
|
||||
"long": "^4.0.0",
|
||||
"lru-cache": "^5.1.1",
|
||||
"named-placeholders": "^1.1.2",
|
||||
"seq-queue": "^0.0.5",
|
||||
"sqlstring": "^2.3.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"iconv-lite": {
|
||||
"version": "0.5.2",
|
||||
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.5.2.tgz",
|
||||
"integrity": "sha512-kERHXvpSaB4aU3eANwidg79K8FlrN77m8G9V+0vOR3HYaRifrlwMEpT7ZBJqLSEIHnEgJTHcWK82wwLwwKwtag==",
|
||||
"requires": {
|
||||
"safer-buffer": ">= 2.1.2 < 3"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"named-placeholders": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/named-placeholders/-/named-placeholders-1.1.2.tgz",
|
||||
"integrity": "sha512-wiFWqxoLL3PGVReSZpjLVxyJ1bRqe+KKJVbr4hGs1KWfTZTQyezHFBbuKj9hsizHyGV2ne7EMjHdxEGAybD5SA==",
|
||||
"requires": {
|
||||
"lru-cache": "^4.1.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"lru-cache": {
|
||||
"version": "4.1.5",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz",
|
||||
"integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==",
|
||||
"requires": {
|
||||
"pseudomap": "^1.0.2",
|
||||
"yallist": "^2.1.2"
|
||||
}
|
||||
},
|
||||
"yallist": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz",
|
||||
"integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI="
|
||||
}
|
||||
}
|
||||
},
|
||||
"negotiator": {
|
||||
"version": "0.6.2",
|
||||
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz",
|
||||
"integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw=="
|
||||
},
|
||||
"node-fetch": {
|
||||
"version": "2.6.0",
|
||||
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.0.tgz",
|
||||
"integrity": "sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA=="
|
||||
},
|
||||
"nth-check": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz",
|
||||
"integrity": "sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==",
|
||||
"requires": {
|
||||
"boolbase": "~1.0.0"
|
||||
}
|
||||
},
|
||||
"on-finished": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
|
||||
"integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=",
|
||||
"requires": {
|
||||
"ee-first": "1.1.1"
|
||||
}
|
||||
},
|
||||
"on-headers": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz",
|
||||
"integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA=="
|
||||
},
|
||||
"parse5": {
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/parse5/-/parse5-3.0.3.tgz",
|
||||
"integrity": "sha512-rgO9Zg5LLLkfJF9E6CCmXlSE4UVceloys8JrFqCcHloC3usd/kJCyPDwH2SOlzix2j3xaP9sUX3e8+kvkuleAA==",
|
||||
"requires": {
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"parseurl": {
|
||||
"version": "1.3.3",
|
||||
"resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
|
||||
"integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ=="
|
||||
},
|
||||
"path-to-regexp": {
|
||||
"version": "0.1.7",
|
||||
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
|
||||
"integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w="
|
||||
},
|
||||
"proxy-addr": {
|
||||
"version": "2.0.6",
|
||||
"resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz",
|
||||
"integrity": "sha512-dh/frvCBVmSsDYzw6n926jv974gddhkFPfiN8hPOi30Wax25QZyZEGveluCgliBnqmuM+UJmBErbAUFIoDbjOw==",
|
||||
"requires": {
|
||||
"forwarded": "~0.1.2",
|
||||
"ipaddr.js": "1.9.1"
|
||||
}
|
||||
},
|
||||
"pseudomap": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz",
|
||||
"integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM="
|
||||
},
|
||||
"qs": {
|
||||
"version": "6.7.0",
|
||||
"resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz",
|
||||
"integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ=="
|
||||
},
|
||||
"range-parser": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
|
||||
"integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg=="
|
||||
},
|
||||
"raw-body": {
|
||||
"version": "2.4.0",
|
||||
"resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz",
|
||||
"integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==",
|
||||
"requires": {
|
||||
"bytes": "3.1.0",
|
||||
"http-errors": "1.7.2",
|
||||
"iconv-lite": "0.4.24",
|
||||
"unpipe": "1.0.0"
|
||||
}
|
||||
},
|
||||
"readable-stream": {
|
||||
"version": "3.6.0",
|
||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
|
||||
"integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
|
||||
"requires": {
|
||||
"inherits": "^2.0.3",
|
||||
"string_decoder": "^1.1.1",
|
||||
"util-deprecate": "^1.0.1"
|
||||
}
|
||||
},
|
||||
"redeyed": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/redeyed/-/redeyed-2.1.1.tgz",
|
||||
"integrity": "sha1-iYS1gV2ZyyIEacme7v/jiRPmzAs=",
|
||||
"requires": {
|
||||
"esprima": "~4.0.0"
|
||||
}
|
||||
},
|
||||
"retry-as-promised": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/retry-as-promised/-/retry-as-promised-3.2.0.tgz",
|
||||
"integrity": "sha512-CybGs60B7oYU/qSQ6kuaFmRd9sTZ6oXSc0toqePvV74Ac6/IFZSI1ReFQmtCN+uvW1Mtqdwpvt/LGOiCBAY2Mg==",
|
||||
"requires": {
|
||||
"any-promise": "^1.3.0"
|
||||
}
|
||||
},
|
||||
"safe-buffer": {
|
||||
"version": "5.2.1",
|
||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
|
||||
"integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="
|
||||
},
|
||||
"safe-json-stringify": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/safe-json-stringify/-/safe-json-stringify-1.2.0.tgz",
|
||||
"integrity": "sha512-gH8eh2nZudPQO6TytOvbxnuhYBOvDBBLW52tz5q6X58lJcd/tkmqFR+5Z9adS8aJtURSXWThWy/xJtJwixErvg=="
|
||||
},
|
||||
"safer-buffer": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
|
||||
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
|
||||
},
|
||||
"semver": {
|
||||
"version": "6.3.0",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
|
||||
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw=="
|
||||
},
|
||||
"send": {
|
||||
"version": "0.17.1",
|
||||
"resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz",
|
||||
"integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==",
|
||||
"requires": {
|
||||
"debug": "2.6.9",
|
||||
"depd": "~1.1.2",
|
||||
"destroy": "~1.0.4",
|
||||
"encodeurl": "~1.0.2",
|
||||
"escape-html": "~1.0.3",
|
||||
"etag": "~1.8.1",
|
||||
"fresh": "0.5.2",
|
||||
"http-errors": "~1.7.2",
|
||||
"mime": "1.6.0",
|
||||
"ms": "2.1.1",
|
||||
"on-finished": "~2.3.0",
|
||||
"range-parser": "~1.2.1",
|
||||
"statuses": "~1.5.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"debug": {
|
||||
"version": "2.6.9",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
|
||||
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
|
||||
"requires": {
|
||||
"ms": "2.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"ms": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
|
||||
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
|
||||
}
|
||||
}
|
||||
},
|
||||
"mime": {
|
||||
"version": "1.6.0",
|
||||
"resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
|
||||
"integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg=="
|
||||
},
|
||||
"ms": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
|
||||
"integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"seq-queue": {
|
||||
"version": "0.0.5",
|
||||
"resolved": "https://registry.npmjs.org/seq-queue/-/seq-queue-0.0.5.tgz",
|
||||
"integrity": "sha1-1WgS4cAXpuTnw+Ojeh2m143TyT4="
|
||||
},
|
||||
"sequelize": {
|
||||
"version": "5.22.3",
|
||||
"resolved": "https://registry.npmjs.org/sequelize/-/sequelize-5.22.3.tgz",
|
||||
"integrity": "sha512-+nxf4TzdrB+PRmoWhR05TP9ukLAurK7qtKcIFv5Vhxm5Z9v+d2PcTT6Ea3YAoIQVkZ47QlT9XWAIUevMT/3l8Q==",
|
||||
"requires": {
|
||||
"bluebird": "^3.5.0",
|
||||
"cls-bluebird": "^2.1.0",
|
||||
"debug": "^4.1.1",
|
||||
"dottie": "^2.0.0",
|
||||
"inflection": "1.12.0",
|
||||
"lodash": "^4.17.15",
|
||||
"moment": "^2.24.0",
|
||||
"moment-timezone": "^0.5.21",
|
||||
"retry-as-promised": "^3.2.0",
|
||||
"semver": "^6.3.0",
|
||||
"sequelize-pool": "^2.3.0",
|
||||
"toposort-class": "^1.0.1",
|
||||
"uuid": "^3.3.3",
|
||||
"validator": "^10.11.0",
|
||||
"wkx": "^0.4.8"
|
||||
}
|
||||
},
|
||||
"sequelize-pool": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/sequelize-pool/-/sequelize-pool-2.3.0.tgz",
|
||||
"integrity": "sha512-Ibz08vnXvkZ8LJTiUOxRcj1Ckdn7qafNZ2t59jYHMX1VIebTAOYefWdRYFt6z6+hy52WGthAHAoLc9hvk3onqA=="
|
||||
},
|
||||
"serr": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/serr/-/serr-1.0.1.tgz",
|
||||
"integrity": "sha1-dKW55/rdW1X4qF5+crwApBm25II=",
|
||||
"requires": {
|
||||
"lodash": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"serve-static": {
|
||||
"version": "1.14.1",
|
||||
"resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz",
|
||||
"integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==",
|
||||
"requires": {
|
||||
"encodeurl": "~1.0.2",
|
||||
"escape-html": "~1.0.3",
|
||||
"parseurl": "~1.3.3",
|
||||
"send": "0.17.1"
|
||||
}
|
||||
},
|
||||
"setprototypeof": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz",
|
||||
"integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw=="
|
||||
},
|
||||
"shimmer": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/shimmer/-/shimmer-1.2.1.tgz",
|
||||
"integrity": "sha512-sQTKC1Re/rM6XyFM6fIAGHRPVGvyXfgzIDvzoq608vM+jeyVD0Tu1E6Np0Kc2zAIFWIj963V2800iF/9LPieQw=="
|
||||
},
|
||||
"sqlstring": {
|
||||
"version": "2.3.2",
|
||||
"resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.2.tgz",
|
||||
"integrity": "sha512-vF4ZbYdKS8OnoJAWBmMxCQDkiEBkGQYU7UZPtL8flbDRSNkhaXvRJ279ZtI6M+zDaQovVU4tuRgzK5fVhvFAhg=="
|
||||
},
|
||||
"statuses": {
|
||||
"version": "1.5.0",
|
||||
"resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
|
||||
"integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow="
|
||||
},
|
||||
"string_decoder": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
|
||||
"integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
|
||||
"requires": {
|
||||
"safe-buffer": "~5.2.0"
|
||||
}
|
||||
},
|
||||
"toidentifier": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz",
|
||||
"integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw=="
|
||||
},
|
||||
"toposort-class": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/toposort-class/-/toposort-class-1.0.1.tgz",
|
||||
"integrity": "sha1-f/0feMi+KMO6Rc1OGj9e4ZO9mYg="
|
||||
},
|
||||
"type-is": {
|
||||
"version": "1.6.18",
|
||||
"resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
|
||||
"integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==",
|
||||
"requires": {
|
||||
"media-typer": "0.3.0",
|
||||
"mime-types": "~2.1.24"
|
||||
}
|
||||
},
|
||||
"typical": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/typical/-/typical-4.0.0.tgz",
|
||||
"integrity": "sha512-VAH4IvQ7BDFYglMd7BPRDfLgxZZX4O4TFcRDA6EN5X7erNJJq+McIEp8np9aVtxrCJ6qx4GTYVfOWNjcqwZgRw=="
|
||||
},
|
||||
"unpipe": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
|
||||
"integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw="
|
||||
},
|
||||
"util-deprecate": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
||||
"integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8="
|
||||
},
|
||||
"utils-merge": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
|
||||
"integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM="
|
||||
},
|
||||
"uuid": {
|
||||
"version": "3.4.0",
|
||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
|
||||
"integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A=="
|
||||
},
|
||||
"validator": {
|
||||
"version": "10.11.0",
|
||||
"resolved": "https://registry.npmjs.org/validator/-/validator-10.11.0.tgz",
|
||||
"integrity": "sha512-X/p3UZerAIsbBfN/IwahhYaBbY68EN/UQBWHtsbXGT5bfrH/p4NQzUCG1kF/rtKaNpnJ7jAu6NGTdSNtyNIXMw=="
|
||||
},
|
||||
"vary": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
|
||||
"integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw="
|
||||
},
|
||||
"wkx": {
|
||||
"version": "0.4.8",
|
||||
"resolved": "https://registry.npmjs.org/wkx/-/wkx-0.4.8.tgz",
|
||||
"integrity": "sha512-ikPXMM9IR/gy/LwiOSqWlSL3X/J5uk9EO2hHNRXS41eTLXaUFEVw9fn/593jW/tE5tedNg8YjT5HkCa4FqQZyQ==",
|
||||
"requires": {
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"yallist": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
|
||||
"integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="
|
||||
}
|
||||
}
|
||||
}
|
||||
23
package.json
Executable file
23
package.json
Executable file
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"name": "cx-amazon-crawler",
|
||||
"version": "1.0.0",
|
||||
"description": "C-Xtra headless browser for crawling service",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1",
|
||||
"start": "node index.js"
|
||||
},
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"cheerio": "^1.0.0-rc.3",
|
||||
"command-line-args": "^5.1.1",
|
||||
"express": "^4.17.1",
|
||||
"express-logging": "^1.1.1",
|
||||
"http-status-codes": "^1.4.0",
|
||||
"logops": "^2.1.1",
|
||||
"mysql2": "^2.1.0",
|
||||
"node-fetch": "^2.6.0",
|
||||
"sequelize": "^5.22.3"
|
||||
}
|
||||
}
|
||||
51
src/Amazon.js
Executable file
51
src/Amazon.js
Executable file
@@ -0,0 +1,51 @@
|
||||
const Product = require('./Product')
|
||||
, parser = require('./Parser')
|
||||
, client = require('./Client');
|
||||
|
||||
|
||||
|
||||
const amazon = {
|
||||
us: {
|
||||
data: {
|
||||
url: 'https://www.amazon.com',
|
||||
categories: {},
|
||||
subcategories: {}
|
||||
},
|
||||
utils: {
|
||||
fakeTitle: (length, calls, leadingTxt) => {
|
||||
let result = '';
|
||||
let characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
|
||||
let charactersLength = characters.length;
|
||||
for (var i = 0; i < length; i++) {
|
||||
result += characters.charAt(Math.floor(Math.random() * charactersLength));
|
||||
}
|
||||
let lengthRand = length //Math.ceil(Math.random(3, length))
|
||||
return --calls ? amazon.us.utils.fakeTitle(lengthRand, calls, leadingTxt + result + '-') : leadingTxt + result;
|
||||
}
|
||||
},
|
||||
task: {
|
||||
categories: () => {
|
||||
return client.request({ amazon: amazon, call: 'categories' }).then(parser.categories);
|
||||
},
|
||||
subCategories: (category) => {
|
||||
return client.request({ amazon: amazon, category: category, call: 'subCategories' }).then(parser.subCategories);
|
||||
},
|
||||
|
||||
productLink: (link) => {
|
||||
return client.request({ amazon: amazon, link: link, call: 'productLinks' }).then(parser.productLinks);
|
||||
},
|
||||
|
||||
productDetail: (asin) => {
|
||||
let product = new Product()
|
||||
return product.fetch(amazon, asin)
|
||||
},
|
||||
|
||||
offerListing: (asin) => {
|
||||
return client.request({ amazon: amazon, asin:asin, call: 'offerListing' }).then(parser.offerListing);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
module.exports = amazon;
|
||||
53
src/Client.js
Executable file
53
src/Client.js
Executable file
@@ -0,0 +1,53 @@
|
||||
const fetch = require("node-fetch");
|
||||
|
||||
|
||||
const Client = {
|
||||
headers: {
|
||||
'authority' : 'www.amazon.com',
|
||||
'method' : 'GET',
|
||||
'path' : '',
|
||||
'scheme' : 'https',
|
||||
'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3',
|
||||
'accept-encoding' : 'gzip, deflate, br',
|
||||
'accept-language' : 'ko-KR,ko;q=0.9,en-US;q=0.8,en;q=0.7',
|
||||
'cache-control' : 'max-age=0',
|
||||
'sec-fetch-mode' : 'navigate',
|
||||
'sec-fetch-site' : 'none',
|
||||
'sec-fetch-user' : '?1',
|
||||
'upgrade-insecure-requests' : '1',
|
||||
'user-agent' : 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36',
|
||||
cookie: 'lc-main=ko_KR;i18n-prefs=KRW'
|
||||
},
|
||||
request: async (args) => {
|
||||
let url = Client[args.call](args)
|
||||
Client.headers['path'] = url.replace(args.amazon.us.data.url, '')
|
||||
return fetch(url, { headers: Client.headers }).then(res => res.textConverted());
|
||||
},
|
||||
offerListing: (args) => {
|
||||
let url = args.amazon.us.data.url + '/dp/offer-listing/' + args.asin + '/ref=dp_olp_new_mbc?ie=UTF8&condition=new';
|
||||
console.log('- request product offer listing page url : ' + url);
|
||||
return url;
|
||||
},
|
||||
productDetail: (args) => {
|
||||
let url = args.amazon.us.data.url + '/' + args.amazon.us.utils.fakeTitle(7, 4, '') + '/dp/' + args.asin;
|
||||
console.log('- request product detail page url : ' + url);
|
||||
return url;
|
||||
},
|
||||
categories: (args) => {
|
||||
let url = args.amazon.us.data.url + '/gp/site-directory';
|
||||
console.log('- request category page url : ' + url)
|
||||
return url;
|
||||
},
|
||||
subCategories: (args) => {
|
||||
let url = args.amazon.us.data.url + args.category.link;
|
||||
console.log('- request sub category page url : ' + url)
|
||||
return url;
|
||||
},
|
||||
productLinks: (args) => {
|
||||
let url = args.amazon.us.data.url + args.link;
|
||||
console.log('- request product links page url : ' + url)
|
||||
return url;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Client;
|
||||
54
src/Parser.js
Executable file
54
src/Parser.js
Executable file
@@ -0,0 +1,54 @@
|
||||
const cheerio = require("cheerio");
|
||||
|
||||
const Parser = {
|
||||
categories: body => {
|
||||
let data = []
|
||||
const $ = cheerio.load(body)
|
||||
$(".a-container a").map((k, v) => {
|
||||
data.push({
|
||||
link: $(v).attr('href'),
|
||||
title: $(v).text()
|
||||
});
|
||||
})
|
||||
console.log('- fetching ' + data.length + ' category links completed')
|
||||
return data
|
||||
},
|
||||
subCategories: body => {
|
||||
let data = []
|
||||
const $ = cheerio.load(body)
|
||||
$(".left_nav.browseBox li a").map((k, v) => {
|
||||
data.push({
|
||||
link: $(v).attr('href'),
|
||||
title: $(v).text()
|
||||
});
|
||||
})
|
||||
return data;
|
||||
},
|
||||
productLinks: body => {
|
||||
let data = []
|
||||
const $ = cheerio.load(body)
|
||||
$("#mainResults a.a-link-normal").map((k, v) => {
|
||||
let title = $(v).find('h2').text().trim();
|
||||
if (title) {
|
||||
data.push({
|
||||
link: $(v).attr('href'),
|
||||
title: title
|
||||
});
|
||||
}
|
||||
})
|
||||
// console.log(data)
|
||||
amazon.us.data.subcategories = data;
|
||||
data.forEach((v, k) => {
|
||||
console.log(v.link)
|
||||
})
|
||||
},
|
||||
|
||||
offerListing: body => {
|
||||
const $ = cheerio.load(body)
|
||||
let stock = $('#olpOfferList .a-row.olpOffer').length;
|
||||
let price = $('#olpOfferList div.a-column.a-span2.olpPriceColumn').last().find('span').text().trim();
|
||||
return {stock: stock, price: price}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Parser
|
||||
118
src/Product.js
Executable file
118
src/Product.js
Executable file
@@ -0,0 +1,118 @@
|
||||
const cheerio = require("cheerio")
|
||||
, client = require('./Client');
|
||||
|
||||
|
||||
class Product {
|
||||
|
||||
constructor() {
|
||||
this.data = {}
|
||||
this.amazon = null
|
||||
}
|
||||
|
||||
async fetch(amazon, asin) {
|
||||
this.amazon = amazon;
|
||||
|
||||
let args = [{ amazon: this.amazon, asin: asin, call: 'productDetail', resolver: 'parseHtmlDetail' },
|
||||
{ amazon: this.amazon, asin: asin, call: 'offerListing', resolver: 'parseHtmlOfferListing' }]
|
||||
let fetchPromises = args.map(async args => {
|
||||
return await client.request(args)
|
||||
})
|
||||
|
||||
for (let k in fetchPromises) {
|
||||
await fetchPromises[k].then(body => this[args[k].resolver](body))
|
||||
}
|
||||
this.data.asin = asin
|
||||
return this.data
|
||||
}
|
||||
|
||||
parseHtmlDetail(body) {
|
||||
let $ = cheerio.load(body)
|
||||
this.data.title = $('#productTitle').text().trim()
|
||||
let merchant = $('#merchant-info a');
|
||||
if (!merchant.length) {
|
||||
merchant = $('#merchant-info');
|
||||
}
|
||||
this.data.seller = {
|
||||
title: merchant.text().replace('에서 판매하고 배송합니다.', '').replace('주문 처리', '').trim(),
|
||||
link: merchant.attr('href')
|
||||
}
|
||||
|
||||
this.data.img = $('#landingImage').attr('src')
|
||||
this.data.description = this.description(this.amazon, $)
|
||||
this.data.category = this.category(this.amazon, $)
|
||||
this.data.price = this.price(this.amazon, $)
|
||||
this.data.colors = this.colors(this.amazon, $)
|
||||
this.data.colorsASIN = this.colorsASIN(this.amazon, $)
|
||||
}
|
||||
|
||||
description(amazon, $) {
|
||||
return {
|
||||
content: $('#aplus').html(),
|
||||
spec: $('#descriptionAndDetails').html(),
|
||||
videos: function () {
|
||||
if ($('#vse-rel-videos-carousel ol li a').length) {
|
||||
return {
|
||||
link: amazon.us.data.url + $('#vse-rel-videos-carousel ol li a').eq(0).attr('href'),
|
||||
title: $('#vse-rel-videos-carousel ol li a div.vse-video-content .vse-video-title-text').eq(0).text().trim()
|
||||
}
|
||||
} else return {}
|
||||
}()
|
||||
}
|
||||
}
|
||||
|
||||
parseHtmlOfferListing(body) {
|
||||
let $ = cheerio.load(body)
|
||||
let stock = $('#olpOfferList .a-row.olpOffer').length;
|
||||
let price = $('#olpOfferList div.a-column.a-span2.olpPriceColumn').last().find('span').text().trim();
|
||||
// let seller = $('#olpOfferList .olpSellerName').last().find('span a').text().trim();
|
||||
// let sellerLink = $('#olpOfferList .olpSellerName').last().find('span a').attr('href');
|
||||
this.data.stock = stock;
|
||||
this.data.price = price;
|
||||
// this.data.seller = { title: seller, link: sellerLink }
|
||||
}
|
||||
|
||||
category(amazon, $) {
|
||||
let categoryPath = []
|
||||
$('#wayfinding-breadcrumbs_feature_div li a').map((k, n) => {
|
||||
categoryPath.push({ title: $(n).text().trim(), link: amazon.us.data.url + $(n).attr('href') })
|
||||
})
|
||||
return categoryPath
|
||||
}
|
||||
|
||||
price(amazon, $) {
|
||||
let price;
|
||||
price = $('#olp-upd-new > span > a').eq(0).text().trim()
|
||||
if (price) {
|
||||
if (price.split('$').length == 2) {
|
||||
return '$' + price.split('$')[1]
|
||||
}
|
||||
}
|
||||
price = $('#priceblock_ourprice').text().trim()
|
||||
if (price) return price
|
||||
}
|
||||
|
||||
colors(amazon, $) {
|
||||
let colors = []
|
||||
$('li[id^=color_name_]').map((k, n) => {
|
||||
colors.push({
|
||||
img: $(n).find('img').attr('src'),
|
||||
title: $(n).find('img').attr('alt'),
|
||||
})
|
||||
})
|
||||
return colors
|
||||
}
|
||||
colorsASIN(amazon, $) {
|
||||
let colorsASIN = []
|
||||
$('li[id^=color_name_]').map((k, n) => {
|
||||
let asin = $(n).attr('data-defaultasin');
|
||||
if (!asin) {
|
||||
asin = $(n).attr('data-dp-url').split('/')[2];
|
||||
}
|
||||
colorsASIN.push(asin)
|
||||
})
|
||||
return colorsASIN
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
module.exports = Product;
|
||||
117
src/component/PurchaseComponent.js
Normal file
117
src/component/PurchaseComponent.js
Normal file
@@ -0,0 +1,117 @@
|
||||
const logger = require('logops')
|
||||
, db = require("../model");
|
||||
|
||||
|
||||
|
||||
class PurchaseComponent {
|
||||
|
||||
getPurchaseData(data, now) {
|
||||
return {
|
||||
OrgCode: data.orgCode,
|
||||
PurchaseNo: data.purchaseNo,
|
||||
Status: data.status,
|
||||
CreatedAt: now
|
||||
}
|
||||
}
|
||||
|
||||
getPurchaseItemData(itemData, purchase, now) {
|
||||
return itemData.map(item => {
|
||||
return {
|
||||
PurchaseId: purchase.Id,
|
||||
ItemLink: item.itemLink,
|
||||
ItemName: item.itemName,
|
||||
ItemBrand: item.itemBrand,
|
||||
ItemUnitPrice: item.itemUnitPrice,
|
||||
ItemTax: item.itemTax,
|
||||
ItemCount: item.itemCount,
|
||||
Status: item.status,
|
||||
CreatedAt: now
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
getSearchPurchaseItemClause(params) {
|
||||
let clause = { where: {}, raw: true }
|
||||
if (params.purchaseId) {
|
||||
clause.where.PurchaseId = Array.isArray(params.purchaseId) ? { [db.Sequelize.Op.in]: params.purchaseId } : params.purchaseId
|
||||
}
|
||||
if (params.id) {
|
||||
clause.where.Id = Array.isArray(params.id) ? { [db.Sequelize.Op.in]: params.id } : params.id
|
||||
}
|
||||
if (params.sdate && params.edate) {
|
||||
clause.where[params.daterangeby ? params.daterangeby : 'CreatedAt'] = { [db.Sequelize.Op.between]: [params.sdate, params.edate] }
|
||||
}
|
||||
if (params.limit) {
|
||||
clause.limit = parseInt(params.limit)
|
||||
}
|
||||
if (params.offset) {
|
||||
clause.offset = parseInt(params.offset)
|
||||
}
|
||||
if (params.column) {
|
||||
clause.attributes = Array.isArray(params.column) ? params.column : [params.column]
|
||||
}
|
||||
if (params.sort) {
|
||||
clause.order = [
|
||||
[params.sort, params.order ? params.order.toUpperCase() : 'ASC']
|
||||
]
|
||||
}
|
||||
return clause
|
||||
}
|
||||
|
||||
findPurchaseById(purchaseId) {
|
||||
let purchases = {}
|
||||
return db.purchase.findAll({ where: { Id: { [db.Sequelize.Op.in]: purchaseId } } }).then(rows => {
|
||||
rows.forEach(p => {
|
||||
purchases[p.Id] = p
|
||||
})
|
||||
return purchases
|
||||
})
|
||||
}
|
||||
|
||||
findPurchaseItemOptionByItemId(purchaseItemId) {
|
||||
let itemOptions = {}
|
||||
let clause = { where: { ItemId: { [db.Sequelize.Op.in]: purchaseItemId } } }
|
||||
return db.purchaseItemOption.findAll(clause).then(options => {
|
||||
options.forEach(opt => {
|
||||
if (itemOptions.hasOwnProperty(opt.ItemId) == false) {
|
||||
itemOptions[opt.ItemId] = []
|
||||
}
|
||||
itemOptions[opt.ItemId].push([opt.OptName, opt.OptValue])
|
||||
})
|
||||
return itemOptions
|
||||
});
|
||||
}
|
||||
|
||||
getSearchTotalPurchaseItem(params) {
|
||||
let clause = this.getSearchPurchaseItemClause(params)
|
||||
delete clause.limit;
|
||||
return db.purchaseItem.count(clause).then(cnt => cnt)
|
||||
}
|
||||
|
||||
findPurchaseByOrgCodeAndPurchaseNo(params) {
|
||||
let clause = { where: {} }
|
||||
if (params.sword) {
|
||||
clause.where.PurchaseNo = params.sword
|
||||
}
|
||||
if (params.orgCode) {
|
||||
clause.where.OrgCode = params.orgCode
|
||||
}
|
||||
return db.purchase.findAll(clause).then(purchases => {
|
||||
return purchases.map(p => p.Id)
|
||||
})
|
||||
}
|
||||
|
||||
replaceItemOption(itemId, itemOptions) {
|
||||
return db.purchaseItemOption.destroy({ where: { ItemId: itemId } }).then(a => {
|
||||
let options = itemOptions.map(opt => {
|
||||
if(opt.optValue) {
|
||||
return { ItemId: itemId, OptName: opt.optName, OptValue: opt.optValue }
|
||||
}
|
||||
})
|
||||
return db.purchaseItemOption.bulkCreate(options).then(inserted => inserted.length > 0)
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
module.exports = new PurchaseComponent
|
||||
20
src/controller/CrawlController.js
Normal file
20
src/controller/CrawlController.js
Normal file
@@ -0,0 +1,20 @@
|
||||
const service = require("../service/CrawlService")
|
||||
, logger = require('logops');
|
||||
|
||||
|
||||
class CrawlController {
|
||||
getMethodName(req) {
|
||||
return req.method.toLowerCase()
|
||||
+ req.params.what.split('_').map(w => w.charAt(0).toUpperCase() + w.slice(1)).join('')
|
||||
}
|
||||
|
||||
crawl(req, callback) {
|
||||
let fn = this.getMethodName(req);
|
||||
let params = Object.assign(req.body, req.query)
|
||||
params = Object.assign(params, req.params)
|
||||
logger.info('Invoking method TestService.%s', fn)
|
||||
service[fn](params, callback)
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = new CrawlController
|
||||
20
src/controller/PurchaseController.js
Normal file
20
src/controller/PurchaseController.js
Normal file
@@ -0,0 +1,20 @@
|
||||
const purchase = require("../service/PurchaseService")
|
||||
, logger = require('logops');
|
||||
|
||||
|
||||
class PurchaseController {
|
||||
getMethodName(req) {
|
||||
return req.method.toLowerCase()
|
||||
+ req.params.what.split('_').map(w => w.charAt(0).toUpperCase() + w.slice(1)).join('')
|
||||
}
|
||||
|
||||
purchase(req, callback) {
|
||||
let fn = this.getMethodName(req);
|
||||
let params = Object.assign(req.body, req.query)
|
||||
params = Object.assign(params, req.params)
|
||||
logger.info('Invoking method PurchaseService.%s', fn)
|
||||
purchase[fn](params, callback)
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = new PurchaseController
|
||||
85
src/model/IoBoundModel.js
Normal file
85
src/model/IoBoundModel.js
Normal file
@@ -0,0 +1,85 @@
|
||||
/* jshint indent: 2 */
|
||||
|
||||
module.exports = function (sequelize, DataTypes) {
|
||||
return sequelize.define('ioBound', {
|
||||
id: {
|
||||
autoIncrement: true,
|
||||
type: DataTypes.INTEGER(11).UNSIGNED,
|
||||
allowNull: false,
|
||||
primaryKey: true,
|
||||
field: 'id'
|
||||
},
|
||||
IoType: {
|
||||
type: DataTypes.STRING(2),
|
||||
allowNull: false,
|
||||
field: 'type'
|
||||
},
|
||||
ItemId: {
|
||||
type: DataTypes.STRING(20),
|
||||
allowNull: false,
|
||||
field: 'pcode'
|
||||
},
|
||||
Barcode: {
|
||||
type: DataTypes.STRING(30),
|
||||
allowNull: false,
|
||||
field: 'ean'
|
||||
},
|
||||
SerialNo: {
|
||||
type: DataTypes.STRING(30),
|
||||
allowNull: false,
|
||||
field: 'serialno'
|
||||
},
|
||||
ArtNo: {
|
||||
type: DataTypes.STRING(30),
|
||||
allowNull: false,
|
||||
comment: 'Article Number/PZN',
|
||||
field: 'artno'
|
||||
},
|
||||
Qty: {
|
||||
type: DataTypes.INTEGER(9).UNSIGNED,
|
||||
allowNull: false,
|
||||
comment: '실재고',
|
||||
field: 'qty'
|
||||
},
|
||||
OrgCode: {
|
||||
type: DataTypes.STRING(10),
|
||||
allowNull: false,
|
||||
field: 'c_code'
|
||||
},
|
||||
ShippingCode: {
|
||||
type: DataTypes.STRING(30),
|
||||
allowNull: false,
|
||||
field: 'wcode'
|
||||
},
|
||||
BoxCode: {
|
||||
type: DataTypes.STRING(30),
|
||||
allowNull: false,
|
||||
field: 'bcode'
|
||||
},
|
||||
CreatedBy: {
|
||||
type: DataTypes.STRING(30),
|
||||
allowNull: false,
|
||||
field: 'reg_user'
|
||||
},
|
||||
CreatedAt: {
|
||||
type: DataTypes.DATE,
|
||||
allowNull: true,
|
||||
field: 'regtime'
|
||||
},
|
||||
UpdatedBy: {
|
||||
type: DataTypes.STRING(10),
|
||||
allowNull: false,
|
||||
field: 'update_user'
|
||||
},
|
||||
UpdatedAt: {
|
||||
type: DataTypes.DATE,
|
||||
allowNull: false,
|
||||
field: 'update_time'
|
||||
}
|
||||
}, {
|
||||
sequelize,
|
||||
tableName: 'wms_in_out_bound',
|
||||
freezeTableName: true,
|
||||
timestamps: false
|
||||
});
|
||||
};
|
||||
27
src/model/IoTypeModel.js
Normal file
27
src/model/IoTypeModel.js
Normal file
@@ -0,0 +1,27 @@
|
||||
/* jshint indent: 2 */
|
||||
|
||||
module.exports = function (sequelize, DataTypes) {
|
||||
return sequelize.define('ioType', {
|
||||
code: {
|
||||
type: DataTypes.STRING(2),
|
||||
allowNull: false,
|
||||
primaryKey: true,
|
||||
field: 'code'
|
||||
},
|
||||
Name: {
|
||||
type: DataTypes.STRING(50),
|
||||
allowNull: true,
|
||||
field: 'name'
|
||||
},
|
||||
NameKr: {
|
||||
type: DataTypes.STRING(50),
|
||||
allowNull: true,
|
||||
field: 'name_kr'
|
||||
}
|
||||
}, {
|
||||
sequelize,
|
||||
tableName: 'wms_in_out_type',
|
||||
freezeTableName: true,
|
||||
timestamps: false
|
||||
});
|
||||
};
|
||||
38
src/model/Purchase.js
Normal file
38
src/model/Purchase.js
Normal file
@@ -0,0 +1,38 @@
|
||||
/* jshint indent: 2 */
|
||||
|
||||
module.exports = function(sequelize, DataTypes) {
|
||||
return sequelize.define('purchase', {
|
||||
Id: {
|
||||
type: DataTypes.INTEGER(11).UNSIGNED,
|
||||
allowNull: false,
|
||||
primaryKey: true,
|
||||
autoIncrement: true,
|
||||
field: 'seq'
|
||||
},
|
||||
OrgCode: {
|
||||
type: DataTypes.STRING(10),
|
||||
allowNull: true,
|
||||
field: 'company_code'
|
||||
},
|
||||
PurchaseNo: {
|
||||
type: DataTypes.STRING(50),
|
||||
allowNull: false,
|
||||
unique: true,
|
||||
field: 'purchase_no'
|
||||
},
|
||||
Status: {
|
||||
type: DataTypes.ENUM('발주요청'),
|
||||
allowNull: false,
|
||||
field: 'status'
|
||||
},
|
||||
CreatedAt: {
|
||||
type: DataTypes.DATE,
|
||||
allowNull: false,
|
||||
field: 'created_at'
|
||||
}
|
||||
}, {
|
||||
tableName: 'ibl_purchase',
|
||||
freezeTableName: true,
|
||||
timestamps: false
|
||||
});
|
||||
};
|
||||
62
src/model/PurchaseItem.js
Normal file
62
src/model/PurchaseItem.js
Normal file
@@ -0,0 +1,62 @@
|
||||
/* jshint indent: 2 */
|
||||
|
||||
module.exports = function(sequelize, DataTypes) {
|
||||
return sequelize.define('purchaseItem', {
|
||||
Id: {
|
||||
type: DataTypes.INTEGER(11).UNSIGNED,
|
||||
allowNull: false,
|
||||
primaryKey: true,
|
||||
autoIncrement: true,
|
||||
field: 'seq'
|
||||
},
|
||||
PurchaseId: {
|
||||
type: DataTypes.INTEGER(11).UNSIGNED,
|
||||
allowNull: false,
|
||||
field: 'purchase_seq'
|
||||
},
|
||||
ItemLink: {
|
||||
type: DataTypes.STRING(255),
|
||||
allowNull: false,
|
||||
field: 'item_link'
|
||||
},
|
||||
ItemName: {
|
||||
type: DataTypes.STRING(50),
|
||||
allowNull: false,
|
||||
field: 'item_name'
|
||||
},
|
||||
ItemBrand: {
|
||||
type: DataTypes.STRING(30),
|
||||
allowNull: false,
|
||||
field: 'item_brand'
|
||||
},
|
||||
ItemUnitPrice: {
|
||||
type: DataTypes.DECIMAL,
|
||||
allowNull: false,
|
||||
field: 'item_unit_price'
|
||||
},
|
||||
ItemTax: {
|
||||
type: DataTypes.ENUM('0','7','19','5','16'),
|
||||
allowNull: false,
|
||||
field: 'item_tax'
|
||||
},
|
||||
ItemCount: {
|
||||
type: DataTypes.INTEGER(4),
|
||||
allowNull: false,
|
||||
field: 'item_count'
|
||||
},
|
||||
Status: {
|
||||
type: DataTypes.ENUM('발주요청'),
|
||||
allowNull: false,
|
||||
field: 'status'
|
||||
},
|
||||
CreatedAt: {
|
||||
type: DataTypes.DATE,
|
||||
allowNull: false,
|
||||
field: 'created_at'
|
||||
}
|
||||
}, {
|
||||
tableName: 'ibl_purchase_item',
|
||||
freezeTableName: true,
|
||||
timestamps: false
|
||||
});
|
||||
};
|
||||
23
src/model/PurchaseItemOption.js
Normal file
23
src/model/PurchaseItemOption.js
Normal file
@@ -0,0 +1,23 @@
|
||||
/* jshint indent: 2 */
|
||||
|
||||
module.exports = function(sequelize, DataTypes) {
|
||||
return sequelize.define('purchaseItemOption', {
|
||||
ItemId: {
|
||||
type: DataTypes.INTEGER(11).UNSIGNED,
|
||||
allowNull: false,
|
||||
primaryKey: true
|
||||
},
|
||||
OptName: {
|
||||
type: DataTypes.STRING(100),
|
||||
allowNull: false
|
||||
},
|
||||
OptValue: {
|
||||
type: DataTypes.STRING(100),
|
||||
allowNull: false
|
||||
}
|
||||
}, {
|
||||
tableName: 'ibp_purchase_itemopt',
|
||||
freezeTableName: true,
|
||||
timestamps: false
|
||||
});
|
||||
};
|
||||
42
src/model/index.js
Normal file
42
src/model/index.js
Normal file
@@ -0,0 +1,42 @@
|
||||
'use strict';
|
||||
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const Sequelize = require('sequelize');
|
||||
const basename = path.basename(__filename);
|
||||
const args = require("../../config/Config")
|
||||
const env = args.env || 'development';
|
||||
const config = require('../../config/config.json')[env];
|
||||
const db = {};
|
||||
|
||||
let sequelize;
|
||||
if (config.use_env_variable) {
|
||||
sequelize = new Sequelize(args.database, config.username, config.password, config);
|
||||
} else {
|
||||
sequelize = new Sequelize(config.database, config.username, config.password, config);
|
||||
}
|
||||
|
||||
sequelize.authenticate().then(() => {
|
||||
console.log('Connection has been established successfully.');
|
||||
}).catch(err => {
|
||||
console.error('Unable to connect to the database:', err);
|
||||
process.exit(1)
|
||||
});
|
||||
|
||||
fs.readdirSync(__dirname).filter(file => {
|
||||
return (file.indexOf('.') !== 0) && (file !== basename) && (file.slice(-3) === '.js');
|
||||
}).forEach(file => {
|
||||
const model = sequelize.import(path.join(__dirname, file));
|
||||
db[model.name] = model;
|
||||
});
|
||||
|
||||
Object.keys(db).forEach(modelName => {
|
||||
if (db[modelName].associate) {
|
||||
db[modelName].associate(db);
|
||||
}
|
||||
});
|
||||
|
||||
db.sequelize = sequelize;
|
||||
db.Sequelize = Sequelize;
|
||||
|
||||
module.exports = db;
|
||||
38
src/service/CrawlService.js
Normal file
38
src/service/CrawlService.js
Normal file
@@ -0,0 +1,38 @@
|
||||
const logger = require("logops")
|
||||
, HttpStatus = require('http-status-codes')
|
||||
, cheerio = require('cheerio')
|
||||
, puppeteer = require('puppeteer');
|
||||
|
||||
|
||||
|
||||
|
||||
class CrawlService {
|
||||
|
||||
constructor() {
|
||||
this.browser = null;
|
||||
this.page = null;
|
||||
}
|
||||
|
||||
async request(url) {
|
||||
if (this.page == null) {
|
||||
this.browser = await puppeteer.launch({ headless: true });
|
||||
this.page = await this.browser.newPage();
|
||||
}
|
||||
await this.page.goto(url)
|
||||
return this.page.evaluate(() => document.documentElement.outerHTML)
|
||||
}
|
||||
|
||||
get(params, callback) {
|
||||
this.request('https://www.amazon.de/').then(html => {
|
||||
const $ = cheerio.load(html)
|
||||
let selector = 'div.a-section.a-spacing-none.feed-carousel.first-carousel ul li a'
|
||||
let links = $(selector).map((i, el) => {
|
||||
return $(el).attr('href')
|
||||
}).get()
|
||||
callback(links)
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
module.exports = new CrawlService
|
||||
103
src/service/PurchaseService.js
Normal file
103
src/service/PurchaseService.js
Normal file
@@ -0,0 +1,103 @@
|
||||
const db = require("../model")
|
||||
, logger = require("logops")
|
||||
, restClient = require('../component/RestClientComponent')
|
||||
, HttpStatus = require('http-status-codes')
|
||||
, purchaseComponent = require('../component/PurchaseComponent');
|
||||
|
||||
|
||||
class PurchaseService {
|
||||
response(res, callback) {
|
||||
if (!res.code) res.code = HttpStatus.OK
|
||||
if (!res.message) res.message = HttpStatus.getStatusText(res.code)
|
||||
if (res.code) {
|
||||
callback(res)
|
||||
return;
|
||||
}
|
||||
callback({ code: HttpStatus.NOT_FOUND, message: HttpStatus.getStatusText(HttpStatus.NOT_FOUND) })
|
||||
}
|
||||
|
||||
post(params, callback) {
|
||||
db.purchase.findAll({
|
||||
where: { PurchaseNo: params.itemData[0].purchaseNo }
|
||||
}).then(result => {
|
||||
if (result.length) {
|
||||
logger.error('Purchase No. Duplicated %s', JSON.stringify(params))
|
||||
callback({ code: HttpStatus.CONFLICT, message: HttpStatus.getStatusText(HttpStatus.CONFLICT) })
|
||||
} else {
|
||||
let now = new Date();
|
||||
db.purchase.create(purchaseComponent.getPurchaseData(params.itemData[0], now)).then(purchase => {
|
||||
db.purchaseItem.bulkCreate(purchaseComponent.getPurchaseItemData(params.itemData, purchase, now)).then(createdItems => {
|
||||
let itemOptions = []
|
||||
createdItems.map((created, k) => {
|
||||
params.itemData[k].itemOptions.map(opt => {
|
||||
if (opt.optValue) {
|
||||
itemOptions.push({
|
||||
ItemId: created.Id,
|
||||
OptName: opt.optName,
|
||||
OptValue: opt.optValue
|
||||
})
|
||||
}
|
||||
})
|
||||
})
|
||||
db.purchaseItemOption.bulkCreate(itemOptions).then(result => {
|
||||
callback(result.length ? { inserted: createdItems.map(item => item.Id) } : { inserted: [] })
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
put(params, callback) {
|
||||
let itemOptions = params.ItemOptions;
|
||||
delete params.ItemOptions
|
||||
Promise.all([
|
||||
db.purchaseItem.update(params, { where: { Id: params.Id } }).then(updated => updated > 0),
|
||||
purchaseComponent.replaceItemOption(params.Id, itemOptions)
|
||||
]).then(results => {
|
||||
logger.info('Update purchase promise results - %s', JSON.stringify(results))
|
||||
let code = results.filter(result => result == true).length ? HttpStatus.OK : HttpStatus.NOT_MODIFIED
|
||||
callback({ code: code, message: HttpStatus.getStatusText(code) })
|
||||
})
|
||||
}
|
||||
|
||||
async getSearch(params, callback) {
|
||||
if (params.sword || params.orgCode) {
|
||||
params.purchaseId = await purchaseComponent.findPurchaseByOrgCodeAndPurchaseNo(params);
|
||||
}
|
||||
let clause = purchaseComponent.getSearchPurchaseItemClause(params)
|
||||
if (Object.keys(clause.where).length) {
|
||||
db.purchaseItem.findAll(clause).then(rows => {
|
||||
let responseBody = { code: HttpStatus.NOT_FOUND, message: HttpStatus.getStatusText(HttpStatus.NOT_FOUND) }
|
||||
if (rows.length) {
|
||||
Promise.all([
|
||||
purchaseComponent.getSearchTotalPurchaseItem(params),
|
||||
purchaseComponent.findPurchaseById(rows.map(row => row.PurchaseId)),
|
||||
purchaseComponent.findPurchaseItemOptionByItemId(rows.map(row => row.Id))
|
||||
]).then(results => {
|
||||
let total = results[0]
|
||||
let purchases = results[1];
|
||||
let itemOptions = results[2];
|
||||
rows.forEach((row, k) => {
|
||||
rows[k].PurchaseNo = purchases[row.PurchaseId].PurchaseNo
|
||||
rows[k].OrgCode = purchases[row.PurchaseId].OrgCode
|
||||
rows[k].ItemOptions = itemOptions[row.Id]
|
||||
})
|
||||
responseBody = { code: HttpStatus.OK, message: HttpStatus.getStatusText(HttpStatus.OK), data: { total: total, rows: rows } }
|
||||
this.response(responseBody, callback)
|
||||
})
|
||||
} else {
|
||||
this.response(responseBody, callback)
|
||||
}
|
||||
});
|
||||
} else {
|
||||
logger.debug('Clause has no where statement - %s', JSON.stringify(clause))
|
||||
this.response({
|
||||
code: HttpStatus.BAD_REQUEST,
|
||||
message: HttpStatus.getStatusText(HttpStatus.BAD_REQUEST)
|
||||
}, callback)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = new PurchaseService
|
||||
92
src/service/RestClientService.js
Normal file
92
src/service/RestClientService.js
Normal file
@@ -0,0 +1,92 @@
|
||||
const fetch = require("node-fetch")
|
||||
, logger = require("logops");
|
||||
|
||||
|
||||
class RestClientService {
|
||||
|
||||
constructor() {
|
||||
this.token = null
|
||||
this.emptyResponse = { code: 200, data: null }
|
||||
this.localhost = 'http://localhost:31000/api/v1/'
|
||||
this.clientId = 'F8Nbz9gGUvLgdn8T'
|
||||
this.clientSecret = 'Fesmx7hHCCMx7Cby7FhV2fAtf2NYEFzP5fCKuwEEdpf8hpnsnnQn9qYhNHt6SsDD'
|
||||
this.setToken()
|
||||
}
|
||||
|
||||
setToken() {
|
||||
this.token = null
|
||||
return fetch(this.localhost + 'oauth/token?client_id=' + this.clientId + '&grant_type=client_credentials&client_secret=' + this.clientSecret, {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'content-type': 'application/json'
|
||||
}
|
||||
}).then(res => res.json()).then(res => {
|
||||
logger.debug(res, 'Tracking service got app token successfully')
|
||||
this.token = res.access_token
|
||||
return this.token
|
||||
})
|
||||
}
|
||||
|
||||
getHeader(additionalheaders) {
|
||||
let headers = {
|
||||
"Authorization": "Bearer " + this.token,
|
||||
"Content-Type": "application/json"
|
||||
}
|
||||
return additionalheaders ? Object.assign(headers, additionalheaders) : headers
|
||||
}
|
||||
|
||||
getResponse(data) {
|
||||
if (data.code == 406) {
|
||||
logger.info(data, 'Token expired and requesting new token')
|
||||
this.emptyResponse.tokenPromise = this.setToken();
|
||||
return this.emptyResponse
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
getProductBrandByItemId(params) {
|
||||
return fetch(this.localhost + 'catalog/brand', {
|
||||
method: 'OPTIONS',
|
||||
headers: this.getHeader(),
|
||||
body: JSON.stringify(params)
|
||||
}).then(res => res.json()).then(data => this.getResponse(data))
|
||||
}
|
||||
|
||||
getProductByBrand(params) {
|
||||
return fetch(this.localhost + 'catalog/brand/' + params.brand, {
|
||||
method: 'GET',
|
||||
headers: this.getHeader()
|
||||
}).then(res => res.json()).then(data => this.getResponse(data))
|
||||
}
|
||||
|
||||
getParcel(params) {
|
||||
if (this.token == null) return this.emptyResponse
|
||||
let defaultParams = {
|
||||
"request": "get", "column": ["ShippingCode"],
|
||||
"status": [2], "limit": 1, "offset": 0, "groupby": ["ShippingCode"], "order": [['CreatedAt', 'DESC']],
|
||||
'daterangeby': 'ExportedAt',
|
||||
'daterange': {
|
||||
sdate: (function () {
|
||||
let d = new Date();
|
||||
d.setMonth(d.getMonth() - 1);
|
||||
return d.toLocaleDateString();
|
||||
})(),
|
||||
edate: (function () {
|
||||
let d = new Date();
|
||||
d.setDate(d.getDate() + 2);
|
||||
return d.toLocaleDateString();
|
||||
})()
|
||||
}
|
||||
}
|
||||
Object.assign(defaultParams, params)
|
||||
logger.debug(defaultParams, 'Request parcel service params')
|
||||
return fetch(this.localhost + 'parcel', {
|
||||
method: 'POST',
|
||||
headers: this.getHeader(),
|
||||
body: JSON.stringify(defaultParams)
|
||||
}).then(res => res.json()).then(data => this.getResponse(data))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
module.exports = new RestClientService;
|
||||
Reference in New Issue
Block a user