From 71f47ef898935e5b4de5cfdf54d9c2cb063074ab Mon Sep 17 00:00:00 2001 From: divlo Date: Mon, 22 Mar 2021 20:23:23 +0100 Subject: [PATCH] chore: migrate from express to fastify --- package-lock.json | 499 ++++++++++-------- package.json | 4 +- .../src/api/downloads/download.controller.js | 113 ---- server/src/api/downloads/download.routes.js | 10 - server/src/api/downloads/get.js | 127 +++++ server/src/api/downloads/index.js | 8 + server/src/api/info/get.js | 34 ++ server/src/api/info/index.js | 8 + server/src/api/info/info.controller.js | 34 -- server/src/api/info/info.routes.js | 10 - server/src/core/server.js | 228 ++++---- server/src/middleware/cors.js | 18 - server/src/plugins/cors.js | 19 + server/src/{middleware => plugins}/other.js | 13 +- test/unit/unit.jest.json | 2 +- 15 files changed, 575 insertions(+), 552 deletions(-) delete mode 100644 server/src/api/downloads/download.controller.js delete mode 100644 server/src/api/downloads/download.routes.js create mode 100644 server/src/api/downloads/get.js create mode 100644 server/src/api/downloads/index.js create mode 100644 server/src/api/info/get.js create mode 100644 server/src/api/info/index.js delete mode 100644 server/src/api/info/info.controller.js delete mode 100644 server/src/api/info/info.routes.js delete mode 100644 server/src/middleware/cors.js create mode 100644 server/src/plugins/cors.js rename server/src/{middleware => plugins}/other.js (50%) diff --git a/package-lock.json b/package-lock.json index 7ee6d485..58ff0224 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3824,6 +3824,27 @@ } } }, + "@fastify/forwarded": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@fastify/forwarded/-/forwarded-1.0.0.tgz", + "integrity": "sha512-VoO+6WD0aRz8bwgJZ8pkkxjq7o/782cQ1j945HWg0obZMgIadYW3Pew0+an+k1QL7IPZHM3db5WF6OP6x4ymMA==" + }, + "@fastify/proxy-addr": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@fastify/proxy-addr/-/proxy-addr-3.0.0.tgz", + "integrity": "sha512-ty7wnUd/GeSqKTC2Jozsl5xGbnxUnEFC0On2/zPv/8ixywipQmVZwuWvNGnBoitJ2wixwVqofwXNua8j6Y62lQ==", + "requires": { + "@fastify/forwarded": "^1.0.0", + "ipaddr.js": "^2.0.0" + }, + "dependencies": { + "ipaddr.js": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.0.0.tgz", + "integrity": "sha512-S54H9mIj0rbxRIyrDMEuuER86LdlgUg9FSeZ8duQb6CUG2iRrA36MYVQBSprTF/ZeAwvyQ5mDGuNvIPM0BIl3w==" + } + } + }, "@ffmpeg-installer/darwin-x64": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/@ffmpeg-installer/darwin-x64/-/darwin-x64-4.1.0.tgz", @@ -5953,6 +5974,11 @@ "event-target-shim": "^5.0.0" } }, + "abstract-logging": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/abstract-logging/-/abstract-logging-2.0.1.tgz", + "integrity": "sha512-2BjRTZxTPvheOvGbBslFSYOUkr+SjPtOnrLP33f+VIWLzezQpZcqVg7ja3L4dBXmzzgwT+a029jRx5PCi3JuiA==" + }, "accepts": { "version": "1.3.7", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", @@ -6029,7 +6055,6 @@ "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, "requires": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -6175,6 +6200,11 @@ } } }, + "archy": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", + "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=" + }, "are-we-there-yet": { "version": "1.1.5", "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz", @@ -6210,11 +6240,6 @@ "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", "dev": true }, - "array-flatten": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" - }, "array-includes": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.3.tgz", @@ -6424,6 +6449,32 @@ "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", "dev": true }, + "atomic-sleep": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/atomic-sleep/-/atomic-sleep-1.0.0.tgz", + "integrity": "sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==" + }, + "avvio": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/avvio/-/avvio-7.2.1.tgz", + "integrity": "sha512-b+gox68dqD6c3S3t+bZBKN6rYbVWdwpN12sHQLFTiacDT2rcq7fm07Ww+IKt/AvAkyCIe1f5ArP1bC/vAlx97A==", + "requires": { + "archy": "^1.0.0", + "debug": "^4.0.0", + "fastq": "^1.6.1", + "queue-microtask": "^1.1.2" + }, + "dependencies": { + "debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "requires": { + "ms": "2.1.2" + } + } + } + }, "aws-sign2": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", @@ -6843,38 +6894,6 @@ "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.5.tgz", "integrity": "sha512-5am6HnnfN+urzt4yfg7IgTbotDjIT/u8AJpEt0sIU9FtXfVeezXAPKswrG+xKUCOYAINpSdgZVDU6QFh+cuH3w==" }, - "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=" - } - } - }, "bowser": { "version": "2.11.0", "resolved": "https://registry.npmjs.org/bowser/-/bowser-2.11.0.tgz", @@ -7075,11 +7094,6 @@ "node-gyp-build": "^4.2.0" } }, - "bytes": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", - "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==" - }, "cache-base": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", @@ -7585,11 +7599,6 @@ "safe-buffer": "5.1.2" } }, - "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==" - }, "convert-source-map": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.6.0.tgz", @@ -7604,11 +7613,6 @@ "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=" - }, "cookiejar": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.2.tgz", @@ -7880,8 +7884,7 @@ "deepmerge": { "version": "4.2.2", "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz", - "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==", - "dev": true + "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==" }, "deepmerge-plus": { "version": "2.1.3", @@ -9185,58 +9188,6 @@ } } }, - "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=" - } - } - }, "ext": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/ext/-/ext-1.4.0.tgz", @@ -9365,11 +9316,15 @@ "resolved": "https://registry.npmjs.org/fast-base64-decode/-/fast-base64-decode-1.0.0.tgz", "integrity": "sha512-qwaScUgUGBYeDNRnbc/KyllVU88Jk1pRHPStuF/lO7B0/RTRLj7U0lkdTAutlBblY08rwZDff6tNU9cjv6j//Q==" }, + "fast-decode-uri-component": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/fast-decode-uri-component/-/fast-decode-uri-component-1.0.1.tgz", + "integrity": "sha512-WKgKWg5eUxvRZGwW8FvfbaH7AXSh2cL+3j5fMGzUMCxWBJ3dV3a7Wz8y2f/uQ0e3B6WmodD3oS54jTQ9HVTIIg==" + }, "fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" }, "fast-glob": { "version": "3.2.5", @@ -9442,14 +9397,29 @@ "fast-json-stable-stringify": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", - "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=", - "dev": true + "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=" + }, + "fast-json-stringify": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/fast-json-stringify/-/fast-json-stringify-2.5.2.tgz", + "integrity": "sha512-H0/Wq7jj/i96DycCySdh+Jl0MubqaScM51GJkdJmjzwyiNpxAgQ9deYqk2H8SNOfwPj21RtTXMkMV5GosUWKeQ==", + "requires": { + "ajv": "^6.11.0", + "deepmerge": "^4.2.2", + "rfdc": "^1.2.0", + "string-similarity": "^4.0.1" + } }, "fast-levenshtein": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=" }, + "fast-redact": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/fast-redact/-/fast-redact-3.0.0.tgz", + "integrity": "sha512-a/S/Hp6aoIjx7EmugtzLqXmcNsyFszqbt6qQ99BdG61QjBZF6shNis0BYR6TsZOQ1twYc0FN2Xdhwwbv6+KD0w==" + }, "fast-safe-stringify": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.0.7.tgz", @@ -9460,6 +9430,80 @@ "resolved": "https://registry.npmjs.org/fast-text-encoding/-/fast-text-encoding-1.0.0.tgz", "integrity": "sha512-R9bHCvweUxxwkDwhjav5vxpFvdPGlVngtqmx4pIZfSUhM/Q4NiIUHB456BAf+Q1Nwu3HEZYONtu+Rya+af4jiQ==" }, + "fastify": { + "version": "3.14.0", + "resolved": "https://registry.npmjs.org/fastify/-/fastify-3.14.0.tgz", + "integrity": "sha512-a6W2iVPJMOaULqCykJ5nFRtnoknqt9K3b6rqAQcGjT/O2Hy+vvo+9/+cL2907KN0iF/91Ke+XQluKrVNF6+Z7w==", + "requires": { + "@fastify/proxy-addr": "^3.0.0", + "abstract-logging": "^2.0.0", + "ajv": "^6.12.2", + "avvio": "^7.1.2", + "fast-json-stringify": "^2.5.0", + "fastify-error": "^0.3.0", + "fastify-warning": "^0.2.0", + "find-my-way": "^4.0.0", + "flatstr": "^1.0.12", + "light-my-request": "^4.2.0", + "pino": "^6.2.1", + "readable-stream": "^3.4.0", + "rfdc": "^1.1.4", + "secure-json-parse": "^2.0.0", + "semver": "^7.3.2", + "tiny-lru": "^7.0.0" + }, + "dependencies": { + "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" + } + } + } + }, + "fastify-error": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/fastify-error/-/fastify-error-0.3.0.tgz", + "integrity": "sha512-Jm2LMTB5rsJqlS1+cmgqqM9tTs0UrlgYR7TvDT3ZgXsUI5ib1NjQlqZHf+tDK5tVPdFGwyq02wAoJtyYIRSiFA==" + }, + "fastify-plugin": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/fastify-plugin/-/fastify-plugin-3.0.0.tgz", + "integrity": "sha512-ZdCvKEEd92DNLps5n0v231Bha8bkz1DjnPP/aEz37rz/q42Z5JVLmgnqR4DYuNn3NXAO3IDCPyRvgvxtJ4Ym4w==" + }, + "fastify-static": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/fastify-static/-/fastify-static-4.0.1.tgz", + "integrity": "sha512-Mjt0My8Gf/nzJqIDai9rz3HsxH4RAJeMGMIPmf40lGMFKAv4SbRiKJ2cmteXoKHrFGPeGxwMq0gXfixwueV8wA==", + "requires": { + "content-disposition": "^0.5.3", + "fastify-plugin": "^3.0.0", + "glob": "^7.1.4", + "readable-stream": "^3.4.0", + "send": "^0.17.1" + }, + "dependencies": { + "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" + } + } + } + }, + "fastify-warning": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/fastify-warning/-/fastify-warning-0.2.0.tgz", + "integrity": "sha512-s1EQguBw/9qtc1p/WTY4eq9WMRIACkj+HTcOIK1in4MV5aFaQC9ZCIt0dJ7pr5bIf4lPpHvAtP2ywpTNgs7hqw==" + }, "fastq": { "version": "1.11.0", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.11.0.tgz", @@ -9514,35 +9558,6 @@ } } }, - "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-babel-config": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/find-babel-config/-/find-babel-config-1.2.0.tgz", @@ -9572,6 +9587,17 @@ "pkg-dir": "^3.0.0" } }, + "find-my-way": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/find-my-way/-/find-my-way-4.0.0.tgz", + "integrity": "sha512-IrICzn/Xm5r5A3RCB8rGLNe+dvzZl+SiUugTQOUMLJciP2qiSu2hw9JtVEYV3VruAYzSWjo/MLH9CFKtVdlWhQ==", + "requires": { + "fast-decode-uri-component": "^1.0.1", + "fast-deep-equal": "^3.1.3", + "safe-regex2": "^2.0.0", + "semver-store": "^0.3.0" + } + }, "find-up": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", @@ -9602,6 +9628,11 @@ } } }, + "flatstr": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/flatstr/-/flatstr-1.0.12.tgz", + "integrity": "sha512-4zPxDyhCyiN2wIAtSLI6gc82/EjqZc1onI4Mz/l0pWrAlsSfYH/2ZIcU+e3oA2wDwbzIWNKwa23F8rh6+DRWkw==" + }, "flatted": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.1.1.tgz", @@ -9644,11 +9675,6 @@ "resolved": "https://registry.npmjs.org/formidable/-/formidable-1.2.2.tgz", "integrity": "sha512-V8gLm+41I/8kguQ4/o1D3RIHRmhYFG4pnNyonvua+40rqcEmT4+V71yaZ3B457xbbgCsCfjSPi65u/W6vK1U5Q==" }, - "forwarded": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", - "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=" - }, "frac": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/frac/-/frac-1.1.2.tgz", @@ -11031,11 +11057,6 @@ "integrity": "sha1-+ni/XS5pE8kRzp+BnuUUa7bYROk=", "dev": true }, - "ipaddr.js": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", - "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==" - }, "is-accessor-descriptor": { "version": "0.1.6", "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", @@ -13361,8 +13382,7 @@ "json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" }, "json-stable-stringify-without-jsonify": { "version": "1.0.1", @@ -13541,6 +13561,30 @@ "type-check": "~0.3.2" } }, + "light-my-request": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/light-my-request/-/light-my-request-4.4.1.tgz", + "integrity": "sha512-FDNRF2mYjthIRWE7O8d/X7AzDx4otQHl4/QXbu3Q/FRwBFcgb+ZoDaUd5HwN53uQXLAiw76osN+Va0NEaOW6rQ==", + "requires": { + "ajv": "^6.12.2", + "cookie": "^0.4.0", + "fastify-warning": "^0.2.0", + "readable-stream": "^3.6.0", + "set-cookie-parser": "^2.4.1" + }, + "dependencies": { + "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" + } + } + } + }, "lines-and-columns": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.1.6.tgz", @@ -13744,11 +13788,6 @@ "object-visit": "^1.0.0" } }, - "media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" - }, "memory-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/memory-stream/-/memory-stream-1.0.0.tgz", @@ -13769,11 +13808,6 @@ } } }, - "merge-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" - }, "merge-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", @@ -14927,11 +14961,6 @@ "resolved": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.6.tgz", "integrity": "sha512-AUjen8sAkGgao7UyCX6Ahv0gIK2fABKmYjvP4xmy5JaKvcbTRueIqIPHLAfq30xJddqSE033IOMUSOMCcK3Sow==" }, - "parseurl": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" - }, "pascalcase": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", @@ -14968,11 +14997,6 @@ "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", "dev": true }, - "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=" - }, "path-type": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", @@ -14996,6 +15020,24 @@ "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", "dev": true }, + "pino": { + "version": "6.11.2", + "resolved": "https://registry.npmjs.org/pino/-/pino-6.11.2.tgz", + "integrity": "sha512-bmzxwbrIPxQUlAuMkF4PWVErUGERU4z37HazlhflKFg08crsNE3fACGN6gPwg5xtKOK47Ux5cZm8YCuLV4wWJg==", + "requires": { + "fast-redact": "^3.0.0", + "fast-safe-stringify": "^2.0.7", + "flatstr": "^1.0.12", + "pino-std-serializers": "^3.1.0", + "quick-format-unescaped": "4.0.1", + "sonic-boom": "^1.0.2" + } + }, + "pino-std-serializers": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-3.2.0.tgz", + "integrity": "sha512-EqX4pwDPrt3MuOAAUBMU0Tk5kR/YcCM5fNPEzgCO2zJ5HfX0vbiH9HbJglnyeQsN96Kznae6MWD47pZB5avTrg==" + }, "pirates": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.1.tgz", @@ -15205,15 +15247,6 @@ } } }, - "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" - } - }, "psl": { "version": "1.8.0", "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", @@ -15273,22 +15306,16 @@ "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.2.tgz", "integrity": "sha512-dB15eXv3p2jDlbOiNLyMabYg1/sXvppd8DP2J3EOCQ0AkuSXCW2tP7mnVouVLJKgUMY6yP0kcQDVpLCN13h4Xg==" }, + "quick-format-unescaped": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/quick-format-unescaped/-/quick-format-unescaped-4.0.1.tgz", + "integrity": "sha512-RyYpQ6Q5/drsJyOhrWHYMWTedvjTIat+FTwv0K4yoUxzvekw2aRHMQJLlnvt8UantkZg2++bEzD9EdxXqkWf4A==" + }, "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" - } - }, "rc": { "version": "1.2.8", "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", @@ -15752,6 +15779,11 @@ "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==" }, + "rfdc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", + "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==" + }, "rimraf": { "version": "2.6.3", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", @@ -15797,6 +15829,21 @@ "ret": "~0.1.10" } }, + "safe-regex2": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/safe-regex2/-/safe-regex2-2.0.0.tgz", + "integrity": "sha512-PaUSFsUaNNuKwkBijoAPHAK6/eM6VirvyPWlZ7BAQy4D+hCvh4B6lIG+nPdhbFfIbP+gTGBcrdsOaUs0F+ZBOQ==", + "requires": { + "ret": "~0.2.0" + }, + "dependencies": { + "ret": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.2.2.tgz", + "integrity": "sha512-M0b3YWQs7R3Z917WRQy1HHA7Ba7D8hvZg6UE5mLykJxQVE2ju0IXbGlaHPPlkY+WN7wFP+wUMXmBFA0aV6vYGQ==" + } + } + }, "safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", @@ -15869,6 +15916,11 @@ "xmlchars": "^2.2.0" } }, + "secure-json-parse": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/secure-json-parse/-/secure-json-parse-2.3.2.tgz", + "integrity": "sha512-4oUSFU0w2d8/XQb7NO9dbMYyp/hxIwZPcZcGAlAAEziMRHs+NbUcx2Z5dda/z8o+avyQ8gpuYnTMlGh8SVwg9g==" + }, "semver": { "version": "7.3.4", "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz", @@ -15909,6 +15961,11 @@ } } }, + "semver-store": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/semver-store/-/semver-store-0.3.0.tgz", + "integrity": "sha512-TcZvGMMy9vodEFSse30lWinkj+JgOBvPn8wRItpQRSayhc+4ssDs335uklkfvQQJgL/WvmHLVj4Ycv2s7QCQMg==" + }, "send": { "version": "0.17.1", "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", @@ -15956,22 +16013,16 @@ } } }, - "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" - } - }, "set-blocking": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" }, + "set-cookie-parser": { + "version": "2.4.8", + "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.4.8.tgz", + "integrity": "sha512-edRH8mBKEWNVIVMKejNnuJxleqYE/ZSdcT8/Nem9/mmosx12pctd80s2Oy00KNZzrogMZS5mauK2/ymL1bvlvg==" + }, "set-value": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", @@ -16333,6 +16384,15 @@ } } }, + "sonic-boom": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-1.4.0.tgz", + "integrity": "sha512-1xUAszhQBOrjk7uisbStQZYkZxD3vkYlCUw5qzOblWQ1ILN5v0dVPAs+QPgszzoPmbdWx6jyT9XiLJ95JdlLiQ==", + "requires": { + "atomic-sleep": "^1.0.0", + "flatstr": "^1.0.12" + } + }, "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -16540,6 +16600,11 @@ } } }, + "string-similarity": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/string-similarity/-/string-similarity-4.0.4.tgz", + "integrity": "sha512-/q/8Q4Bl4ZKAPjj8WerIBJWALKkaPRfrvhfF8k/B23i4nzrlRj2/go1m90In7nG/3XDSbOo0+pu6RvCTM9RGMQ==" + }, "string-width": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", @@ -16905,6 +16970,11 @@ "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", "dev": true }, + "tiny-lru": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/tiny-lru/-/tiny-lru-7.0.6.tgz", + "integrity": "sha512-zNYO0Kvgn5rXzWpL0y3RS09sMK67eGaQj9805jlK9G6pSadfriTczzLHFXa/xcW4mIRfmlB9HyQ/+SgL0V1uow==" + }, "tmp": { "version": "0.0.33", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", @@ -17131,15 +17201,6 @@ "integrity": "sha512-OdjXJxnCN1AvyLSzeKIgXTXxV+99ZuXl3Hpo9XpJAv9MBcHrrJOQ5kV7ypXOuQie+AmWG25hLbiKdwYTifzcfQ==", "dev": true }, - "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" - } - }, "typedarray-dts": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/typedarray-dts/-/typedarray-dts-1.0.0.tgz", @@ -17255,11 +17316,6 @@ "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==" }, - "unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" - }, "unset-value": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", @@ -17383,7 +17439,6 @@ "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, "requires": { "punycode": "^2.1.0" }, @@ -17391,8 +17446,7 @@ "punycode": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", - "dev": true + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" } } }, @@ -17435,11 +17489,6 @@ "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.3.2", "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", diff --git a/package.json b/package.json index 339acc1c..db9c6645 100644 --- a/package.json +++ b/package.json @@ -54,12 +54,12 @@ "@google-cloud/text-to-speech": "^3.1.3", "archiver": "^5.2.0", "async": "^3.2.0", - "body-parser": "^1.19.0", "cross-env": "^7.0.3", "deepspeech": "^0.9.3", "dotenv": "^8.2.0", "execa": "^5.0.0", - "express": "^4.17.1", + "fastify": "^3.14.0", + "fastify-static": "^4.0.1", "fluent-ffmpeg": "^2.1.2", "googleapis": "^67.1.1", "ibm-watson": "^6.0.3", diff --git a/server/src/api/downloads/download.controller.js b/server/src/api/downloads/download.controller.js deleted file mode 100644 index 3ab4260f..00000000 --- a/server/src/api/downloads/download.controller.js +++ /dev/null @@ -1,113 +0,0 @@ -import fs from 'fs' -import archiver from 'archiver' - -import log from '@/helpers/log' -import string from '@/helpers/string' - -const downloadController = { } - -downloadController.get = (req, res) => { - log.title('GET /downloads') - - const clean = (dir, files) => { - log.info('Cleaning module download directory...') - for (let i = 0; i < files.length; i += 1) { - fs.unlinkSync(`${dir}/${files[i]}`) - } - fs.rmdirSync(dir) - log.success('Downloads directory cleaned') - } - let message = '' - - if (req.query.package && req.query.module) { - const packageDir = `${__dirname}/../../../../packages/${req.query.package}` - const dlPackageDir = `${__dirname}/../../../../downloads/${req.query.package}` - const module = `${packageDir}/${req.query.module}.py` - - log.info(`Checking existence of the ${string.ucfirst(req.query.module)} module...`) - if (fs.existsSync(module)) { - log.success(`${string.ucfirst(req.query.module)} module exists`) - const downloadsDir = `${dlPackageDir}/${req.query.module}` - - log.info('Reading downloads directory...') - fs.readdir(downloadsDir, (err, files) => { - if (err && err.code === 'ENOENT') { - message = 'There is no content to download for this module.' - log.error(message) - res.json({ - success: false, status: 404, code: 'module_dir_not_found', message - }) - } else { - if (err) log.error(err) - - // Download the file if there is only one - if (files.length === 1) { - log.info(`${files[0]} is downloading...`) - res.download(`${downloadsDir}/${files[0]}`, (err) => { - if (err) log.error(err) - - log.success(`${files[0]} downloaded`) - - clean(downloadsDir, files) - }) - } else { - log.info('Deleting previous archives...') - const zipSlug = `leon-${req.query.package}-${req.query.module}` - const pkgFiles = fs.readdirSync(dlPackageDir) - - for (let i = 0; i < pkgFiles.length; i += 1) { - if (pkgFiles[i].indexOf('.zip') !== -1 && pkgFiles[i].indexOf(zipSlug) !== -1) { - fs.unlinkSync(`${dlPackageDir}/${pkgFiles[i]}`) - log.success(`${pkgFiles[i]} archive deleted`) - } - } - - log.info('Preparing new archive...') - const zipName = `${zipSlug}-${Date.now()}.zip` - const zipFile = `${dlPackageDir}/${zipName}` - const output = fs.createWriteStream(zipFile) - const archive = archiver('zip', { zlib: { level: 9 } }) - - // When the archive is ready - output.on('close', () => { - log.info(`${zipName} is downloading...`) - res.download(zipFile, (err) => { - if (err) log.error(err) - - log.success(`${zipName} downloaded`) - - clean(downloadsDir, files) - }) - }) - archive.on('error', (err) => { log.error(err) }) - - // Add the content to the archive - log.info('Adding content...') - archive.directory(downloadsDir, false) - - // Inject stream data to the archive - log.info('Injecting stream data...') - archive.pipe(output) - - log.info('Finalizing...') - archive.finalize() - } - } - }) - } else { - message = 'This module does not exist.' - log.error(message) - res.json({ - success: false, status: 404, code: 'module_not_found', message - }) - } - } else { - message = 'Bad request.' - log.error(message) - res.json({ - success: false, status: 400, code: 'bad_request', message - }) - } -} - -export default downloadController diff --git a/server/src/api/downloads/download.routes.js b/server/src/api/downloads/download.routes.js deleted file mode 100644 index b6de4519..00000000 --- a/server/src/api/downloads/download.routes.js +++ /dev/null @@ -1,10 +0,0 @@ -import { Router } from 'express' - -import downloadController from '@/api/downloads/download.controller' - -const downloadRouter = Router() - -// Get downloads to download module content -downloadRouter.get('/', downloadController.get) - -export default downloadRouter diff --git a/server/src/api/downloads/get.js b/server/src/api/downloads/get.js new file mode 100644 index 00000000..14bbf00f --- /dev/null +++ b/server/src/api/downloads/get.js @@ -0,0 +1,127 @@ +import fs from 'fs' +import archiver from 'archiver' + +import log from '@/helpers/log' +import string from '@/helpers/string' + +const getDownloads = async (fastify, options) => { + fastify.get(`/${options.apiVersion}/downloads`, (request, reply) => { + log.title('GET /downloads') + + const clean = (dir, files) => { + log.info('Cleaning module download directory...') + for (let i = 0; i < files.length; i += 1) { + fs.unlinkSync(`${dir}/${files[i]}`) + } + fs.rmdirSync(dir) + log.success('Downloads directory cleaned') + } + let message = '' + + if (request.query.package && request.query.module) { + const packageDir = `${__dirname}/../../../../packages/${request.query.package}` + const dlPackageDir = `${__dirname}/../../../../downloads/${request.query.package}` + const module = `${packageDir}/${request.query.module}.py` + + log.info( + `Checking existence of the ${string.ucfirst( + request.query.module + )} module...` + ) + if (fs.existsSync(module)) { + log.success(`${string.ucfirst(request.query.module)} module exists`) + const downloadsDir = `${dlPackageDir}/${request.query.module}` + + log.info('Reading downloads directory...') + fs.readdir(downloadsDir, (err, files) => { + if (err && err.code === 'ENOENT') { + message = 'There is no content to download for this module.' + log.error(message) + reply.send({ + success: false, + status: 404, + code: 'module_dir_not_found', + message + }) + } else { + if (err) log.error(err) + + // Download the file if there is only one + if (files.length === 1) { + log.info(`${files[0]} is downloading...`) + reply.download(`${downloadsDir}/${files[0]}`) + log.success(`${files[0]} downloaded`) + clean(downloadsDir, files) + } else { + log.info('Deleting previous archives...') + const zipSlug = `leon-${request.query.package}-${request.query.module}` + const pkgFiles = fs.readdirSync(dlPackageDir) + + for (let i = 0; i < pkgFiles.length; i += 1) { + if ( + pkgFiles[i].indexOf('.zip') !== -1 + && pkgFiles[i].indexOf(zipSlug) !== -1 + ) { + fs.unlinkSync(`${dlPackageDir}/${pkgFiles[i]}`) + log.success(`${pkgFiles[i]} archive deleted`) + } + } + + log.info('Preparing new archive...') + const zipName = `${zipSlug}-${Date.now()}.zip` + const zipFile = `${dlPackageDir}/${zipName}` + const output = fs.createWriteStream(zipFile) + const archive = archiver('zip', { zlib: { level: 9 } }) + + // When the archive is ready + output.on('close', () => { + log.info(`${zipName} is downloading...`) + reply.download(zipFile, (err) => { + if (err) log.error(err) + + log.success(`${zipName} downloaded`) + + clean(downloadsDir, files) + }) + }) + archive.on('error', (err) => { + log.error(err) + }) + + // Add the content to the archive + log.info('Adding content...') + archive.directory(downloadsDir, false) + + // Inject stream data to the archive + log.info('Injecting stream data...') + archive.pipe(output) + + log.info('Finalizing...') + archive.finalize() + } + } + }) + } else { + message = 'This module does not exist.' + log.error(message) + reply.send({ + success: false, + status: 404, + code: 'module_not_found', + message + }) + } + } else { + message = 'Bad request.' + log.error(message) + reply.send({ + success: false, + status: 400, + code: 'bad_request', + message + }) + } + }) +} + +export default getDownloads diff --git a/server/src/api/downloads/index.js b/server/src/api/downloads/index.js new file mode 100644 index 00000000..05eebb47 --- /dev/null +++ b/server/src/api/downloads/index.js @@ -0,0 +1,8 @@ +import getDownloads from '@/api/downloads/get' + +const downloadsPlugin = async (fastify, options) => { + // Get downloads to download module content + fastify.register(getDownloads, options) +} + +export default downloadsPlugin diff --git a/server/src/api/info/get.js b/server/src/api/info/get.js new file mode 100644 index 00000000..a3b4d6e2 --- /dev/null +++ b/server/src/api/info/get.js @@ -0,0 +1,34 @@ +import { langs } from '@@/core/langs.json' +import { version } from '@@/package.json' +import log from '@/helpers/log' + +const getInfo = async (fastify, options) => { + fastify.get(`/${options.apiVersion}/info`, (_request, reply) => { + log.title('GET /info') + + const message = 'Information pulled.' + + log.success(message) + + reply.send({ + success: true, + status: 200, + code: 'info_pulled', + message, + after_speech: process.env.LEON_AFTER_SPEECH === 'true', + logger: process.env.LEON_LOGGER === 'true', + stt: { + enabled: process.env.LEON_STT === 'true', + provider: process.env.LEON_STT_PROVIDER + }, + tts: { + enabled: process.env.LEON_TTS === 'true', + provider: process.env.LEON_TTS_PROVIDER + }, + lang: langs[process.env.LEON_LANG], + version + }) + }) +} + +export default getInfo diff --git a/server/src/api/info/index.js b/server/src/api/info/index.js new file mode 100644 index 00000000..3e579e98 --- /dev/null +++ b/server/src/api/info/index.js @@ -0,0 +1,8 @@ +import getInfo from '@/api/info/get' + +const infoPlugin = async (fastify, options) => { + // Get information to init client + fastify.register(getInfo, options) +} + +export default infoPlugin diff --git a/server/src/api/info/info.controller.js b/server/src/api/info/info.controller.js deleted file mode 100644 index 58815e7a..00000000 --- a/server/src/api/info/info.controller.js +++ /dev/null @@ -1,34 +0,0 @@ -import { langs } from '@@/core/langs.json' -import { version } from '@@/package.json' -import log from '@/helpers/log' - -const infoController = { } - -infoController.get = (req, res) => { - log.title('GET /info') - - const message = 'Information pulled.' - - log.success(message) - - res.json({ - success: true, - status: 200, - code: 'info_pulled', - message, - after_speech: process.env.LEON_AFTER_SPEECH === 'true', - logger: process.env.LEON_LOGGER === 'true', - stt: { - enabled: process.env.LEON_STT === 'true', - provider: process.env.LEON_STT_PROVIDER - }, - tts: { - enabled: process.env.LEON_TTS === 'true', - provider: process.env.LEON_TTS_PROVIDER - }, - lang: langs[process.env.LEON_LANG], - version - }) -} - -export default infoController diff --git a/server/src/api/info/info.routes.js b/server/src/api/info/info.routes.js deleted file mode 100644 index 5c63b5e7..00000000 --- a/server/src/api/info/info.routes.js +++ /dev/null @@ -1,10 +0,0 @@ -import { Router } from 'express' - -import infoController from '@/api/info/info.controller' - -const infoRouter = Router() - -// Get information to init client -infoRouter.get('/', infoController.get) - -export default infoRouter diff --git a/server/src/core/server.js b/server/src/core/server.js index a5d2ac83..607e9a70 100644 --- a/server/src/core/server.js +++ b/server/src/core/server.js @@ -1,6 +1,5 @@ -import express from 'express' -import http from 'http' -import bodyParser from 'body-parser' +import Fastify from 'fastify' +import fastifyStatic from 'fastify-static' import socketio from 'socket.io' import path from 'path' @@ -10,14 +9,14 @@ import Nlu from '@/core/nlu' import Brain from '@/core/brain' import Asr from '@/core/asr' import Stt from '@/stt/stt' -import corsMidd from '@/middleware/cors' -import otherMidd from '@/middleware/other' -import infoRouter from '@/api/info/info.routes' -import downloadRouter from '@/api/downloads/download.routes' +import corsMidd from '@/plugins/cors' +import otherMidd from '@/plugins/other' +import infoPlugin from '@/api/info/index' +import downloadsPlugin from '@/api/downloads/index' import log from '@/helpers/log' import date from '@/helpers/date' -const app = express() +const fastify = Fastify() let stt = { } class Server { @@ -28,162 +27,133 @@ class Server { /** * Server entry point */ - static init () { - return new Promise(async (resolve) => { - // CORS middleware - app.use(corsMidd) + static async init () { + fastify.addHook('onRequest', corsMidd) + fastify.addHook('onRequest', otherMidd) - // A simple middleware - app.use(otherMidd) + log.title('Initialization') + log.success(`The current env is ${process.env.LEON_NODE_ENV}`) + log.success(`The current version is ${version}`) - app.use(bodyParser.json()) - app.use(bodyParser.urlencoded({ - extended: true - })) + if (!Object.keys(langs).includes(process.env.LEON_LANG) === true) { + process.env.LEON_LANG = 'en-US' + log.warning('The language you chose is not supported, then the default language has been applied') + } - log.title('Initialization') - log.success(`The current env is ${process.env.LEON_NODE_ENV}`) - log.success(`The current version is ${version}`) + log.success(`The current language is ${process.env.LEON_LANG}`) + log.success(`The current time zone is ${date.timeZone()}`) - if (!Object.keys(langs).includes(process.env.LEON_LANG) === true) { - process.env.LEON_LANG = 'en-US' + const sLogger = (process.env.LEON_LOGGER !== 'true') ? 'disabled' : 'enabled' + log.success(`Collaborative logger ${sLogger}`) - log.warning('The language you chose is not supported, then the default language has been applied') - } - - log.success(`The current language is ${process.env.LEON_LANG}`) - log.success(`The current time zone is ${date.timeZone()}`) - - const sLogger = (process.env.LEON_LOGGER !== 'true') ? 'disabled' : 'enabled' - log.success(`Collaborative logger ${sLogger}`) - - await this.bootstrap() - resolve() - }) + await Server.bootstrap() } /** * Bootstrap API */ - static bootstrap () { - return new Promise(async (resolve) => { - const apiVersion = 'v1' + static async bootstrap () { + const apiVersion = 'v1' - // Render the web app - app.use(express.static(`${__dirname}/../../../app/dist`)) - app.get('/', (req, res) => { - res.sendFile(path.resolve(`${__dirname}/../../../app/dist/index.html`)) - }) - - app.use(`/${apiVersion}/info`, infoRouter) - app.use(`/${apiVersion}/downloads`, downloadRouter) - - try { - this.server = http.createServer(app) - - await this.listen(process.env.LEON_PORT) - resolve() - } catch (e) { - log[e.type](e.obj.message) - } + // Render the web app + fastify.register(fastifyStatic, { + root: path.join(__dirname, '..', '..', '..', 'app', 'dist'), + prefix: '/' }) + fastify.get('/', (_request, reply) => { + reply.sendFile('index.html') + }) + + fastify.register(infoPlugin, { apiVersion }) + fastify.register(downloadsPlugin, { apiVersion }) + this.server = fastify.server + try { + await Server.listen(process.env.LEON_PORT) + } catch (e) { + log.error(e.message) + } } /** * Launch server */ - static listen (port) { - return new Promise((resolve, reject) => { - const io = process.env.LEON_NODE_ENV === 'development' - ? socketio(this.server, { cors: { origin: `${process.env.LEON_HOST}:3000` } }) - : socketio(this.server) + static async listen (port) { + const io = process.env.LEON_NODE_ENV === 'development' + ? socketio(this.server, { cors: { origin: `${process.env.LEON_HOST}:3000` } }) + : socketio(this.server) - io.on('connection', this.connection) + io.on('connection', Server.connection) - this.server.listen(port, (err) => { - /* istanbul ignore if */ - if (err) { - reject({ type: 'error', obj: err }) - return - } - - log.success(`Server is available at ${process.env.LEON_HOST}:${port}`) - - resolve() - }) - }) + await fastify.listen(port, '0.0.0.0') + log.success(`Server is available at ${process.env.LEON_HOST}:${port}`) } /** * Bootstrap socket */ - static connection (socket) { - return new Promise((resolve) => { - log.title('Client') - log.success('Connected') + static async connection (socket) { + log.title('Client') + log.success('Connected') - // Init - socket.on('init', async (data) => { - log.info(`Type: ${data}`) - log.info(`Socket id: ${socket.id}`) + // Init + socket.on('init', async (data) => { + log.info(`Type: ${data}`) + log.info(`Socket id: ${socket.id}`) - if (data === 'hotword-node') { - // Hotword triggered - socket.on('hotword-detected', (data) => { - log.title('Socket') - log.success(`Hotword ${data.hotword} detected`) + if (data === 'hotword-node') { + // Hotword triggered + socket.on('hotword-detected', (data) => { + log.title('Socket') + log.success(`Hotword ${data.hotword} detected`) - socket.broadcast.emit('enable-record') - }) - } else { - const brain = new Brain(socket, langs[process.env.LEON_LANG].short) - const nlu = new Nlu(brain) - const asr = new Asr() - let sttState = 'disabled' - let ttsState = 'disabled' + socket.broadcast.emit('enable-record') + }) + } else { + const brain = new Brain(socket, langs[process.env.LEON_LANG].short) + const nlu = new Nlu(brain) + const asr = new Asr() + let sttState = 'disabled' + let ttsState = 'disabled' - if (process.env.LEON_STT === 'true') { - sttState = 'enabled' + if (process.env.LEON_STT === 'true') { + sttState = 'enabled' - stt = new Stt(socket, process.env.LEON_STT_PROVIDER) - stt.init() - } - if (process.env.LEON_TTS === 'true') { - ttsState = 'enabled' - } + stt = new Stt(socket, process.env.LEON_STT_PROVIDER) + stt.init() + } + if (process.env.LEON_TTS === 'true') { + ttsState = 'enabled' + } - log.title('Initialization') - log.success(`STT ${sttState}`) - log.success(`TTS ${ttsState}`) + log.title('Initialization') + log.success(`STT ${sttState}`) + log.success(`TTS ${ttsState}`) - // Train modules expressions + // Train modules expressions + try { + await nlu.loadModel(`${__dirname}/../data/expressions/classifier.json`) + } catch (e) { + log[e.type](e.obj.message) + } + + // Listen for new query + socket.on('query', async (data) => { + log.title('Socket') + log.info(`${data.client} emitted: ${data.value}`) + + socket.emit('is-typing', true) + await nlu.process(data.value) + }) + + // Handle automatic speech recognition + socket.on('recognize', async (data) => { try { - await nlu.loadModel(`${__dirname}/../data/expressions/classifier.json`) + await asr.run(data, stt) } catch (e) { log[e.type](e.obj.message) } - - // Listen for new query - socket.on('query', async (data) => { - log.title('Socket') - log.info(`${data.client} emitted: ${data.value}`) - - socket.emit('is-typing', true) - await nlu.process(data.value) - }) - - // Handle automatic speech recognition - socket.on('recognize', async (data) => { - try { - await asr.run(data, stt) - } catch (e) { - log[e.type](e.obj.message) - } - }) - } - - resolve() - }) + }) + } }) } } diff --git a/server/src/middleware/cors.js b/server/src/middleware/cors.js deleted file mode 100644 index 1486cf9f..00000000 --- a/server/src/middleware/cors.js +++ /dev/null @@ -1,18 +0,0 @@ -/** - * CORS middleware - */ -const corsMidd = (req, res, next) => { - // Allow only a specific client to request to the API (depending of the env) - if (process.env.LEON_NODE_ENV !== 'production') { - res.header('Access-Control-Allow-Origin', `${process.env.LEON_HOST}:3000`) - } - - // Allow several headers for our requests - res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept') - - res.header('Access-Control-Allow-Credentials', true) - - next() -} - -export default corsMidd diff --git a/server/src/plugins/cors.js b/server/src/plugins/cors.js new file mode 100644 index 00000000..00976893 --- /dev/null +++ b/server/src/plugins/cors.js @@ -0,0 +1,19 @@ +const corsMidd = async (_request, reply) => { + // Allow only a specific client to request to the API (depending of the env) + if (process.env.LEON_NODE_ENV !== 'production') { + reply.header( + 'Access-Control-Allow-Origin', + `${process.env.LEON_HOST}:3000` + ) + } + + // Allow several headers for our requests + reply.header( + 'Access-Control-Allow-Headers', + 'Origin, X-Requested-With, Content-Type, Accept' + ) + + reply.header('Access-Control-Allow-Credentials', true) +} + +export default corsMidd diff --git a/server/src/middleware/other.js b/server/src/plugins/other.js similarity index 50% rename from server/src/middleware/other.js rename to server/src/plugins/other.js index 08708d37..435d2ae9 100644 --- a/server/src/middleware/other.js +++ b/server/src/plugins/other.js @@ -1,17 +1,10 @@ import log from '@/helpers/log' -/** - * Just a middleware - */ -const otherMidd = (req, res, next) => { +const otherMidd = async (request, reply) => { // Disable from the header, else it makes hacker's life easier to know more about our system - res.removeHeader('X-Powered-By') - + reply.removeHeader('X-Powered-By') log.title('Requesting') - log.info(`${req.method} ${req.url}`) - - // Add next() to continue - next() + log.info(`${request.method} ${request.url}`) } export default otherMidd diff --git a/test/unit/unit.jest.json b/test/unit/unit.jest.json index 84e1f270..d0b34e8b 100644 --- a/test/unit/unit.jest.json +++ b/test/unit/unit.jest.json @@ -18,7 +18,7 @@ "collectCoverageFrom": [ "/server/src/**/*.js", "!/server/src/api/**/*.js", - "!/server/src/middleware/**/*.js", + "!/server/src/plugins/**/*.js", "!/server/src/stt/google-cloud-stt/**/*.js", "!/server/src/stt/watson-stt/**/*.js", "!/server/src/tts/amazon-polly/**/*.js",