From 8562b8d1b3d2278a436b0546f21807de87597465 Mon Sep 17 00:00:00 2001 From: advplyr Date: Wed, 6 Jul 2022 17:07:08 -0500 Subject: [PATCH 001/100] Remove node-ffprobe dependency --- package-lock.json | 5 ----- package.json | 1 - server/libs/nodeFfprobe/LICENSE | 22 ++++++++++++++++++++++ server/libs/nodeFfprobe/index.js | 28 ++++++++++++++++++++++++++++ server/utils/prober.js | 2 +- 5 files changed, 51 insertions(+), 7 deletions(-) create mode 100644 server/libs/nodeFfprobe/LICENSE create mode 100644 server/libs/nodeFfprobe/index.js diff --git a/package-lock.json b/package-lock.json index 601ed23ba..32c53652d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -846,11 +846,6 @@ "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==" }, - "node-ffprobe": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/node-ffprobe/-/node-ffprobe-3.0.0.tgz", - "integrity": "sha512-2LNTLStz2hw/urwo4xJ00TIOvthgepcl3tF4HB8BWnhJ4nhJ7S08YThapBHkGLYV+GUuY9pML/kX76+dqY2iUg==" - }, "normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", diff --git a/package.json b/package.json index 7a0f89244..9fd3c0c28 100644 --- a/package.json +++ b/package.json @@ -41,7 +41,6 @@ "fluent-ffmpeg": "^2.1.2", "htmlparser2": "^8.0.1", "jsonwebtoken": "^8.5.1", - "node-ffprobe": "^3.0.0", "socket.io": "^4.4.1", "xml2js": "^0.4.23" } diff --git a/server/libs/nodeFfprobe/LICENSE b/server/libs/nodeFfprobe/LICENSE new file mode 100644 index 000000000..3d2680a84 --- /dev/null +++ b/server/libs/nodeFfprobe/LICENSE @@ -0,0 +1,22 @@ +(The MIT License) + +Copyright (c) 2011 Listener Approved LLC. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/server/libs/nodeFfprobe/index.js b/server/libs/nodeFfprobe/index.js new file mode 100644 index 000000000..a6d78233f --- /dev/null +++ b/server/libs/nodeFfprobe/index.js @@ -0,0 +1,28 @@ +// +// node-ffprobe modified for audiobookshelf +// SOURCE: https://github.com/ListenerApproved/node-ffprobe +// + +const spawn = require('child_process').spawn + +module.exports = (function () { + function doProbe(file) { + return new Promise((resolve, reject) => { + let proc = spawn(module.exports.FFPROBE_PATH || 'ffprobe', ['-hide_banner', '-loglevel', 'fatal', '-show_error', '-show_format', '-show_streams', '-show_programs', '-show_chapters', '-show_private_data', '-print_format', 'json', file]) + let probeData = [] + let errData = [] + + proc.stdout.setEncoding('utf8') + proc.stderr.setEncoding('utf8') + + proc.stdout.on('data', function (data) { probeData.push(data) }) + proc.stderr.on('data', function (data) { errData.push(data) }) + + proc.on('exit', code => { exitCode = code }) + proc.on('error', err => reject(err)) + proc.on('close', () => resolve(JSON.parse(probeData.join('')))) + }) + } + + return doProbe +})() \ No newline at end of file diff --git a/server/utils/prober.js b/server/utils/prober.js index 890899b85..ec047fbfb 100644 --- a/server/utils/prober.js +++ b/server/utils/prober.js @@ -1,4 +1,4 @@ -const ffprobe = require('node-ffprobe') +const ffprobe = require('../libs/nodeFfprobe') const MediaProbeData = require('../scanner/MediaProbeData') const Logger = require('../Logger') From b61ecefce41c81dfdba9f385f3babaca7c522fbb Mon Sep 17 00:00:00 2001 From: advplyr Date: Wed, 6 Jul 2022 17:38:19 -0500 Subject: [PATCH 002/100] Remove fluent-ffmpeg dependency --- package-lock.json | 22 - package.json | 1 - server/libs/async/LICENSE | 19 + server/libs/async/index.js | 6 + server/libs/fluentFfmpeg/LICENSE | 9 + server/libs/fluentFfmpeg/capabilities.js | 665 ++++++++++++++++++ server/libs/fluentFfmpeg/ffprobe.js | 261 +++++++ server/libs/fluentFfmpeg/index.js | 231 ++++++ server/libs/fluentFfmpeg/options/audio.js | 178 +++++ server/libs/fluentFfmpeg/options/custom.js | 212 ++++++ server/libs/fluentFfmpeg/options/inputs.js | 178 +++++ server/libs/fluentFfmpeg/options/misc.js | 41 ++ server/libs/fluentFfmpeg/options/output.js | 162 +++++ server/libs/fluentFfmpeg/options/video.js | 184 +++++ server/libs/fluentFfmpeg/options/videosize.js | 291 ++++++++ server/libs/fluentFfmpeg/presets/divx.js | 14 + .../libs/fluentFfmpeg/presets/flashvideo.js | 16 + server/libs/fluentFfmpeg/presets/podcast.js | 16 + server/libs/fluentFfmpeg/processor.js | 660 +++++++++++++++++ server/libs/fluentFfmpeg/recipes.js | 456 ++++++++++++ server/libs/fluentFfmpeg/utils.js | 454 ++++++++++++ server/libs/isexe/LICENSE | 15 + server/libs/isexe/index.js | 61 ++ server/libs/isexe/mode.js | 41 ++ server/libs/isexe/windows.js | 42 ++ server/libs/properLockfile/index.js | 6 + server/libs/retry/index.js | 31 +- server/libs/rss/index.js | 2 +- server/libs/signalExit/index.js | 25 +- server/libs/universalify/index.js | 5 + server/libs/which/LICENSE | 15 + server/libs/which/index.js | 130 ++++ server/objects/Stream.js | 2 +- server/utils/downloadWorker.js | 2 +- server/utils/ffmpegHelpers.js | 2 +- 35 files changed, 4405 insertions(+), 50 deletions(-) create mode 100644 server/libs/async/LICENSE create mode 100644 server/libs/async/index.js create mode 100644 server/libs/fluentFfmpeg/LICENSE create mode 100644 server/libs/fluentFfmpeg/capabilities.js create mode 100644 server/libs/fluentFfmpeg/ffprobe.js create mode 100644 server/libs/fluentFfmpeg/index.js create mode 100644 server/libs/fluentFfmpeg/options/audio.js create mode 100644 server/libs/fluentFfmpeg/options/custom.js create mode 100644 server/libs/fluentFfmpeg/options/inputs.js create mode 100644 server/libs/fluentFfmpeg/options/misc.js create mode 100644 server/libs/fluentFfmpeg/options/output.js create mode 100644 server/libs/fluentFfmpeg/options/video.js create mode 100644 server/libs/fluentFfmpeg/options/videosize.js create mode 100644 server/libs/fluentFfmpeg/presets/divx.js create mode 100644 server/libs/fluentFfmpeg/presets/flashvideo.js create mode 100644 server/libs/fluentFfmpeg/presets/podcast.js create mode 100644 server/libs/fluentFfmpeg/processor.js create mode 100644 server/libs/fluentFfmpeg/recipes.js create mode 100644 server/libs/fluentFfmpeg/utils.js create mode 100644 server/libs/isexe/LICENSE create mode 100644 server/libs/isexe/index.js create mode 100644 server/libs/isexe/mode.js create mode 100644 server/libs/isexe/windows.js create mode 100644 server/libs/which/LICENSE create mode 100644 server/libs/which/index.js diff --git a/package-lock.json b/package-lock.json index 32c53652d..bcd222472 100644 --- a/package-lock.json +++ b/package-lock.json @@ -510,15 +510,6 @@ "array-back": "^3.0.1" } }, - "fluent-ffmpeg": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/fluent-ffmpeg/-/fluent-ffmpeg-2.1.2.tgz", - "integrity": "sha512-IZTB4kq5GK0DPp7sGQ0q/BWurGHffRtQQwVkiqDgeO6wYJLLV5ZhgNOQ65loZxxuPMKZKZcICCUnaGtlxBiR0Q==", - "requires": { - "async": ">=0.2.9", - "which": "^1.1.1" - } - }, "follow-redirects": { "version": "1.15.1", "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.1.tgz", @@ -650,11 +641,6 @@ "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" }, - "isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" - }, "jsonwebtoken": { "version": "8.5.1", "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz", @@ -1148,14 +1134,6 @@ "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" }, - "which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "requires": { - "isexe": "^2.0.0" - } - }, "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", diff --git a/package.json b/package.json index 9fd3c0c28..2cf504c6b 100644 --- a/package.json +++ b/package.json @@ -38,7 +38,6 @@ "express": "^4.17.1", "express-fileupload": "^1.2.1", "express-rate-limit": "^5.3.0", - "fluent-ffmpeg": "^2.1.2", "htmlparser2": "^8.0.1", "jsonwebtoken": "^8.5.1", "socket.io": "^4.4.1", diff --git a/server/libs/async/LICENSE b/server/libs/async/LICENSE new file mode 100644 index 000000000..5c8b6cf17 --- /dev/null +++ b/server/libs/async/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2010-2018 Caolan McMahon + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. \ No newline at end of file diff --git a/server/libs/async/index.js b/server/libs/async/index.js new file mode 100644 index 000000000..56d6cd34f --- /dev/null +++ b/server/libs/async/index.js @@ -0,0 +1,6 @@ +// +// Used by fluentFfmpeg +// Source: https://github.com/caolan/async +// + +(function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t(e.async={})})(this,function(e){'use strict';function t(e,...t){return(...n)=>e(...t,...n)}function n(e){return function(...t){var n=t.pop();return e.call(this,t,n)}}function a(e){setTimeout(e,0)}function i(e){return(t,...n)=>e(()=>t(...n))}function r(e){return u(e)?function(...t){const n=t.pop(),a=e.apply(this,t);return s(a,n)}:n(function(t,n){var a;try{a=e.apply(this,t)}catch(t){return n(t)}return a&&"function"==typeof a.then?s(a,n):void n(null,a)})}function s(e,t){return e.then(e=>{l(t,null,e)},e=>{l(t,e&&e.message?e:new Error(e))})}function l(e,t,n){try{e(t,n)}catch(e){_e(t=>{throw t},e)}}function u(e){return"AsyncFunction"===e[Symbol.toStringTag]}function d(e){return"AsyncGenerator"===e[Symbol.toStringTag]}function p(e){return"function"==typeof e[Symbol.asyncIterator]}function c(e){if("function"!=typeof e)throw new Error("expected a function");return u(e)?r(e):e}function o(e,t=e.length){if(!t)throw new Error("arity is undefined");return function(...n){return"function"==typeof n[t-1]?e.apply(this,n):new Promise((a,i)=>{n[t-1]=(e,...t)=>e?i(e):void a(1{c(e).apply(i,n.concat(t))},a)});return a}}function f(e,t,n,a){t=t||[];var i=[],r=0,s=c(n);return e(t,(e,t,n)=>{var a=r++;s(e,(e,t)=>{i[a]=t,n(e)})},e=>{a(e,i)})}function y(e){return e&&"number"==typeof e.length&&0<=e.length&&0==e.length%1}function m(e){function t(...t){if(null!==e){var n=e;e=null,n.apply(this,t)}}return Object.assign(t,e),t}function g(e){return e[Symbol.iterator]&&e[Symbol.iterator]()}function k(e){var t=-1,n=e.length;return function(){return++t=t||d||l||(d=!0,e.next().then(({value:e,done:t})=>{if(!(u||l))return d=!1,t?(l=!0,void(0>=p&&a(null))):void(p++,n(e,c,r),c++,i())}).catch(s))}function r(e,t){return p-=1,u?void 0:e?s(e):!1===e?(l=!0,void(u=!0)):t===be||l&&0>=p?(l=!0,a(null)):void i()}function s(e){u||(d=!1,l=!0,a(e))}let l=!1,u=!1,d=!1,p=0,c=0;i()}function O(e,t,n){function a(e,t){!1===e&&(l=!0);!0===l||(e?n(e):(++r===s||t===be)&&n(null))}n=m(n);var i=0,r=0,{length:s}=e,l=!1;for(0===s&&n(null);i{t=e,n=a}),e}function A(e,t,n){function a(e,t){g.push(()=>l(e,t))}function i(){if(!h){if(0===g.length&&0===o)return n(null,p);for(;g.length&&oe()),i()}function l(e,t){if(!f){var a=L((t,...a)=>{if(o--,!1===t)return void(h=!0);if(2>a.length&&([a]=a),t){var i={};if(Object.keys(p).forEach(e=>{i[e]=p[e]}),i[e]=a,f=!0,y=Object.create(null),h)return;n(t,i)}else p[e]=a,s(e)});o++;var i=c(t[t.length-1]);1{const i=e[a];Array.isArray(i)&&0<=i.indexOf(t)&&n.push(a)}),n}"number"!=typeof t&&(n=t,t=null),n=m(n||b());var d=Object.keys(e).length;if(!d)return n(null);t||(t=d);var p={},o=0,h=!1,f=!1,y=Object.create(null),g=[],k=[],v={};return Object.keys(e).forEach(t=>{var n=e[t];if(!Array.isArray(n))return a(t,[n]),void k.push(t);var i=n.slice(0,n.length-1),s=i.length;return 0===s?(a(t,n),void k.push(t)):void(v[t]=s,i.forEach(l=>{if(!e[l])throw new Error("async.auto task `"+t+"` has a non-existent dependency `"+l+"` in "+i.join(", "));r(l,()=>{s--,0===s&&a(t,n)})}))}),function(){for(var e,t=0;k.length;)e=k.pop(),t++,u(e).forEach(e=>{0==--v[e]&&k.push(e)});if(t!==d)throw new Error("async.auto cannot execute tasks due to a recursive dependency")}(),i(),n[Ce]}function I(e){let t="",n=0,a=e.indexOf("*/");for(;ne.replace(Ne,"").trim())}function j(e,t){var n={};return Object.keys(e).forEach(t=>{function a(e,t){var n=i.map(t=>e[t]);n.push(t),c(r)(...n)}var i,r=e[t],s=u(r),l=!s&&1===r.length||s&&0===r.length;if(Array.isArray(r))i=[...r],r=i.pop(),n[t]=i.concat(0{r(e,n),t(...a)};f[e].push(n)}function r(e,t){return e?t?void(f[e]=f[e].filter(e=>e!==t)):f[e]=[]:Object.keys(f).forEach(e=>f[e]=[])}function s(e,...t){f[e].forEach(e=>e(...t))}function l(e,t,n,a){function i(e,...t){return e?n?s(e):r():1>=t.length?r(t[0]):void r(t)}if(null!=a&&"function"!=typeof a)throw new Error("task callback must be a function");k.started=!0;var r,s,l=k._createTaskItem(e,n?i:a||i);if(t?k._tasks.unshift(l):k._tasks.push(l),y||(y=!0,_e(()=>{y=!1,k.process()})),n||!a)return new Promise((e,t)=>{r=e,s=t})}function u(e){return function(t,...n){o-=1;for(var a=0,r=e.length;as("drain")),!0)}if(null==t)t=1;else if(0===t)throw new RangeError("Concurrency must not be zero");var p=c(e),o=0,h=[];const f={error:[],drain:[],saturated:[],unsaturated:[],empty:[]};var y=!1;const m=e=>t=>t?void(r(e),a(e,t)):new Promise((t,n)=>{i(e,(e,a)=>e?n(e):void t(a))});var g=!1,k={_tasks:new Ve,_createTaskItem(e,t){return{data:e,callback:t}},*[Symbol.iterator](){yield*k._tasks[Symbol.iterator]()},concurrency:t,payload:n,buffer:t/4,started:!1,paused:!1,push(e,t){return Array.isArray(e)?d(e)?void 0:e.map(e=>l(e,!1,!1,t)):l(e,!1,!1,t)},pushAsync(e,t){return Array.isArray(e)?d(e)?void 0:e.map(e=>l(e,!1,!0,t)):l(e,!1,!0,t)},kill(){r(),k._tasks.empty()},unshift(e,t){return Array.isArray(e)?d(e)?void 0:e.map(e=>l(e,!0,!1,t)):l(e,!0,!1,t)},unshiftAsync(e,t){return Array.isArray(e)?d(e)?void 0:e.map(e=>l(e,!0,!0,t)):l(e,!0,!0,t)},remove(e){k._tasks.remove(e)},process(){var e=Math.min;if(!g){for(g=!0;!k.paused&&o{t.apply(n,e.concat((e,...t)=>{a(e,t)}))},(e,t)=>a(e,...t)),a[Ce]}}function P(...e){return C(...e.reverse())}function R(...e){return function(...t){var n=t.pop();return n(null,...e)}}function z(e,t){return(n,a,i,r)=>{var s,l=!1;const u=c(i);n(a,(n,a,i)=>{u(n,(a,r)=>a||!1===a?i(a):e(r)&&!s?(l=!0,s=t(!0,n),i(null,be)):void i())},e=>e?r(e):void r(null,l?s:t(!1)))}}function N(e){return(t,...n)=>c(t)(...n,(t,...n)=>{"object"==typeof console&&(t?console.error&&console.error(t):console[e]&&n.forEach(t=>console[e](t)))})}function V(e,t,n){const a=c(t);return Xe(e,(...e)=>{const t=e.pop();a(...e,(e,n)=>t(e,!n))},n)}function Y(e){return(t,n,a)=>e(t,a)}function q(e){return u(e)?e:function(...t){var n=t.pop(),a=!0;t.push((...e)=>{a?_e(()=>n(...e)):n(...e)}),e.apply(this,t),a=!1}}function D(e,t,n,a){var r=Array(t.length);e(t,(e,t,a)=>{n(e,(e,n)=>{r[t]=!!n,a(e)})},e=>{if(e)return a(e);for(var n=[],s=0;s{n(e,(n,r)=>n?a(n):void(r&&i.push({index:t,value:e}),a(n)))},e=>e?a(e):void a(null,i.sort((e,t)=>e.index-t.index).map(e=>e.value)))}function U(e,t,n,a){var i=y(t)?D:Q;return i(e,t,c(n),a)}function G(e,t,n){return ut(e,1/0,t,n)}function W(e,t,n){return ut(e,1,t,n)}function H(e,t,n){return pt(e,1/0,t,n)}function J(e,t,n){return pt(e,1,t,n)}function K(e,t=e=>e){var a=Object.create(null),r=Object.create(null),s=c(e),l=n((e,n)=>{var u=t(...e);u in a?_e(()=>n(null,...a[u])):u in r?r[u].push(n):(r[u]=[n],s(...e,(e,...t)=>{e||(a[u]=t);var n=r[u];delete r[u];for(var s=0,d=n.length;s{n(e[0],t)},t,1)}function ee(e){return(e<<1)+1}function te(e){return(e+1>>1)-1}function ne(e,t){return e.priority===t.priority?e.pushCount({data:e,priority:t})):{data:e,priority:t}}var a=$(e,t),{push:i,pushAsync:r}=a;return a._tasks=new ht,a._createTaskItem=({data:e,priority:t},n)=>({data:e,priority:t,callback:n}),a.push=function(e,t=0,a){return i(n(e,t),a)},a.pushAsync=function(e,t=0,a){return r(n(e,t),a)},delete a.unshift,delete a.unshiftAsync,a}function ie(e,t,n,a){var i=[...e].reverse();return qe(i,t,n,a)}function re(e){var t=c(e);return n(function(e,n){return e.push((e,...t)=>{let a={};if(e&&(a.error=e),0=t.length&&([i]=t),a.value=i}n(null,a)}),t.apply(this,e)})}function se(e){var t;return Array.isArray(e)?t=e.map(re):(t={},Object.keys(e).forEach(n=>{t[n]=re.call(this,e[n])})),t}function le(e,t,n,a){const i=c(n);return U(e,t,(e,t)=>{i(e,(e,n)=>{t(e,!n)})},a)}function ue(e){return function(){return e}}function de(e,t,n){function a(){r((e,...t)=>{!1===e||(e&&s++arguments.length&&"function"==typeof e?(n=t||b(),t=e):(pe(i,e),n=n||b()),"function"!=typeof t)throw new Error("Invalid arguments for async.retry");var r=c(t),s=1;return a(),n[Ce]}function pe(e,n){if("object"==typeof n)e.times=+n.times||kt,e.intervalFunc="function"==typeof n.interval?n.interval:ue(+n.interval||vt),e.errorFilter=n.errorFilter;else if("number"==typeof n||"string"==typeof n)e.times=+n||kt;else throw new Error("Invalid arguments for async.retry")}function ce(e,t){t||(t=e,e=null);let a=e&&e.arity||t.length;u(t)&&(a+=1);var i=c(t);return n((t,n)=>{function r(e){i(...t,e)}return(t.length{var s,l=!1;n.push((...e)=>{l||(r(...e),clearTimeout(s))}),s=setTimeout(function(){var t=e.name||"anonymous",n=new Error("Callback function \""+t+"\" timed out.");n.code="ETIMEDOUT",a&&(n.info=a),l=!0,r(n)},t),i(...n)})}function fe(e){for(var t=Array(e);e--;)t[e]=e;return t}function ye(e,t,n,a){var i=c(n);return De(fe(e),t,i,a)}function me(e,t,n){return ye(e,1/0,t,n)}function ge(e,t,n){return ye(e,1,t,n)}function ke(e,t,n,a){3>=arguments.length&&"function"==typeof t&&(a=n,n=t,t=Array.isArray(e)?[]:{}),a=m(a||b());var i=c(n);return Me(e,(e,n,a)=>{i(t,e,n,a)},e=>a(e,t)),a[Ce]}function ve(e){return(...t)=>(e.unmemoized||e)(...t)}function Se(e,t,n){const a=c(e);return _t(e=>a((t,n)=>e(t,!n)),t,n)}var xe,Le="function"==typeof queueMicrotask&&queueMicrotask,Ee="function"==typeof setImmediate&&setImmediate,Oe="object"==typeof process&&"function"==typeof process.nextTick;xe=Le?queueMicrotask:Ee?setImmediate:Oe?process.nextTick:a;var _e=i(xe);const be={};var Ae=e=>(t,n,a)=>{function i(e,t){if(!u)if(c-=1,e)l=!0,a(e);else if(!1===e)l=!0,u=!0;else{if(t===be||l&&0>=c)return l=!0,a(null);o||r()}}function r(){for(o=!0;c=c&&a(null));c+=1,n(t.value,t.key,L(i))}o=!1}if(a=m(a),0>=e)throw new RangeError("concurrency limit cannot be less than 1");if(!t)return a(null);if(d(t))return E(t,e,n,a);if(p(t))return E(t[Symbol.asyncIterator](),e,n,a);var s=x(t),l=!1,u=!1,c=0,o=!1;r()},Ie=o(function(e,t,n,a){return Ae(t)(e,c(n),a)},4),Me=o(function(e,t,n){var a=y(e)?O:_;return a(e,c(t),n)},3),je=o(function(e,t,n){return f(Me,e,t,n)},3),we=h(je),Be=o(function(e,t,n){return Ie(e,1,t,n)},3),Te=o(function(e,t,n){return f(Be,e,t,n)},3),Fe=h(Te);const Ce=Symbol("promiseCallback");var Pe=/^(?:async\s+)?(?:function)?\s*\w*\s*\(\s*([^)]+)\s*\)(?:\s*{)/,Re=/^(?:async\s+)?\(?\s*([^)=]+)\s*\)?(?:\s*=>)/,ze=/,/,Ne=/(=.+)?(\s*)$/;class Ve{constructor(){this.head=this.tail=null,this.length=0}removeLink(e){return e.prev?e.prev.next=e.next:this.head=e.next,e.next?e.next.prev=e.prev:this.tail=e.prev,e.prev=e.next=null,this.length-=1,e}empty(){for(;this.head;)this.shift();return this}insertAfter(e,t){t.prev=e,t.next=e.next,e.next?e.next.prev=t:this.tail=t,e.next=t,this.length+=1}insertBefore(e,t){t.prev=e.prev,t.next=e,e.prev?e.prev.next=t:this.head=t,e.prev=t,this.length+=1}unshift(e){this.head?this.insertBefore(this.head,e):w(this,e)}push(e){this.tail?this.insertAfter(this.tail,e):w(this,e)}shift(){return this.head&&this.removeLink(this.head)}pop(){return this.tail&&this.removeLink(this.tail)}toArray(){return[...this]}*[Symbol.iterator](){for(var e=this.head;e;)yield e.data,e=e.next}remove(e){for(var t=this.head;t;){var{next:n}=t;e(t)&&this.removeLink(t),t=n}return this}}var Ye,qe=o(function(e,t,n,a){a=m(a);var r=c(n);return Be(e,(e,n,a)=>{r(t,e,(e,n)=>{t=n,a(e)})},e=>a(e,t))},4),De=o(function(e,t,n,a){return f(Ae(t),e,n,a)},4),Qe=o(function(e,t,n,a){var i=c(n);return De(e,t,(e,t)=>{i(e,(e,...n)=>e?t(e):t(e,n))},(e,t)=>{for(var n=[],r=0;re,(e,t)=>t)(Me,e,t,n)},3),He=o(function(e,t,n,a){return z(e=>e,(e,t)=>t)(Ae(t),e,n,a)},4),Je=o(function(e,t,n){return z(e=>e,(e,t)=>t)(Ae(1),e,t,n)},3),Ke=N("dir"),Xe=o(function(e,t,n){function a(e,...t){return e?n(e):void(!1===e||(r=t,l(...t,i)))}function i(e,t){return e?n(e):!1===e?void 0:t?void s(a):n(null,...r)}n=L(n);var r,s=c(e),l=c(t);return i(null,!0)},3),Ze=o(function(e,t,n){return Me(e,Y(c(t)),n)},3),$e=o(function(e,t,n,a){return Ae(t)(e,Y(c(n)),a)},4),et=o(function(e,t,n){return $e(e,1,t,n)},3),tt=o(function(e,t,n){return z(e=>!e,e=>!e)(Me,e,t,n)},3),nt=o(function(e,t,n,a){return z(e=>!e,e=>!e)(Ae(t),e,n,a)},4),at=o(function(e,t,n){return z(e=>!e,e=>!e)(Be,e,t,n)},3),it=o(function(e,t,n){return U(Me,e,t,n)},3),rt=o(function(e,t,n,a){return U(Ae(t),e,n,a)},4),st=o(function(e,t,n){return U(Be,e,t,n)},3),lt=o(function(e,t){function n(e){return e?a(e):void(!1===e||i(n))}var a=L(t),i=c(q(e));return n()},2),ut=o(function(e,t,n,a){var i=c(n);return De(e,t,(e,t)=>{i(e,(n,a)=>n?t(n):t(n,{key:a,val:e}))},(e,t)=>{for(var n={},{hasOwnProperty:r}=Object.prototype,s=0;s{r(e,t,(e,a)=>e?n(e):void(i[t]=a,n(e)))},e=>a(e,i))},4);Ye=Oe?process.nextTick:Ee?setImmediate:a;var ct=i(Ye),ot=o((e,t,n)=>{var a=y(t)?[]:{};e(t,(e,t,n)=>{c(e)((e,...i)=>{2>i.length&&([i]=i),a[t]=i,n(e)})},e=>n(e,a))},3);class ht{constructor(){this.heap=[],this.pushCount=Number.MIN_SAFE_INTEGER}get length(){return this.heap.length}empty(){return this.heap=[],this}percUp(e){for(let n;0e)(Me,e,t,n)},3),xt=o(function(e,t,n,a){return z(Boolean,e=>e)(Ae(t),e,n,a)},4),Lt=o(function(e,t,n){return z(Boolean,e=>e)(Be,e,t,n)},3),Et=o(function(e,t,n){function a(e,t){var n=e.criteria,a=t.criteria;return na?1:0}var i=c(t);return je(e,(e,t)=>{i(e,(n,a)=>n?t(n):void t(n,{value:e,criteria:a}))},(e,t)=>e?n(e):void n(null,t.sort(a).map(e=>e.value)))},3),Ot=o(function(e,t){var n,a=null;return et(e,(e,t)=>{c(e)((e,...i)=>!1===e?t(e):void(2>i.length?[n]=i:n=i,a=e,t(e?null:{})))},()=>t(a,n))}),_t=o(function(e,t,n){function a(e,...t){if(e)return n(e);l=t;!1===e||s(i)}function i(e,t){return e?n(e):!1===e?void 0:t?void r(a):n(null,...l)}n=L(n);var r=c(t),s=c(e),l=[];return s(i)},3),bt=o(function(e,t){function n(t){var n=c(e[i++]);n(...t,L(a))}function a(a,...r){return!1===a?void 0:a||i===e.length?t(a,...r):void n(r)}if(t=m(t),!Array.isArray(e))return t(new Error("First argument to waterfall must be an array of functions"));if(!e.length)return t();var i=0;n([])});e.default={apply:t,applyEach:we,applyEachSeries:Fe,asyncify:r,auto:A,autoInject:j,cargo:T,cargoQueue:F,compose:P,concat:Ue,concatLimit:Qe,concatSeries:Ge,constant:R,detect:We,detectLimit:He,detectSeries:Je,dir:Ke,doUntil:V,doWhilst:Xe,each:Ze,eachLimit:$e,eachOf:Me,eachOfLimit:Ie,eachOfSeries:Be,eachSeries:et,ensureAsync:q,every:tt,everyLimit:nt,everySeries:at,filter:it,filterLimit:rt,filterSeries:st,forever:lt,groupBy:G,groupByLimit:ut,groupBySeries:W,log:dt,map:je,mapLimit:De,mapSeries:Te,mapValues:H,mapValuesLimit:pt,mapValuesSeries:J,memoize:K,nextTick:ct,parallel:X,parallelLimit:Z,priorityQueue:ae,queue:$,race:ft,reduce:qe,reduceRight:ie,reflect:re,reflectAll:se,reject:yt,rejectLimit:mt,rejectSeries:gt,retry:de,retryable:ce,seq:C,series:oe,setImmediate:_e,some:St,someLimit:xt,someSeries:Lt,sortBy:Et,timeout:he,times:me,timesLimit:ye,timesSeries:ge,transform:ke,tryEach:Ot,unmemoize:ve,until:Se,waterfall:bt,whilst:_t,all:tt,allLimit:nt,allSeries:at,any:St,anyLimit:xt,anySeries:Lt,find:We,findLimit:He,findSeries:Je,flatMap:Ue,flatMapLimit:Qe,flatMapSeries:Ge,forEach:Ze,forEachSeries:et,forEachLimit:$e,forEachOf:Me,forEachOfSeries:Be,forEachOfLimit:Ie,inject:qe,foldl:qe,foldr:ie,select:it,selectLimit:rt,selectSeries:st,wrapSync:r,during:_t,doDuring:Xe},e.apply=t,e.applyEach=we,e.applyEachSeries=Fe,e.asyncify=r,e.auto=A,e.autoInject=j,e.cargo=T,e.cargoQueue=F,e.compose=P,e.concat=Ue,e.concatLimit=Qe,e.concatSeries=Ge,e.constant=R,e.detect=We,e.detectLimit=He,e.detectSeries=Je,e.dir=Ke,e.doUntil=V,e.doWhilst=Xe,e.each=Ze,e.eachLimit=$e,e.eachOf=Me,e.eachOfLimit=Ie,e.eachOfSeries=Be,e.eachSeries=et,e.ensureAsync=q,e.every=tt,e.everyLimit=nt,e.everySeries=at,e.filter=it,e.filterLimit=rt,e.filterSeries=st,e.forever=lt,e.groupBy=G,e.groupByLimit=ut,e.groupBySeries=W,e.log=dt,e.map=je,e.mapLimit=De,e.mapSeries=Te,e.mapValues=H,e.mapValuesLimit=pt,e.mapValuesSeries=J,e.memoize=K,e.nextTick=ct,e.parallel=X,e.parallelLimit=Z,e.priorityQueue=ae,e.queue=$,e.race=ft,e.reduce=qe,e.reduceRight=ie,e.reflect=re,e.reflectAll=se,e.reject=yt,e.rejectLimit=mt,e.rejectSeries=gt,e.retry=de,e.retryable=ce,e.seq=C,e.series=oe,e.setImmediate=_e,e.some=St,e.someLimit=xt,e.someSeries=Lt,e.sortBy=Et,e.timeout=he,e.times=me,e.timesLimit=ye,e.timesSeries=ge,e.transform=ke,e.tryEach=Ot,e.unmemoize=ve,e.until=Se,e.waterfall=bt,e.whilst=_t,e.all=tt,e.allLimit=nt,e.allSeries=at,e.any=St,e.anyLimit=xt,e.anySeries=Lt,e.find=We,e.findLimit=He,e.findSeries=Je,e.flatMap=Ue,e.flatMapLimit=Qe,e.flatMapSeries=Ge,e.forEach=Ze,e.forEachSeries=et,e.forEachLimit=$e,e.forEachOf=Me,e.forEachOfSeries=Be,e.forEachOfLimit=Ie,e.inject=qe,e.foldl=qe,e.foldr=ie,e.select=it,e.selectLimit=rt,e.selectSeries=st,e.wrapSync=r,e.during=_t,e.doDuring=Xe,Object.defineProperty(e,"__esModule",{value:!0})}); \ No newline at end of file diff --git a/server/libs/fluentFfmpeg/LICENSE b/server/libs/fluentFfmpeg/LICENSE new file mode 100644 index 000000000..f037822f8 --- /dev/null +++ b/server/libs/fluentFfmpeg/LICENSE @@ -0,0 +1,9 @@ +(The MIT License) + +Copyright (c) 2011-2015 The fluent-ffmpeg contributors + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/server/libs/fluentFfmpeg/capabilities.js b/server/libs/fluentFfmpeg/capabilities.js new file mode 100644 index 000000000..0e0a823d9 --- /dev/null +++ b/server/libs/fluentFfmpeg/capabilities.js @@ -0,0 +1,665 @@ +/*jshint node:true*/ +'use strict'; + +var fs = require('fs'); +var path = require('path'); +var async = require('../async'); +var utils = require('./utils'); + +/* + *! Capability helpers + */ + +var avCodecRegexp = /^\s*([D ])([E ])([VAS])([S ])([D ])([T ]) ([^ ]+) +(.*)$/; +var ffCodecRegexp = /^\s*([D\.])([E\.])([VAS])([I\.])([L\.])([S\.]) ([^ ]+) +(.*)$/; +var ffEncodersRegexp = /\(encoders:([^\)]+)\)/; +var ffDecodersRegexp = /\(decoders:([^\)]+)\)/; +var encodersRegexp = /^\s*([VAS\.])([F\.])([S\.])([X\.])([B\.])([D\.]) ([^ ]+) +(.*)$/; +var formatRegexp = /^\s*([D ])([E ]) ([^ ]+) +(.*)$/; +var lineBreakRegexp = /\r\n|\r|\n/; +var filterRegexp = /^(?: [T\.][S\.][C\.] )?([^ ]+) +(AA?|VV?|\|)->(AA?|VV?|\|) +(.*)$/; + +var cache = {}; + +module.exports = function (proto) { + /** + * Manually define the ffmpeg binary full path. + * + * @method FfmpegCommand#setFfmpegPath + * + * @param {String} ffmpegPath The full path to the ffmpeg binary. + * @return FfmpegCommand + */ + proto.setFfmpegPath = function (ffmpegPath) { + cache.ffmpegPath = ffmpegPath; + return this; + }; + + /** + * Manually define the ffprobe binary full path. + * + * @method FfmpegCommand#setFfprobePath + * + * @param {String} ffprobePath The full path to the ffprobe binary. + * @return FfmpegCommand + */ + proto.setFfprobePath = function (ffprobePath) { + cache.ffprobePath = ffprobePath; + return this; + }; + + /** + * Manually define the flvtool2/flvmeta binary full path. + * + * @method FfmpegCommand#setFlvtoolPath + * + * @param {String} flvtool The full path to the flvtool2 or flvmeta binary. + * @return FfmpegCommand + */ + proto.setFlvtoolPath = function (flvtool) { + cache.flvtoolPath = flvtool; + return this; + }; + + /** + * Forget executable paths + * + * (only used for testing purposes) + * + * @method FfmpegCommand#_forgetPaths + * @private + */ + proto._forgetPaths = function () { + delete cache.ffmpegPath; + delete cache.ffprobePath; + delete cache.flvtoolPath; + }; + + /** + * Check for ffmpeg availability + * + * If the FFMPEG_PATH environment variable is set, try to use it. + * If it is unset or incorrect, try to find ffmpeg in the PATH instead. + * + * @method FfmpegCommand#_getFfmpegPath + * @param {Function} callback callback with signature (err, path) + * @private + */ + proto._getFfmpegPath = function (callback) { + if ('ffmpegPath' in cache) { + return callback(null, cache.ffmpegPath); + } + + async.waterfall([ + // Try FFMPEG_PATH + function (cb) { + if (process.env.FFMPEG_PATH) { + fs.exists(process.env.FFMPEG_PATH, function (exists) { + if (exists) { + cb(null, process.env.FFMPEG_PATH); + } else { + cb(null, ''); + } + }); + } else { + cb(null, ''); + } + }, + + // Search in the PATH + function (ffmpeg, cb) { + if (ffmpeg.length) { + return cb(null, ffmpeg); + } + + utils.which('ffmpeg', function (err, ffmpeg) { + cb(err, ffmpeg); + }); + } + ], function (err, ffmpeg) { + if (err) { + callback(err); + } else { + callback(null, cache.ffmpegPath = (ffmpeg || '')); + } + }); + }; + + + /** + * Check for ffprobe availability + * + * If the FFPROBE_PATH environment variable is set, try to use it. + * If it is unset or incorrect, try to find ffprobe in the PATH instead. + * If this still fails, try to find ffprobe in the same directory as ffmpeg. + * + * @method FfmpegCommand#_getFfprobePath + * @param {Function} callback callback with signature (err, path) + * @private + */ + proto._getFfprobePath = function (callback) { + var self = this; + + if ('ffprobePath' in cache) { + return callback(null, cache.ffprobePath); + } + + async.waterfall([ + // Try FFPROBE_PATH + function (cb) { + if (process.env.FFPROBE_PATH) { + fs.exists(process.env.FFPROBE_PATH, function (exists) { + cb(null, exists ? process.env.FFPROBE_PATH : ''); + }); + } else { + cb(null, ''); + } + }, + + // Search in the PATH + function (ffprobe, cb) { + if (ffprobe.length) { + return cb(null, ffprobe); + } + + utils.which('ffprobe', function (err, ffprobe) { + cb(err, ffprobe); + }); + }, + + // Search in the same directory as ffmpeg + function (ffprobe, cb) { + if (ffprobe.length) { + return cb(null, ffprobe); + } + + self._getFfmpegPath(function (err, ffmpeg) { + if (err) { + cb(err); + } else if (ffmpeg.length) { + var name = utils.isWindows ? 'ffprobe.exe' : 'ffprobe'; + var ffprobe = path.join(path.dirname(ffmpeg), name); + fs.exists(ffprobe, function (exists) { + cb(null, exists ? ffprobe : ''); + }); + } else { + cb(null, ''); + } + }); + } + ], function (err, ffprobe) { + if (err) { + callback(err); + } else { + callback(null, cache.ffprobePath = (ffprobe || '')); + } + }); + }; + + + /** + * Check for flvtool2/flvmeta availability + * + * If the FLVTOOL2_PATH or FLVMETA_PATH environment variable are set, try to use them. + * If both are either unset or incorrect, try to find flvtool2 or flvmeta in the PATH instead. + * + * @method FfmpegCommand#_getFlvtoolPath + * @param {Function} callback callback with signature (err, path) + * @private + */ + proto._getFlvtoolPath = function (callback) { + if ('flvtoolPath' in cache) { + return callback(null, cache.flvtoolPath); + } + + async.waterfall([ + // Try FLVMETA_PATH + function (cb) { + if (process.env.FLVMETA_PATH) { + fs.exists(process.env.FLVMETA_PATH, function (exists) { + cb(null, exists ? process.env.FLVMETA_PATH : ''); + }); + } else { + cb(null, ''); + } + }, + + // Try FLVTOOL2_PATH + function (flvtool, cb) { + if (flvtool.length) { + return cb(null, flvtool); + } + + if (process.env.FLVTOOL2_PATH) { + fs.exists(process.env.FLVTOOL2_PATH, function (exists) { + cb(null, exists ? process.env.FLVTOOL2_PATH : ''); + }); + } else { + cb(null, ''); + } + }, + + // Search for flvmeta in the PATH + function (flvtool, cb) { + if (flvtool.length) { + return cb(null, flvtool); + } + + utils.which('flvmeta', function (err, flvmeta) { + cb(err, flvmeta); + }); + }, + + // Search for flvtool2 in the PATH + function (flvtool, cb) { + if (flvtool.length) { + return cb(null, flvtool); + } + + utils.which('flvtool2', function (err, flvtool2) { + cb(err, flvtool2); + }); + }, + ], function (err, flvtool) { + if (err) { + callback(err); + } else { + callback(null, cache.flvtoolPath = (flvtool || '')); + } + }); + }; + + + /** + * A callback passed to {@link FfmpegCommand#availableFilters}. + * + * @callback FfmpegCommand~filterCallback + * @param {Error|null} err error object or null if no error happened + * @param {Object} filters filter object with filter names as keys and the following + * properties for each filter: + * @param {String} filters.description filter description + * @param {String} filters.input input type, one of 'audio', 'video' and 'none' + * @param {Boolean} filters.multipleInputs whether the filter supports multiple inputs + * @param {String} filters.output output type, one of 'audio', 'video' and 'none' + * @param {Boolean} filters.multipleOutputs whether the filter supports multiple outputs + */ + + /** + * Query ffmpeg for available filters + * + * @method FfmpegCommand#availableFilters + * @category Capabilities + * @aliases getAvailableFilters + * + * @param {FfmpegCommand~filterCallback} callback callback function + */ + proto.availableFilters = + proto.getAvailableFilters = function (callback) { + if ('filters' in cache) { + return callback(null, cache.filters); + } + + this._spawnFfmpeg(['-filters'], { captureStdout: true, stdoutLines: 0 }, function (err, stdoutRing) { + if (err) { + return callback(err); + } + + var stdout = stdoutRing.get(); + var lines = stdout.split('\n'); + var data = {}; + var types = { A: 'audio', V: 'video', '|': 'none' }; + + lines.forEach(function (line) { + var match = line.match(filterRegexp); + if (match) { + data[match[1]] = { + description: match[4], + input: types[match[2].charAt(0)], + multipleInputs: match[2].length > 1, + output: types[match[3].charAt(0)], + multipleOutputs: match[3].length > 1 + }; + } + }); + + callback(null, cache.filters = data); + }); + }; + + + /** + * A callback passed to {@link FfmpegCommand#availableCodecs}. + * + * @callback FfmpegCommand~codecCallback + * @param {Error|null} err error object or null if no error happened + * @param {Object} codecs codec object with codec names as keys and the following + * properties for each codec (more properties may be available depending on the + * ffmpeg version used): + * @param {String} codecs.description codec description + * @param {Boolean} codecs.canDecode whether the codec is able to decode streams + * @param {Boolean} codecs.canEncode whether the codec is able to encode streams + */ + + /** + * Query ffmpeg for available codecs + * + * @method FfmpegCommand#availableCodecs + * @category Capabilities + * @aliases getAvailableCodecs + * + * @param {FfmpegCommand~codecCallback} callback callback function + */ + proto.availableCodecs = + proto.getAvailableCodecs = function (callback) { + if ('codecs' in cache) { + return callback(null, cache.codecs); + } + + this._spawnFfmpeg(['-codecs'], { captureStdout: true, stdoutLines: 0 }, function (err, stdoutRing) { + if (err) { + return callback(err); + } + + var stdout = stdoutRing.get(); + var lines = stdout.split(lineBreakRegexp); + var data = {}; + + lines.forEach(function (line) { + var match = line.match(avCodecRegexp); + if (match && match[7] !== '=') { + data[match[7]] = { + type: { 'V': 'video', 'A': 'audio', 'S': 'subtitle' }[match[3]], + description: match[8], + canDecode: match[1] === 'D', + canEncode: match[2] === 'E', + drawHorizBand: match[4] === 'S', + directRendering: match[5] === 'D', + weirdFrameTruncation: match[6] === 'T' + }; + } + + match = line.match(ffCodecRegexp); + if (match && match[7] !== '=') { + var codecData = data[match[7]] = { + type: { 'V': 'video', 'A': 'audio', 'S': 'subtitle' }[match[3]], + description: match[8], + canDecode: match[1] === 'D', + canEncode: match[2] === 'E', + intraFrameOnly: match[4] === 'I', + isLossy: match[5] === 'L', + isLossless: match[6] === 'S' + }; + + var encoders = codecData.description.match(ffEncodersRegexp); + encoders = encoders ? encoders[1].trim().split(' ') : []; + + var decoders = codecData.description.match(ffDecodersRegexp); + decoders = decoders ? decoders[1].trim().split(' ') : []; + + if (encoders.length || decoders.length) { + var coderData = {}; + utils.copy(codecData, coderData); + delete coderData.canEncode; + delete coderData.canDecode; + + encoders.forEach(function (name) { + data[name] = {}; + utils.copy(coderData, data[name]); + data[name].canEncode = true; + }); + + decoders.forEach(function (name) { + if (name in data) { + data[name].canDecode = true; + } else { + data[name] = {}; + utils.copy(coderData, data[name]); + data[name].canDecode = true; + } + }); + } + } + }); + + callback(null, cache.codecs = data); + }); + }; + + + /** + * A callback passed to {@link FfmpegCommand#availableEncoders}. + * + * @callback FfmpegCommand~encodersCallback + * @param {Error|null} err error object or null if no error happened + * @param {Object} encoders encoders object with encoder names as keys and the following + * properties for each encoder: + * @param {String} encoders.description codec description + * @param {Boolean} encoders.type "audio", "video" or "subtitle" + * @param {Boolean} encoders.frameMT whether the encoder is able to do frame-level multithreading + * @param {Boolean} encoders.sliceMT whether the encoder is able to do slice-level multithreading + * @param {Boolean} encoders.experimental whether the encoder is experimental + * @param {Boolean} encoders.drawHorizBand whether the encoder supports draw_horiz_band + * @param {Boolean} encoders.directRendering whether the encoder supports direct encoding method 1 + */ + + /** + * Query ffmpeg for available encoders + * + * @method FfmpegCommand#availableEncoders + * @category Capabilities + * @aliases getAvailableEncoders + * + * @param {FfmpegCommand~encodersCallback} callback callback function + */ + proto.availableEncoders = + proto.getAvailableEncoders = function (callback) { + if ('encoders' in cache) { + return callback(null, cache.encoders); + } + + this._spawnFfmpeg(['-encoders'], { captureStdout: true, stdoutLines: 0 }, function (err, stdoutRing) { + if (err) { + return callback(err); + } + + var stdout = stdoutRing.get(); + var lines = stdout.split(lineBreakRegexp); + var data = {}; + + lines.forEach(function (line) { + var match = line.match(encodersRegexp); + if (match && match[7] !== '=') { + data[match[7]] = { + type: { 'V': 'video', 'A': 'audio', 'S': 'subtitle' }[match[1]], + description: match[8], + frameMT: match[2] === 'F', + sliceMT: match[3] === 'S', + experimental: match[4] === 'X', + drawHorizBand: match[5] === 'B', + directRendering: match[6] === 'D' + }; + } + }); + + callback(null, cache.encoders = data); + }); + }; + + + /** + * A callback passed to {@link FfmpegCommand#availableFormats}. + * + * @callback FfmpegCommand~formatCallback + * @param {Error|null} err error object or null if no error happened + * @param {Object} formats format object with format names as keys and the following + * properties for each format: + * @param {String} formats.description format description + * @param {Boolean} formats.canDemux whether the format is able to demux streams from an input file + * @param {Boolean} formats.canMux whether the format is able to mux streams into an output file + */ + + /** + * Query ffmpeg for available formats + * + * @method FfmpegCommand#availableFormats + * @category Capabilities + * @aliases getAvailableFormats + * + * @param {FfmpegCommand~formatCallback} callback callback function + */ + proto.availableFormats = + proto.getAvailableFormats = function (callback) { + if ('formats' in cache) { + return callback(null, cache.formats); + } + + // Run ffmpeg -formats + this._spawnFfmpeg(['-formats'], { captureStdout: true, stdoutLines: 0 }, function (err, stdoutRing) { + if (err) { + return callback(err); + } + + // Parse output + var stdout = stdoutRing.get(); + var lines = stdout.split(lineBreakRegexp); + var data = {}; + + lines.forEach(function (line) { + var match = line.match(formatRegexp); + if (match) { + match[3].split(',').forEach(function (format) { + if (!(format in data)) { + data[format] = { + description: match[4], + canDemux: false, + canMux: false + }; + } + + if (match[1] === 'D') { + data[format].canDemux = true; + } + if (match[2] === 'E') { + data[format].canMux = true; + } + }); + } + }); + + callback(null, cache.formats = data); + }); + }; + + + /** + * Check capabilities before executing a command + * + * Checks whether all used codecs and formats are indeed available + * + * @method FfmpegCommand#_checkCapabilities + * @param {Function} callback callback with signature (err) + * @private + */ + proto._checkCapabilities = function (callback) { + var self = this; + async.waterfall([ + // Get available formats + function (cb) { + self.availableFormats(cb); + }, + + // Check whether specified formats are available + function (formats, cb) { + var unavailable; + + // Output format(s) + unavailable = self._outputs + .reduce(function (fmts, output) { + var format = output.options.find('-f', 1); + if (format) { + if (!(format[0] in formats) || !(formats[format[0]].canMux)) { + fmts.push(format); + } + } + + return fmts; + }, []); + + if (unavailable.length === 1) { + return cb(new Error('Output format ' + unavailable[0] + ' is not available')); + } else if (unavailable.length > 1) { + return cb(new Error('Output formats ' + unavailable.join(', ') + ' are not available')); + } + + // Input format(s) + unavailable = self._inputs + .reduce(function (fmts, input) { + var format = input.options.find('-f', 1); + if (format) { + if (!(format[0] in formats) || !(formats[format[0]].canDemux)) { + fmts.push(format[0]); + } + } + + return fmts; + }, []); + + if (unavailable.length === 1) { + return cb(new Error('Input format ' + unavailable[0] + ' is not available')); + } else if (unavailable.length > 1) { + return cb(new Error('Input formats ' + unavailable.join(', ') + ' are not available')); + } + + cb(); + }, + + // Get available codecs + function (cb) { + self.availableEncoders(cb); + }, + + // Check whether specified codecs are available and add strict experimental options if needed + function (encoders, cb) { + var unavailable; + + // Audio codec(s) + unavailable = self._outputs.reduce(function (cdcs, output) { + var acodec = output.audio.find('-acodec', 1); + if (acodec && acodec[0] !== 'copy') { + if (!(acodec[0] in encoders) || encoders[acodec[0]].type !== 'audio') { + cdcs.push(acodec[0]); + } + } + + return cdcs; + }, []); + + if (unavailable.length === 1) { + return cb(new Error('Audio codec ' + unavailable[0] + ' is not available')); + } else if (unavailable.length > 1) { + return cb(new Error('Audio codecs ' + unavailable.join(', ') + ' are not available')); + } + + // Video codec(s) + unavailable = self._outputs.reduce(function (cdcs, output) { + var vcodec = output.video.find('-vcodec', 1); + if (vcodec && vcodec[0] !== 'copy') { + if (!(vcodec[0] in encoders) || encoders[vcodec[0]].type !== 'video') { + cdcs.push(vcodec[0]); + } + } + + return cdcs; + }, []); + + if (unavailable.length === 1) { + return cb(new Error('Video codec ' + unavailable[0] + ' is not available')); + } else if (unavailable.length > 1) { + return cb(new Error('Video codecs ' + unavailable.join(', ') + ' are not available')); + } + + cb(); + } + ], callback); + }; +}; diff --git a/server/libs/fluentFfmpeg/ffprobe.js b/server/libs/fluentFfmpeg/ffprobe.js new file mode 100644 index 000000000..d24be85d2 --- /dev/null +++ b/server/libs/fluentFfmpeg/ffprobe.js @@ -0,0 +1,261 @@ +/*jshint node:true, laxcomma:true*/ +'use strict'; + +var spawn = require('child_process').spawn; + + +function legacyTag(key) { return key.match(/^TAG:/); } +function legacyDisposition(key) { return key.match(/^DISPOSITION:/); } + +function parseFfprobeOutput(out) { + var lines = out.split(/\r\n|\r|\n/); + + lines = lines.filter(function (line) { + return line.length > 0; + }); + + var data = { + streams: [], + format: {}, + chapters: [] + }; + + function parseBlock(name) { + var data = {}; + + var line = lines.shift(); + while (typeof line !== 'undefined') { + if (line.toLowerCase() == '[/'+name+']') { + return data; + } else if (line.match(/^\[/)) { + line = lines.shift(); + continue; + } + + var kv = line.match(/^([^=]+)=(.*)$/); + if (kv) { + if (!(kv[1].match(/^TAG:/)) && kv[2].match(/^[0-9]+(\.[0-9]+)?$/)) { + data[kv[1]] = Number(kv[2]); + } else { + data[kv[1]] = kv[2]; + } + } + + line = lines.shift(); + } + + return data; + } + + var line = lines.shift(); + while (typeof line !== 'undefined') { + if (line.match(/^\[stream/i)) { + var stream = parseBlock('stream'); + data.streams.push(stream); + } else if (line.match(/^\[chapter/i)) { + var chapter = parseBlock('chapter'); + data.chapters.push(chapter); + } else if (line.toLowerCase() === '[format]') { + data.format = parseBlock('format'); + } + + line = lines.shift(); + } + + return data; +} + + + +module.exports = function(proto) { + /** + * A callback passed to the {@link FfmpegCommand#ffprobe} method. + * + * @callback FfmpegCommand~ffprobeCallback + * + * @param {Error|null} err error object or null if no error happened + * @param {Object} ffprobeData ffprobe output data; this object + * has the same format as what the following command returns: + * + * `ffprobe -print_format json -show_streams -show_format INPUTFILE` + * @param {Array} ffprobeData.streams stream information + * @param {Object} ffprobeData.format format information + */ + + /** + * Run ffprobe on last specified input + * + * @method FfmpegCommand#ffprobe + * @category Metadata + * + * @param {?Number} [index] 0-based index of input to probe (defaults to last input) + * @param {?String[]} [options] array of output options to return + * @param {FfmpegCommand~ffprobeCallback} callback callback function + * + */ + proto.ffprobe = function() { + var input, index = null, options = [], callback; + + // the last argument should be the callback + var callback = arguments[arguments.length - 1]; + + var ended = false + function handleCallback(err, data) { + if (!ended) { + ended = true; + callback(err, data); + } + }; + + // map the arguments to the correct variable names + switch (arguments.length) { + case 3: + index = arguments[0]; + options = arguments[1]; + break; + case 2: + if (typeof arguments[0] === 'number') { + index = arguments[0]; + } else if (Array.isArray(arguments[0])) { + options = arguments[0]; + } + break; + } + + + if (index === null) { + if (!this._currentInput) { + return handleCallback(new Error('No input specified')); + } + + input = this._currentInput; + } else { + input = this._inputs[index]; + + if (!input) { + return handleCallback(new Error('Invalid input index')); + } + } + + // Find ffprobe + this._getFfprobePath(function(err, path) { + if (err) { + return handleCallback(err); + } else if (!path) { + return handleCallback(new Error('Cannot find ffprobe')); + } + + var stdout = ''; + var stdoutClosed = false; + var stderr = ''; + var stderrClosed = false; + + // Spawn ffprobe + var src = input.isStream ? 'pipe:0' : input.source; + var ffprobe = spawn(path, ['-show_streams', '-show_format'].concat(options, src), {windowsHide: true}); + + if (input.isStream) { + // Skip errors on stdin. These get thrown when ffprobe is complete and + // there seems to be no way hook in and close stdin before it throws. + ffprobe.stdin.on('error', function(err) { + if (['ECONNRESET', 'EPIPE', 'EOF'].indexOf(err.code) >= 0) { return; } + handleCallback(err); + }); + + // Once ffprobe's input stream closes, we need no more data from the + // input + ffprobe.stdin.on('close', function() { + input.source.pause(); + input.source.unpipe(ffprobe.stdin); + }); + + input.source.pipe(ffprobe.stdin); + } + + ffprobe.on('error', callback); + + // Ensure we wait for captured streams to end before calling callback + var exitError = null; + function handleExit(err) { + if (err) { + exitError = err; + } + + if (processExited && stdoutClosed && stderrClosed) { + if (exitError) { + if (stderr) { + exitError.message += '\n' + stderr; + } + + return handleCallback(exitError); + } + + // Process output + var data = parseFfprobeOutput(stdout); + + // Handle legacy output with "TAG:x" and "DISPOSITION:x" keys + [data.format].concat(data.streams).forEach(function(target) { + if (target) { + var legacyTagKeys = Object.keys(target).filter(legacyTag); + + if (legacyTagKeys.length) { + target.tags = target.tags || {}; + + legacyTagKeys.forEach(function(tagKey) { + target.tags[tagKey.substr(4)] = target[tagKey]; + delete target[tagKey]; + }); + } + + var legacyDispositionKeys = Object.keys(target).filter(legacyDisposition); + + if (legacyDispositionKeys.length) { + target.disposition = target.disposition || {}; + + legacyDispositionKeys.forEach(function(dispositionKey) { + target.disposition[dispositionKey.substr(12)] = target[dispositionKey]; + delete target[dispositionKey]; + }); + } + } + }); + + handleCallback(null, data); + } + } + + // Handle ffprobe exit + var processExited = false; + ffprobe.on('exit', function(code, signal) { + processExited = true; + + if (code) { + handleExit(new Error('ffprobe exited with code ' + code)); + } else if (signal) { + handleExit(new Error('ffprobe was killed with signal ' + signal)); + } else { + handleExit(); + } + }); + + // Handle stdout/stderr streams + ffprobe.stdout.on('data', function(data) { + stdout += data; + }); + + ffprobe.stdout.on('close', function() { + stdoutClosed = true; + handleExit(); + }); + + ffprobe.stderr.on('data', function(data) { + stderr += data; + }); + + ffprobe.stderr.on('close', function() { + stderrClosed = true; + handleExit(); + }); + }); + }; +}; diff --git a/server/libs/fluentFfmpeg/index.js b/server/libs/fluentFfmpeg/index.js new file mode 100644 index 000000000..8a5112e9c --- /dev/null +++ b/server/libs/fluentFfmpeg/index.js @@ -0,0 +1,231 @@ +/*jshint node:true*/ +'use strict'; + +// +// modified for use with audiobookshelf +// Source: https://github.com/fluent-ffmpeg/node-fluent-ffmpeg +// + +var path = require('path'); +var util = require('util'); +var EventEmitter = require('events').EventEmitter; + +var utils = require('./utils'); +var ARGLISTS = ['_global', '_audio', '_audioFilters', '_video', '_videoFilters', '_sizeFilters', '_complexFilters']; + + +/** + * Create an ffmpeg command + * + * Can be called with or without the 'new' operator, and the 'input' parameter + * may be specified as 'options.source' instead (or passed later with the + * addInput method). + * + * @constructor + * @param {String|ReadableStream} [input] input file path or readable stream + * @param {Object} [options] command options + * @param {Object} [options.logger=] logger object with 'error', 'warning', 'info' and 'debug' methods + * @param {Number} [options.niceness=0] ffmpeg process niceness, ignored on Windows + * @param {Number} [options.priority=0] alias for `niceness` + * @param {String} [options.presets="fluent-ffmpeg/lib/presets"] directory to load presets from + * @param {String} [options.preset="fluent-ffmpeg/lib/presets"] alias for `presets` + * @param {String} [options.stdoutLines=100] maximum lines of ffmpeg output to keep in memory, use 0 for unlimited + * @param {Number} [options.timeout=] ffmpeg processing timeout in seconds + * @param {String|ReadableStream} [options.source=] alias for the `input` parameter + */ +function FfmpegCommand(input, options) { + // Make 'new' optional + if (!(this instanceof FfmpegCommand)) { + return new FfmpegCommand(input, options); + } + + EventEmitter.call(this); + + if (typeof input === 'object' && !('readable' in input)) { + // Options object passed directly + options = input; + } else { + // Input passed first + options = options || {}; + options.source = input; + } + + // Add input if present + this._inputs = []; + if (options.source) { + this.input(options.source); + } + + // Add target-less output for backwards compatibility + this._outputs = []; + this.output(); + + // Create argument lists + var self = this; + ['_global', '_complexFilters'].forEach(function (prop) { + self[prop] = utils.args(); + }); + + // Set default option values + options.stdoutLines = 'stdoutLines' in options ? options.stdoutLines : 100; + options.presets = options.presets || options.preset || path.join(__dirname, 'presets'); + options.niceness = options.niceness || options.priority || 0; + + // Save options + this.options = options; + + // Setup logger + this.logger = options.logger || { + debug: function () { }, + info: function () { }, + warn: function () { }, + error: function () { } + }; +} +util.inherits(FfmpegCommand, EventEmitter); +module.exports = FfmpegCommand; + + +/** + * Clone an ffmpeg command + * + * This method is useful when you want to process the same input multiple times. + * It returns a new FfmpegCommand instance with the exact same options. + * + * All options set _after_ the clone() call will only be applied to the instance + * it has been called on. + * + * @example + * var command = ffmpeg('/path/to/source.avi') + * .audioCodec('libfaac') + * .videoCodec('libx264') + * .format('mp4'); + * + * command.clone() + * .size('320x200') + * .save('/path/to/output-small.mp4'); + * + * command.clone() + * .size('640x400') + * .save('/path/to/output-medium.mp4'); + * + * command.save('/path/to/output-original-size.mp4'); + * + * @method FfmpegCommand#clone + * @return FfmpegCommand + */ +FfmpegCommand.prototype.clone = function () { + var clone = new FfmpegCommand(); + var self = this; + + // Clone options and logger + clone.options = this.options; + clone.logger = this.logger; + + // Clone inputs + clone._inputs = this._inputs.map(function (input) { + return { + source: input.source, + options: input.options.clone() + }; + }); + + // Create first output + if ('target' in this._outputs[0]) { + // We have outputs set, don't clone them and create first output + clone._outputs = []; + clone.output(); + } else { + // No outputs set, clone first output options + clone._outputs = [ + clone._currentOutput = { + flags: {} + } + ]; + + ['audio', 'audioFilters', 'video', 'videoFilters', 'sizeFilters', 'options'].forEach(function (key) { + clone._currentOutput[key] = self._currentOutput[key].clone(); + }); + + if (this._currentOutput.sizeData) { + clone._currentOutput.sizeData = {}; + utils.copy(this._currentOutput.sizeData, clone._currentOutput.sizeData); + } + + utils.copy(this._currentOutput.flags, clone._currentOutput.flags); + } + + // Clone argument lists + ['_global', '_complexFilters'].forEach(function (prop) { + clone[prop] = self[prop].clone(); + }); + + return clone; +}; + + +/* Add methods from options submodules */ + +require('./options/inputs')(FfmpegCommand.prototype); +require('./options/audio')(FfmpegCommand.prototype); +require('./options/video')(FfmpegCommand.prototype); +require('./options/videosize')(FfmpegCommand.prototype); +require('./options/output')(FfmpegCommand.prototype); +require('./options/custom')(FfmpegCommand.prototype); +require('./options/misc')(FfmpegCommand.prototype); + + +/* Add processor methods */ + +require('./processor')(FfmpegCommand.prototype); + + +/* Add capabilities methods */ + +require('./capabilities')(FfmpegCommand.prototype); + +FfmpegCommand.setFfmpegPath = function (path) { + (new FfmpegCommand()).setFfmpegPath(path); +}; + +FfmpegCommand.setFfprobePath = function (path) { + (new FfmpegCommand()).setFfprobePath(path); +}; + +FfmpegCommand.setFlvtoolPath = function (path) { + (new FfmpegCommand()).setFlvtoolPath(path); +}; + +FfmpegCommand.availableFilters = + FfmpegCommand.getAvailableFilters = function (callback) { + (new FfmpegCommand()).availableFilters(callback); + }; + +FfmpegCommand.availableCodecs = + FfmpegCommand.getAvailableCodecs = function (callback) { + (new FfmpegCommand()).availableCodecs(callback); + }; + +FfmpegCommand.availableFormats = + FfmpegCommand.getAvailableFormats = function (callback) { + (new FfmpegCommand()).availableFormats(callback); + }; + +FfmpegCommand.availableEncoders = + FfmpegCommand.getAvailableEncoders = function (callback) { + (new FfmpegCommand()).availableEncoders(callback); + }; + + +/* Add ffprobe methods */ + +require('./ffprobe')(FfmpegCommand.prototype); + +FfmpegCommand.ffprobe = function (file) { + var instance = new FfmpegCommand(file); + instance.ffprobe.apply(instance, Array.prototype.slice.call(arguments, 1)); +}; + +/* Add processing recipes */ + +require('./recipes')(FfmpegCommand.prototype); diff --git a/server/libs/fluentFfmpeg/options/audio.js b/server/libs/fluentFfmpeg/options/audio.js new file mode 100644 index 000000000..607fdb37d --- /dev/null +++ b/server/libs/fluentFfmpeg/options/audio.js @@ -0,0 +1,178 @@ +/*jshint node:true*/ +'use strict'; + +var utils = require('../utils'); + + +/* + *! Audio-related methods + */ + +module.exports = function(proto) { + /** + * Disable audio in the output + * + * @method FfmpegCommand#noAudio + * @category Audio + * @aliases withNoAudio + * @return FfmpegCommand + */ + proto.withNoAudio = + proto.noAudio = function() { + this._currentOutput.audio.clear(); + this._currentOutput.audioFilters.clear(); + this._currentOutput.audio('-an'); + + return this; + }; + + + /** + * Specify audio codec + * + * @method FfmpegCommand#audioCodec + * @category Audio + * @aliases withAudioCodec + * + * @param {String} codec audio codec name + * @return FfmpegCommand + */ + proto.withAudioCodec = + proto.audioCodec = function(codec) { + this._currentOutput.audio('-acodec', codec); + + return this; + }; + + + /** + * Specify audio bitrate + * + * @method FfmpegCommand#audioBitrate + * @category Audio + * @aliases withAudioBitrate + * + * @param {String|Number} bitrate audio bitrate in kbps (with an optional 'k' suffix) + * @return FfmpegCommand + */ + proto.withAudioBitrate = + proto.audioBitrate = function(bitrate) { + this._currentOutput.audio('-b:a', ('' + bitrate).replace(/k?$/, 'k')); + return this; + }; + + + /** + * Specify audio channel count + * + * @method FfmpegCommand#audioChannels + * @category Audio + * @aliases withAudioChannels + * + * @param {Number} channels channel count + * @return FfmpegCommand + */ + proto.withAudioChannels = + proto.audioChannels = function(channels) { + this._currentOutput.audio('-ac', channels); + return this; + }; + + + /** + * Specify audio frequency + * + * @method FfmpegCommand#audioFrequency + * @category Audio + * @aliases withAudioFrequency + * + * @param {Number} freq audio frequency in Hz + * @return FfmpegCommand + */ + proto.withAudioFrequency = + proto.audioFrequency = function(freq) { + this._currentOutput.audio('-ar', freq); + return this; + }; + + + /** + * Specify audio quality + * + * @method FfmpegCommand#audioQuality + * @category Audio + * @aliases withAudioQuality + * + * @param {Number} quality audio quality factor + * @return FfmpegCommand + */ + proto.withAudioQuality = + proto.audioQuality = function(quality) { + this._currentOutput.audio('-aq', quality); + return this; + }; + + + /** + * Specify custom audio filter(s) + * + * Can be called both with one or many filters, or a filter array. + * + * @example + * command.audioFilters('filter1'); + * + * @example + * command.audioFilters('filter1', 'filter2=param1=value1:param2=value2'); + * + * @example + * command.audioFilters(['filter1', 'filter2']); + * + * @example + * command.audioFilters([ + * { + * filter: 'filter1' + * }, + * { + * filter: 'filter2', + * options: 'param=value:param=value' + * } + * ]); + * + * @example + * command.audioFilters( + * { + * filter: 'filter1', + * options: ['value1', 'value2'] + * }, + * { + * filter: 'filter2', + * options: { param1: 'value1', param2: 'value2' } + * } + * ); + * + * @method FfmpegCommand#audioFilters + * @aliases withAudioFilter,withAudioFilters,audioFilter + * @category Audio + * + * @param {...String|String[]|Object[]} filters audio filter strings, string array or + * filter specification array, each with the following properties: + * @param {String} filters.filter filter name + * @param {String|String[]|Object} [filters.options] filter option string, array, or object + * @return FfmpegCommand + */ + proto.withAudioFilter = + proto.withAudioFilters = + proto.audioFilter = + proto.audioFilters = function(filters) { + if (arguments.length > 1) { + filters = [].slice.call(arguments); + } + + if (!Array.isArray(filters)) { + filters = [filters]; + } + + this._currentOutput.audioFilters(utils.makeFilterStrings(filters)); + return this; + }; +}; diff --git a/server/libs/fluentFfmpeg/options/custom.js b/server/libs/fluentFfmpeg/options/custom.js new file mode 100644 index 000000000..d74356642 --- /dev/null +++ b/server/libs/fluentFfmpeg/options/custom.js @@ -0,0 +1,212 @@ +/*jshint node:true*/ +'use strict'; + +var utils = require('../utils'); + + +/* + *! Custom options methods + */ + +module.exports = function(proto) { + /** + * Add custom input option(s) + * + * When passing a single string or an array, each string containing two + * words is split (eg. inputOptions('-option value') is supported) for + * compatibility reasons. This is not the case when passing more than + * one argument. + * + * @example + * command.inputOptions('option1'); + * + * @example + * command.inputOptions('option1', 'option2'); + * + * @example + * command.inputOptions(['option1', 'option2']); + * + * @method FfmpegCommand#inputOptions + * @category Custom options + * @aliases addInputOption,addInputOptions,withInputOption,withInputOptions,inputOption + * + * @param {...String} options option string(s) or string array + * @return FfmpegCommand + */ + proto.addInputOption = + proto.addInputOptions = + proto.withInputOption = + proto.withInputOptions = + proto.inputOption = + proto.inputOptions = function(options) { + if (!this._currentInput) { + throw new Error('No input specified'); + } + + var doSplit = true; + + if (arguments.length > 1) { + options = [].slice.call(arguments); + doSplit = false; + } + + if (!Array.isArray(options)) { + options = [options]; + } + + this._currentInput.options(options.reduce(function(options, option) { + var split = String(option).split(' '); + + if (doSplit && split.length === 2) { + options.push(split[0], split[1]); + } else { + options.push(option); + } + + return options; + }, [])); + return this; + }; + + + /** + * Add custom output option(s) + * + * @example + * command.outputOptions('option1'); + * + * @example + * command.outputOptions('option1', 'option2'); + * + * @example + * command.outputOptions(['option1', 'option2']); + * + * @method FfmpegCommand#outputOptions + * @category Custom options + * @aliases addOutputOption,addOutputOptions,addOption,addOptions,withOutputOption,withOutputOptions,withOption,withOptions,outputOption + * + * @param {...String} options option string(s) or string array + * @return FfmpegCommand + */ + proto.addOutputOption = + proto.addOutputOptions = + proto.addOption = + proto.addOptions = + proto.withOutputOption = + proto.withOutputOptions = + proto.withOption = + proto.withOptions = + proto.outputOption = + proto.outputOptions = function(options) { + var doSplit = true; + + if (arguments.length > 1) { + options = [].slice.call(arguments); + doSplit = false; + } + + if (!Array.isArray(options)) { + options = [options]; + } + + this._currentOutput.options(options.reduce(function(options, option) { + var split = String(option).split(' '); + + if (doSplit && split.length === 2) { + options.push(split[0], split[1]); + } else { + options.push(option); + } + + return options; + }, [])); + return this; + }; + + + /** + * Specify a complex filtergraph + * + * Calling this method will override any previously set filtergraph, but you can set + * as many filters as needed in one call. + * + * @example Overlay an image over a video (using a filtergraph string) + * ffmpeg() + * .input('video.avi') + * .input('image.png') + * .complexFilter('[0:v][1:v]overlay[out]', ['out']); + * + * @example Overlay an image over a video (using a filter array) + * ffmpeg() + * .input('video.avi') + * .input('image.png') + * .complexFilter([{ + * filter: 'overlay', + * inputs: ['0:v', '1:v'], + * outputs: ['out'] + * }], ['out']); + * + * @example Split video into RGB channels and output a 3x1 video with channels side to side + * ffmpeg() + * .input('video.avi') + * .complexFilter([ + * // Duplicate video stream 3 times into streams a, b, and c + * { filter: 'split', options: '3', outputs: ['a', 'b', 'c'] }, + * + * // Create stream 'red' by cancelling green and blue channels from stream 'a' + * { filter: 'lutrgb', options: { g: 0, b: 0 }, inputs: 'a', outputs: 'red' }, + * + * // Create stream 'green' by cancelling red and blue channels from stream 'b' + * { filter: 'lutrgb', options: { r: 0, b: 0 }, inputs: 'b', outputs: 'green' }, + * + * // Create stream 'blue' by cancelling red and green channels from stream 'c' + * { filter: 'lutrgb', options: { r: 0, g: 0 }, inputs: 'c', outputs: 'blue' }, + * + * // Pad stream 'red' to 3x width, keeping the video on the left, and name output 'padded' + * { filter: 'pad', options: { w: 'iw*3', h: 'ih' }, inputs: 'red', outputs: 'padded' }, + * + * // Overlay 'green' onto 'padded', moving it to the center, and name output 'redgreen' + * { filter: 'overlay', options: { x: 'w', y: 0 }, inputs: ['padded', 'green'], outputs: 'redgreen'}, + * + * // Overlay 'blue' onto 'redgreen', moving it to the right + * { filter: 'overlay', options: { x: '2*w', y: 0 }, inputs: ['redgreen', 'blue']}, + * ]); + * + * @method FfmpegCommand#complexFilter + * @category Custom options + * @aliases filterGraph + * + * @param {String|Array} spec filtergraph string or array of filter specification + * objects, each having the following properties: + * @param {String} spec.filter filter name + * @param {String|Array} [spec.inputs] (array of) input stream specifier(s) for the filter, + * defaults to ffmpeg automatically choosing the first unused matching streams + * @param {String|Array} [spec.outputs] (array of) output stream specifier(s) for the filter, + * defaults to ffmpeg automatically assigning the output to the output file + * @param {Object|String|Array} [spec.options] filter options, can be omitted to not set any options + * @param {Array} [map] (array of) stream specifier(s) from the graph to include in + * ffmpeg output, defaults to ffmpeg automatically choosing the first matching streams. + * @return FfmpegCommand + */ + proto.filterGraph = + proto.complexFilter = function(spec, map) { + this._complexFilters.clear(); + + if (!Array.isArray(spec)) { + spec = [spec]; + } + + this._complexFilters('-filter_complex', utils.makeFilterStrings(spec).join(';')); + + if (Array.isArray(map)) { + var self = this; + map.forEach(function(streamSpec) { + self._complexFilters('-map', streamSpec.replace(utils.streamRegexp, '[$1]')); + }); + } else if (typeof map === 'string') { + this._complexFilters('-map', map.replace(utils.streamRegexp, '[$1]')); + } + + return this; + }; +}; diff --git a/server/libs/fluentFfmpeg/options/inputs.js b/server/libs/fluentFfmpeg/options/inputs.js new file mode 100644 index 000000000..804a21a34 --- /dev/null +++ b/server/libs/fluentFfmpeg/options/inputs.js @@ -0,0 +1,178 @@ +/*jshint node:true*/ +'use strict'; + +var utils = require('../utils'); + +/* + *! Input-related methods + */ + +module.exports = function(proto) { + /** + * Add an input to command + * + * Also switches "current input", that is the input that will be affected + * by subsequent input-related methods. + * + * Note: only one stream input is supported for now. + * + * @method FfmpegCommand#input + * @category Input + * @aliases mergeAdd,addInput + * + * @param {String|Readable} source input file path or readable stream + * @return FfmpegCommand + */ + proto.mergeAdd = + proto.addInput = + proto.input = function(source) { + var isFile = false; + var isStream = false; + + if (typeof source !== 'string') { + if (!('readable' in source) || !(source.readable)) { + throw new Error('Invalid input'); + } + + var hasInputStream = this._inputs.some(function(input) { + return input.isStream; + }); + + if (hasInputStream) { + throw new Error('Only one input stream is supported'); + } + + isStream = true; + source.pause(); + } else { + var protocol = source.match(/^([a-z]{2,}):/i); + isFile = !protocol || protocol[0] === 'file'; + } + + this._inputs.push(this._currentInput = { + source: source, + isFile: isFile, + isStream: isStream, + options: utils.args() + }); + + return this; + }; + + + /** + * Specify input format for the last specified input + * + * @method FfmpegCommand#inputFormat + * @category Input + * @aliases withInputFormat,fromFormat + * + * @param {String} format input format + * @return FfmpegCommand + */ + proto.withInputFormat = + proto.inputFormat = + proto.fromFormat = function(format) { + if (!this._currentInput) { + throw new Error('No input specified'); + } + + this._currentInput.options('-f', format); + return this; + }; + + + /** + * Specify input FPS for the last specified input + * (only valid for raw video formats) + * + * @method FfmpegCommand#inputFps + * @category Input + * @aliases withInputFps,withInputFPS,withFpsInput,withFPSInput,inputFPS,inputFps,fpsInput + * + * @param {Number} fps input FPS + * @return FfmpegCommand + */ + proto.withInputFps = + proto.withInputFPS = + proto.withFpsInput = + proto.withFPSInput = + proto.inputFPS = + proto.inputFps = + proto.fpsInput = + proto.FPSInput = function(fps) { + if (!this._currentInput) { + throw new Error('No input specified'); + } + + this._currentInput.options('-r', fps); + return this; + }; + + + /** + * Use native framerate for the last specified input + * + * @method FfmpegCommand#native + * @category Input + * @aliases nativeFramerate,withNativeFramerate + * + * @return FfmmegCommand + */ + proto.nativeFramerate = + proto.withNativeFramerate = + proto.native = function() { + if (!this._currentInput) { + throw new Error('No input specified'); + } + + this._currentInput.options('-re'); + return this; + }; + + + /** + * Specify input seek time for the last specified input + * + * @method FfmpegCommand#seekInput + * @category Input + * @aliases setStartTime,seekTo + * + * @param {String|Number} seek seek time in seconds or as a '[hh:[mm:]]ss[.xxx]' string + * @return FfmpegCommand + */ + proto.setStartTime = + proto.seekInput = function(seek) { + if (!this._currentInput) { + throw new Error('No input specified'); + } + + this._currentInput.options('-ss', seek); + + return this; + }; + + + /** + * Loop over the last specified input + * + * @method FfmpegCommand#loop + * @category Input + * + * @param {String|Number} [duration] loop duration in seconds or as a '[[hh:]mm:]ss[.xxx]' string + * @return FfmpegCommand + */ + proto.loop = function(duration) { + if (!this._currentInput) { + throw new Error('No input specified'); + } + + this._currentInput.options('-loop', '1'); + + if (typeof duration !== 'undefined') { + this.duration(duration); + } + + return this; + }; +}; diff --git a/server/libs/fluentFfmpeg/options/misc.js b/server/libs/fluentFfmpeg/options/misc.js new file mode 100644 index 000000000..a92f7aab6 --- /dev/null +++ b/server/libs/fluentFfmpeg/options/misc.js @@ -0,0 +1,41 @@ +/*jshint node:true*/ +'use strict'; + +var path = require('path'); + +/* + *! Miscellaneous methods + */ + +module.exports = function(proto) { + /** + * Use preset + * + * @method FfmpegCommand#preset + * @category Miscellaneous + * @aliases usingPreset + * + * @param {String|Function} preset preset name or preset function + */ + proto.usingPreset = + proto.preset = function(preset) { + if (typeof preset === 'function') { + preset(this); + } else { + try { + var modulePath = path.join(this.options.presets, preset); + var module = require(modulePath); + + if (typeof module.load === 'function') { + module.load(this); + } else { + throw new Error('preset ' + modulePath + ' has no load() function'); + } + } catch (err) { + throw new Error('preset ' + modulePath + ' could not be loaded: ' + err.message); + } + } + + return this; + }; +}; diff --git a/server/libs/fluentFfmpeg/options/output.js b/server/libs/fluentFfmpeg/options/output.js new file mode 100644 index 000000000..da4f7711c --- /dev/null +++ b/server/libs/fluentFfmpeg/options/output.js @@ -0,0 +1,162 @@ +/*jshint node:true*/ +'use strict'; + +var utils = require('../utils'); + + +/* + *! Output-related methods + */ + +module.exports = function(proto) { + /** + * Add output + * + * @method FfmpegCommand#output + * @category Output + * @aliases addOutput + * + * @param {String|Writable} target target file path or writable stream + * @param {Object} [pipeopts={}] pipe options (only applies to streams) + * @return FfmpegCommand + */ + proto.addOutput = + proto.output = function(target, pipeopts) { + var isFile = false; + + if (!target && this._currentOutput) { + // No target is only allowed when called from constructor + throw new Error('Invalid output'); + } + + if (target && typeof target !== 'string') { + if (!('writable' in target) || !(target.writable)) { + throw new Error('Invalid output'); + } + } else if (typeof target === 'string') { + var protocol = target.match(/^([a-z]{2,}):/i); + isFile = !protocol || protocol[0] === 'file'; + } + + if (target && !('target' in this._currentOutput)) { + // For backwards compatibility, set target for first output + this._currentOutput.target = target; + this._currentOutput.isFile = isFile; + this._currentOutput.pipeopts = pipeopts || {}; + } else { + if (target && typeof target !== 'string') { + var hasOutputStream = this._outputs.some(function(output) { + return typeof output.target !== 'string'; + }); + + if (hasOutputStream) { + throw new Error('Only one output stream is supported'); + } + } + + this._outputs.push(this._currentOutput = { + target: target, + isFile: isFile, + flags: {}, + pipeopts: pipeopts || {} + }); + + var self = this; + ['audio', 'audioFilters', 'video', 'videoFilters', 'sizeFilters', 'options'].forEach(function(key) { + self._currentOutput[key] = utils.args(); + }); + + if (!target) { + // Call from constructor: remove target key + delete this._currentOutput.target; + } + } + + return this; + }; + + + /** + * Specify output seek time + * + * @method FfmpegCommand#seek + * @category Input + * @aliases seekOutput + * + * @param {String|Number} seek seek time in seconds or as a '[hh:[mm:]]ss[.xxx]' string + * @return FfmpegCommand + */ + proto.seekOutput = + proto.seek = function(seek) { + this._currentOutput.options('-ss', seek); + return this; + }; + + + /** + * Set output duration + * + * @method FfmpegCommand#duration + * @category Output + * @aliases withDuration,setDuration + * + * @param {String|Number} duration duration in seconds or as a '[[hh:]mm:]ss[.xxx]' string + * @return FfmpegCommand + */ + proto.withDuration = + proto.setDuration = + proto.duration = function(duration) { + this._currentOutput.options('-t', duration); + return this; + }; + + + /** + * Set output format + * + * @method FfmpegCommand#format + * @category Output + * @aliases toFormat,withOutputFormat,outputFormat + * + * @param {String} format output format name + * @return FfmpegCommand + */ + proto.toFormat = + proto.withOutputFormat = + proto.outputFormat = + proto.format = function(format) { + this._currentOutput.options('-f', format); + return this; + }; + + + /** + * Add stream mapping to output + * + * @method FfmpegCommand#map + * @category Output + * + * @param {String} spec stream specification string, with optional square brackets + * @return FfmpegCommand + */ + proto.map = function(spec) { + this._currentOutput.options('-map', spec.replace(utils.streamRegexp, '[$1]')); + return this; + }; + + + /** + * Run flvtool2/flvmeta on output + * + * @method FfmpegCommand#flvmeta + * @category Output + * @aliases updateFlvMetadata + * + * @return FfmpegCommand + */ + proto.updateFlvMetadata = + proto.flvmeta = function() { + this._currentOutput.flags.flvmeta = true; + return this; + }; +}; diff --git a/server/libs/fluentFfmpeg/options/video.js b/server/libs/fluentFfmpeg/options/video.js new file mode 100644 index 000000000..bb13c6648 --- /dev/null +++ b/server/libs/fluentFfmpeg/options/video.js @@ -0,0 +1,184 @@ +/*jshint node:true*/ +'use strict'; + +var utils = require('../utils'); + + +/* + *! Video-related methods + */ + +module.exports = function(proto) { + /** + * Disable video in the output + * + * @method FfmpegCommand#noVideo + * @category Video + * @aliases withNoVideo + * + * @return FfmpegCommand + */ + proto.withNoVideo = + proto.noVideo = function() { + this._currentOutput.video.clear(); + this._currentOutput.videoFilters.clear(); + this._currentOutput.video('-vn'); + + return this; + }; + + + /** + * Specify video codec + * + * @method FfmpegCommand#videoCodec + * @category Video + * @aliases withVideoCodec + * + * @param {String} codec video codec name + * @return FfmpegCommand + */ + proto.withVideoCodec = + proto.videoCodec = function(codec) { + this._currentOutput.video('-vcodec', codec); + return this; + }; + + + /** + * Specify video bitrate + * + * @method FfmpegCommand#videoBitrate + * @category Video + * @aliases withVideoBitrate + * + * @param {String|Number} bitrate video bitrate in kbps (with an optional 'k' suffix) + * @param {Boolean} [constant=false] enforce constant bitrate + * @return FfmpegCommand + */ + proto.withVideoBitrate = + proto.videoBitrate = function(bitrate, constant) { + bitrate = ('' + bitrate).replace(/k?$/, 'k'); + + this._currentOutput.video('-b:v', bitrate); + if (constant) { + this._currentOutput.video( + '-maxrate', bitrate, + '-minrate', bitrate, + '-bufsize', '3M' + ); + } + + return this; + }; + + + /** + * Specify custom video filter(s) + * + * Can be called both with one or many filters, or a filter array. + * + * @example + * command.videoFilters('filter1'); + * + * @example + * command.videoFilters('filter1', 'filter2=param1=value1:param2=value2'); + * + * @example + * command.videoFilters(['filter1', 'filter2']); + * + * @example + * command.videoFilters([ + * { + * filter: 'filter1' + * }, + * { + * filter: 'filter2', + * options: 'param=value:param=value' + * } + * ]); + * + * @example + * command.videoFilters( + * { + * filter: 'filter1', + * options: ['value1', 'value2'] + * }, + * { + * filter: 'filter2', + * options: { param1: 'value1', param2: 'value2' } + * } + * ); + * + * @method FfmpegCommand#videoFilters + * @category Video + * @aliases withVideoFilter,withVideoFilters,videoFilter + * + * @param {...String|String[]|Object[]} filters video filter strings, string array or + * filter specification array, each with the following properties: + * @param {String} filters.filter filter name + * @param {String|String[]|Object} [filters.options] filter option string, array, or object + * @return FfmpegCommand + */ + proto.withVideoFilter = + proto.withVideoFilters = + proto.videoFilter = + proto.videoFilters = function(filters) { + if (arguments.length > 1) { + filters = [].slice.call(arguments); + } + + if (!Array.isArray(filters)) { + filters = [filters]; + } + + this._currentOutput.videoFilters(utils.makeFilterStrings(filters)); + + return this; + }; + + + /** + * Specify output FPS + * + * @method FfmpegCommand#fps + * @category Video + * @aliases withOutputFps,withOutputFPS,withFpsOutput,withFPSOutput,withFps,withFPS,outputFPS,outputFps,fpsOutput,FPSOutput,FPS + * + * @param {Number} fps output FPS + * @return FfmpegCommand + */ + proto.withOutputFps = + proto.withOutputFPS = + proto.withFpsOutput = + proto.withFPSOutput = + proto.withFps = + proto.withFPS = + proto.outputFPS = + proto.outputFps = + proto.fpsOutput = + proto.FPSOutput = + proto.fps = + proto.FPS = function(fps) { + this._currentOutput.video('-r', fps); + return this; + }; + + + /** + * Only transcode a certain number of frames + * + * @method FfmpegCommand#frames + * @category Video + * @aliases takeFrames,withFrames + * + * @param {Number} frames frame count + * @return FfmpegCommand + */ + proto.takeFrames = + proto.withFrames = + proto.frames = function(frames) { + this._currentOutput.video('-vframes', frames); + return this; + }; +}; diff --git a/server/libs/fluentFfmpeg/options/videosize.js b/server/libs/fluentFfmpeg/options/videosize.js new file mode 100644 index 000000000..b175dcd47 --- /dev/null +++ b/server/libs/fluentFfmpeg/options/videosize.js @@ -0,0 +1,291 @@ +/*jshint node:true*/ +'use strict'; + +/* + *! Size helpers + */ + + +/** + * Return filters to pad video to width*height, + * + * @param {Number} width output width + * @param {Number} height output height + * @param {Number} aspect video aspect ratio (without padding) + * @param {Number} color padding color + * @return scale/pad filters + * @private + */ +function getScalePadFilters(width, height, aspect, color) { + /* + let a be the input aspect ratio, A be the requested aspect ratio + + if a > A, padding is done on top and bottom + if a < A, padding is done on left and right + */ + + return [ + /* + In both cases, we first have to scale the input to match the requested size. + When using computed width/height, we truncate them to multiples of 2 + */ + { + filter: 'scale', + options: { + w: 'if(gt(a,' + aspect + '),' + width + ',trunc(' + height + '*a/2)*2)', + h: 'if(lt(a,' + aspect + '),' + height + ',trunc(' + width + '/a/2)*2)' + } + }, + + /* + Then we pad the scaled input to match the target size + (here iw and ih refer to the padding input, i.e the scaled output) + */ + + { + filter: 'pad', + options: { + w: width, + h: height, + x: 'if(gt(a,' + aspect + '),0,(' + width + '-iw)/2)', + y: 'if(lt(a,' + aspect + '),0,(' + height + '-ih)/2)', + color: color + } + } + ]; +} + + +/** + * Recompute size filters + * + * @param {Object} output + * @param {String} key newly-added parameter name ('size', 'aspect' or 'pad') + * @param {String} value newly-added parameter value + * @return filter string array + * @private + */ +function createSizeFilters(output, key, value) { + // Store parameters + var data = output.sizeData = output.sizeData || {}; + data[key] = value; + + if (!('size' in data)) { + // No size requested, keep original size + return []; + } + + // Try to match the different size string formats + var fixedSize = data.size.match(/([0-9]+)x([0-9]+)/); + var fixedWidth = data.size.match(/([0-9]+)x\?/); + var fixedHeight = data.size.match(/\?x([0-9]+)/); + var percentRatio = data.size.match(/\b([0-9]{1,3})%/); + var width, height, aspect; + + if (percentRatio) { + var ratio = Number(percentRatio[1]) / 100; + return [{ + filter: 'scale', + options: { + w: 'trunc(iw*' + ratio + '/2)*2', + h: 'trunc(ih*' + ratio + '/2)*2' + } + }]; + } else if (fixedSize) { + // Round target size to multiples of 2 + width = Math.round(Number(fixedSize[1]) / 2) * 2; + height = Math.round(Number(fixedSize[2]) / 2) * 2; + + aspect = width / height; + + if (data.pad) { + return getScalePadFilters(width, height, aspect, data.pad); + } else { + // No autopad requested, rescale to target size + return [{ filter: 'scale', options: { w: width, h: height }}]; + } + } else if (fixedWidth || fixedHeight) { + if ('aspect' in data) { + // Specified aspect ratio + width = fixedWidth ? fixedWidth[1] : Math.round(Number(fixedHeight[1]) * data.aspect); + height = fixedHeight ? fixedHeight[1] : Math.round(Number(fixedWidth[1]) / data.aspect); + + // Round to multiples of 2 + width = Math.round(width / 2) * 2; + height = Math.round(height / 2) * 2; + + if (data.pad) { + return getScalePadFilters(width, height, data.aspect, data.pad); + } else { + // No autopad requested, rescale to target size + return [{ filter: 'scale', options: { w: width, h: height }}]; + } + } else { + // Keep input aspect ratio + + if (fixedWidth) { + return [{ + filter: 'scale', + options: { + w: Math.round(Number(fixedWidth[1]) / 2) * 2, + h: 'trunc(ow/a/2)*2' + } + }]; + } else { + return [{ + filter: 'scale', + options: { + w: 'trunc(oh*a/2)*2', + h: Math.round(Number(fixedHeight[1]) / 2) * 2 + } + }]; + } + } + } else { + throw new Error('Invalid size specified: ' + data.size); + } +} + + +/* + *! Video size-related methods + */ + +module.exports = function(proto) { + /** + * Keep display aspect ratio + * + * This method is useful when converting an input with non-square pixels to an output format + * that does not support non-square pixels. It rescales the input so that the display aspect + * ratio is the same. + * + * @method FfmpegCommand#keepDAR + * @category Video size + * @aliases keepPixelAspect,keepDisplayAspect,keepDisplayAspectRatio + * + * @return FfmpegCommand + */ + proto.keepPixelAspect = // Only for compatibility, this is not about keeping _pixel_ aspect ratio + proto.keepDisplayAspect = + proto.keepDisplayAspectRatio = + proto.keepDAR = function() { + return this.videoFilters([ + { + filter: 'scale', + options: { + w: 'if(gt(sar,1),iw*sar,iw)', + h: 'if(lt(sar,1),ih/sar,ih)' + } + }, + { + filter: 'setsar', + options: '1' + } + ]); + }; + + + /** + * Set output size + * + * The 'size' parameter can have one of 4 forms: + * - 'X%': rescale to xx % of the original size + * - 'WxH': specify width and height + * - 'Wx?': specify width and compute height from input aspect ratio + * - '?xH': specify height and compute width from input aspect ratio + * + * Note: both dimensions will be truncated to multiples of 2. + * + * @method FfmpegCommand#size + * @category Video size + * @aliases withSize,setSize + * + * @param {String} size size string, eg. '33%', '320x240', '320x?', '?x240' + * @return FfmpegCommand + */ + proto.withSize = + proto.setSize = + proto.size = function(size) { + var filters = createSizeFilters(this._currentOutput, 'size', size); + + this._currentOutput.sizeFilters.clear(); + this._currentOutput.sizeFilters(filters); + + return this; + }; + + + /** + * Set output aspect ratio + * + * @method FfmpegCommand#aspect + * @category Video size + * @aliases withAspect,withAspectRatio,setAspect,setAspectRatio,aspectRatio + * + * @param {String|Number} aspect aspect ratio (number or 'X:Y' string) + * @return FfmpegCommand + */ + proto.withAspect = + proto.withAspectRatio = + proto.setAspect = + proto.setAspectRatio = + proto.aspect = + proto.aspectRatio = function(aspect) { + var a = Number(aspect); + if (isNaN(a)) { + var match = aspect.match(/^(\d+):(\d+)$/); + if (match) { + a = Number(match[1]) / Number(match[2]); + } else { + throw new Error('Invalid aspect ratio: ' + aspect); + } + } + + var filters = createSizeFilters(this._currentOutput, 'aspect', a); + + this._currentOutput.sizeFilters.clear(); + this._currentOutput.sizeFilters(filters); + + return this; + }; + + + /** + * Enable auto-padding the output + * + * @method FfmpegCommand#autopad + * @category Video size + * @aliases applyAutopadding,applyAutoPadding,applyAutopad,applyAutoPad,withAutopadding,withAutoPadding,withAutopad,withAutoPad,autoPad + * + * @param {Boolean} [pad=true] enable/disable auto-padding + * @param {String} [color='black'] pad color + */ + proto.applyAutopadding = + proto.applyAutoPadding = + proto.applyAutopad = + proto.applyAutoPad = + proto.withAutopadding = + proto.withAutoPadding = + proto.withAutopad = + proto.withAutoPad = + proto.autoPad = + proto.autopad = function(pad, color) { + // Allow autopad(color) + if (typeof pad === 'string') { + color = pad; + pad = true; + } + + // Allow autopad() and autopad(undefined, color) + if (typeof pad === 'undefined') { + pad = true; + } + + var filters = createSizeFilters(this._currentOutput, 'pad', pad ? color || 'black' : false); + + this._currentOutput.sizeFilters.clear(); + this._currentOutput.sizeFilters(filters); + + return this; + }; +}; diff --git a/server/libs/fluentFfmpeg/presets/divx.js b/server/libs/fluentFfmpeg/presets/divx.js new file mode 100644 index 000000000..090571b4f --- /dev/null +++ b/server/libs/fluentFfmpeg/presets/divx.js @@ -0,0 +1,14 @@ +/*jshint node:true */ +'use strict'; + +exports.load = function(ffmpeg) { + ffmpeg + .format('avi') + .videoBitrate('1024k') + .videoCodec('mpeg4') + .size('720x?') + .audioBitrate('128k') + .audioChannels(2) + .audioCodec('libmp3lame') + .outputOptions(['-vtag DIVX']); +}; \ No newline at end of file diff --git a/server/libs/fluentFfmpeg/presets/flashvideo.js b/server/libs/fluentFfmpeg/presets/flashvideo.js new file mode 100644 index 000000000..22aef8e45 --- /dev/null +++ b/server/libs/fluentFfmpeg/presets/flashvideo.js @@ -0,0 +1,16 @@ +/*jshint node:true */ +'use strict'; + +exports.load = function(ffmpeg) { + ffmpeg + .format('flv') + .flvmeta() + .size('320x?') + .videoBitrate('512k') + .videoCodec('libx264') + .fps(24) + .audioBitrate('96k') + .audioCodec('aac') + .audioFrequency(22050) + .audioChannels(2); +}; diff --git a/server/libs/fluentFfmpeg/presets/podcast.js b/server/libs/fluentFfmpeg/presets/podcast.js new file mode 100644 index 000000000..a7a0dc177 --- /dev/null +++ b/server/libs/fluentFfmpeg/presets/podcast.js @@ -0,0 +1,16 @@ +/*jshint node:true */ +'use strict'; + +exports.load = function(ffmpeg) { + ffmpeg + .format('m4v') + .videoBitrate('512k') + .videoCodec('libx264') + .size('320x176') + .audioBitrate('128k') + .audioCodec('aac') + .audioChannels(1) + .outputOptions(['-flags', '+loop', '-cmp', '+chroma', '-partitions','+parti4x4+partp8x8+partb8x8', '-flags2', + '+mixed_refs', '-me_method umh', '-subq 5', '-bufsize 2M', '-rc_eq \'blurCplx^(1-qComp)\'', + '-qcomp 0.6', '-qmin 10', '-qmax 51', '-qdiff 4', '-level 13' ]); +}; diff --git a/server/libs/fluentFfmpeg/processor.js b/server/libs/fluentFfmpeg/processor.js new file mode 100644 index 000000000..a82a25343 --- /dev/null +++ b/server/libs/fluentFfmpeg/processor.js @@ -0,0 +1,660 @@ +/*jshint node:true*/ +'use strict'; + +var spawn = require('child_process').spawn; +var async = require('../async'); +var utils = require('./utils'); + +/* + *! Processor methods + */ + + +/** + * Run ffprobe asynchronously and store data in command + * + * @param {FfmpegCommand} command + * @private + */ +function runFfprobe(command) { + const inputProbeIndex = 0; + if (command._inputs[inputProbeIndex].isStream) { + // Don't probe input streams as this will consume them + return; + } + command.ffprobe(inputProbeIndex, function (err, data) { + command._ffprobeData = data; + }); +} + + +module.exports = function (proto) { + /** + * Emitted just after ffmpeg has been spawned. + * + * @event FfmpegCommand#start + * @param {String} command ffmpeg command line + */ + + /** + * Emitted when ffmpeg reports progress information + * + * @event FfmpegCommand#progress + * @param {Object} progress progress object + * @param {Number} progress.frames number of frames transcoded + * @param {Number} progress.currentFps current processing speed in frames per second + * @param {Number} progress.currentKbps current output generation speed in kilobytes per second + * @param {Number} progress.targetSize current output file size + * @param {String} progress.timemark current video timemark + * @param {Number} [progress.percent] processing progress (may not be available depending on input) + */ + + /** + * Emitted when ffmpeg outputs to stderr + * + * @event FfmpegCommand#stderr + * @param {String} line stderr output line + */ + + /** + * Emitted when ffmpeg reports input codec data + * + * @event FfmpegCommand#codecData + * @param {Object} codecData codec data object + * @param {String} codecData.format input format name + * @param {String} codecData.audio input audio codec name + * @param {String} codecData.audio_details input audio codec parameters + * @param {String} codecData.video input video codec name + * @param {String} codecData.video_details input video codec parameters + */ + + /** + * Emitted when an error happens when preparing or running a command + * + * @event FfmpegCommand#error + * @param {Error} error error object, with optional properties 'inputStreamError' / 'outputStreamError' for errors on their respective streams + * @param {String|null} stdout ffmpeg stdout, unless outputting to a stream + * @param {String|null} stderr ffmpeg stderr + */ + + /** + * Emitted when a command finishes processing + * + * @event FfmpegCommand#end + * @param {Array|String|null} [filenames|stdout] generated filenames when taking screenshots, ffmpeg stdout when not outputting to a stream, null otherwise + * @param {String|null} stderr ffmpeg stderr + */ + + + /** + * Spawn an ffmpeg process + * + * The 'options' argument may contain the following keys: + * - 'niceness': specify process niceness, ignored on Windows (default: 0) + * - `cwd`: change working directory + * - 'captureStdout': capture stdout and pass it to 'endCB' as its 2nd argument (default: false) + * - 'stdoutLines': override command limit (default: use command limit) + * + * The 'processCB' callback, if present, is called as soon as the process is created and + * receives a nodejs ChildProcess object. It may not be called at all if an error happens + * before spawning the process. + * + * The 'endCB' callback is called either when an error occurs or when the ffmpeg process finishes. + * + * @method FfmpegCommand#_spawnFfmpeg + * @param {Array} args ffmpeg command line argument list + * @param {Object} [options] spawn options (see above) + * @param {Function} [processCB] callback called with process object and stdout/stderr ring buffers when process has been created + * @param {Function} endCB callback called with error (if applicable) and stdout/stderr ring buffers when process finished + * @private + */ + proto._spawnFfmpeg = function (args, options, processCB, endCB) { + // Enable omitting options + if (typeof options === 'function') { + endCB = processCB; + processCB = options; + options = {}; + } + + // Enable omitting processCB + if (typeof endCB === 'undefined') { + endCB = processCB; + processCB = function () { }; + } + + var maxLines = 'stdoutLines' in options ? options.stdoutLines : this.options.stdoutLines; + + // Find ffmpeg + this._getFfmpegPath(function (err, command) { + if (err) { + return endCB(err); + } else if (!command || command.length === 0) { + return endCB(new Error('Cannot find ffmpeg')); + } + + // Apply niceness + if (options.niceness && options.niceness !== 0 && !utils.isWindows) { + args.unshift('-n', options.niceness, command); + command = 'nice'; + } + + var stdoutRing = utils.linesRing(maxLines); + var stdoutClosed = false; + + var stderrRing = utils.linesRing(maxLines); + var stderrClosed = false; + + // Spawn process + var ffmpegProc = spawn(command, args, options); + + if (ffmpegProc.stderr) { + ffmpegProc.stderr.setEncoding('utf8'); + } + + ffmpegProc.on('error', function (err) { + endCB(err); + }); + + // Ensure we wait for captured streams to end before calling endCB + var exitError = null; + function handleExit(err) { + if (err) { + exitError = err; + } + + if (processExited && (stdoutClosed || !options.captureStdout) && stderrClosed) { + endCB(exitError, stdoutRing, stderrRing); + } + } + + // Handle process exit + var processExited = false; + ffmpegProc.on('exit', function (code, signal) { + processExited = true; + + if (signal) { + handleExit(new Error('ffmpeg was killed with signal ' + signal)); + } else if (code) { + handleExit(new Error('ffmpeg exited with code ' + code)); + } else { + handleExit(); + } + }); + + // Capture stdout if specified + if (options.captureStdout) { + ffmpegProc.stdout.on('data', function (data) { + stdoutRing.append(data); + }); + + ffmpegProc.stdout.on('close', function () { + stdoutRing.close(); + stdoutClosed = true; + handleExit(); + }); + } + + // Capture stderr if specified + ffmpegProc.stderr.on('data', function (data) { + stderrRing.append(data); + }); + + ffmpegProc.stderr.on('close', function () { + stderrRing.close(); + stderrClosed = true; + handleExit(); + }); + + // Call process callback + processCB(ffmpegProc, stdoutRing, stderrRing); + }); + }; + + + /** + * Build the argument list for an ffmpeg command + * + * @method FfmpegCommand#_getArguments + * @return argument list + * @private + */ + proto._getArguments = function () { + var complexFilters = this._complexFilters.get(); + + var fileOutput = this._outputs.some(function (output) { + return output.isFile; + }); + + return [].concat( + // Inputs and input options + this._inputs.reduce(function (args, input) { + var source = (typeof input.source === 'string') ? input.source : 'pipe:0'; + + // For each input, add input options, then '-i ' + return args.concat( + input.options.get(), + ['-i', source] + ); + }, []), + + // Global options + this._global.get(), + + // Overwrite if we have file outputs + fileOutput ? ['-y'] : [], + + // Complex filters + complexFilters, + + // Outputs, filters and output options + this._outputs.reduce(function (args, output) { + var sizeFilters = utils.makeFilterStrings(output.sizeFilters.get()); + var audioFilters = output.audioFilters.get(); + var videoFilters = output.videoFilters.get().concat(sizeFilters); + var outputArg; + + if (!output.target) { + outputArg = []; + } else if (typeof output.target === 'string') { + outputArg = [output.target]; + } else { + outputArg = ['pipe:1']; + } + + return args.concat( + output.audio.get(), + audioFilters.length ? ['-filter:a', audioFilters.join(',')] : [], + output.video.get(), + videoFilters.length ? ['-filter:v', videoFilters.join(',')] : [], + output.options.get(), + outputArg + ); + }, []) + ); + }; + + + /** + * Prepare execution of an ffmpeg command + * + * Checks prerequisites for the execution of the command (codec/format availability, flvtool...), + * then builds the argument list for ffmpeg and pass them to 'callback'. + * + * @method FfmpegCommand#_prepare + * @param {Function} callback callback with signature (err, args) + * @param {Boolean} [readMetadata=false] read metadata before processing + * @private + */ + proto._prepare = function (callback, readMetadata) { + var self = this; + + async.waterfall([ + // Check codecs and formats + function (cb) { + self._checkCapabilities(cb); + }, + + // Read metadata if required + function (cb) { + if (!readMetadata) { + return cb(); + } + + self.ffprobe(0, function (err, data) { + if (!err) { + self._ffprobeData = data; + } + + cb(); + }); + }, + + // Check for flvtool2/flvmeta if necessary + function (cb) { + var flvmeta = self._outputs.some(function (output) { + // Remove flvmeta flag on non-file output + if (output.flags.flvmeta && !output.isFile) { + self.logger.warn('Updating flv metadata is only supported for files'); + output.flags.flvmeta = false; + } + + return output.flags.flvmeta; + }); + + if (flvmeta) { + self._getFlvtoolPath(function (err) { + cb(err); + }); + } else { + cb(); + } + }, + + // Build argument list + function (cb) { + var args; + try { + args = self._getArguments(); + } catch (e) { + return cb(e); + } + + cb(null, args); + }, + + // Add "-strict experimental" option where needed + function (args, cb) { + self.availableEncoders(function (err, encoders) { + for (var i = 0; i < args.length; i++) { + if (args[i] === '-acodec' || args[i] === '-vcodec') { + i++; + + if ((args[i] in encoders) && encoders[args[i]].experimental) { + args.splice(i + 1, 0, '-strict', 'experimental'); + i += 2; + } + } + } + + cb(null, args); + }); + } + ], callback); + + if (!readMetadata) { + // Read metadata as soon as 'progress' listeners are added + + if (this.listeners('progress').length > 0) { + // Read metadata in parallel + runFfprobe(this); + } else { + // Read metadata as soon as the first 'progress' listener is added + this.once('newListener', function (event) { + if (event === 'progress') { + runFfprobe(this); + } + }); + } + } + }; + + + /** + * Run ffmpeg command + * + * @method FfmpegCommand#run + * @category Processing + * @aliases exec,execute + */ + proto.exec = + proto.execute = + proto.run = function () { + var self = this; + + // Check if at least one output is present + var outputPresent = this._outputs.some(function (output) { + return 'target' in output; + }); + + if (!outputPresent) { + throw new Error('No output specified'); + } + + // Get output stream if any + var outputStream = this._outputs.filter(function (output) { + return typeof output.target !== 'string'; + })[0]; + + // Get input stream if any + var inputStream = this._inputs.filter(function (input) { + return typeof input.source !== 'string'; + })[0]; + + // Ensure we send 'end' or 'error' only once + var ended = false; + function emitEnd(err, stdout, stderr) { + if (!ended) { + ended = true; + + if (err) { + self.emit('error', err, stdout, stderr); + } else { + self.emit('end', stdout, stderr); + } + } + } + + self._prepare(function (err, args) { + if (err) { + return emitEnd(err); + } + + // Run ffmpeg + self._spawnFfmpeg( + args, + { + captureStdout: !outputStream, + niceness: self.options.niceness, + cwd: self.options.cwd, + windowsHide: true + }, + + function processCB(ffmpegProc, stdoutRing, stderrRing) { + self.ffmpegProc = ffmpegProc; + self.emit('start', 'ffmpeg ' + args.join(' ')); + + // Pipe input stream if any + if (inputStream) { + inputStream.source.on('error', function (err) { + var reportingErr = new Error('Input stream error: ' + err.message); + reportingErr.inputStreamError = err; + emitEnd(reportingErr); + ffmpegProc.kill(); + }); + + inputStream.source.resume(); + inputStream.source.pipe(ffmpegProc.stdin); + + // Set stdin error handler on ffmpeg (prevents nodejs catching the error, but + // ffmpeg will fail anyway, so no need to actually handle anything) + ffmpegProc.stdin.on('error', function () { }); + } + + // Setup timeout if requested + if (self.options.timeout) { + self.processTimer = setTimeout(function () { + var msg = 'process ran into a timeout (' + self.options.timeout + 's)'; + + emitEnd(new Error(msg), stdoutRing.get(), stderrRing.get()); + ffmpegProc.kill(); + }, self.options.timeout * 1000); + } + + + if (outputStream) { + // Pipe ffmpeg stdout to output stream + ffmpegProc.stdout.pipe(outputStream.target, outputStream.pipeopts); + + // Handle output stream events + outputStream.target.on('close', function () { + self.logger.debug('Output stream closed, scheduling kill for ffmpeg process'); + + // Don't kill process yet, to give a chance to ffmpeg to + // terminate successfully first This is necessary because + // under load, the process 'exit' event sometimes happens + // after the output stream 'close' event. + setTimeout(function () { + emitEnd(new Error('Output stream closed')); + ffmpegProc.kill(); + }, 20); + }); + + outputStream.target.on('error', function (err) { + self.logger.debug('Output stream error, killing ffmpeg process'); + var reportingErr = new Error('Output stream error: ' + err.message); + reportingErr.outputStreamError = err; + emitEnd(reportingErr, stdoutRing.get(), stderrRing.get()); + ffmpegProc.kill('SIGKILL'); + }); + } + + // Setup stderr handling + if (stderrRing) { + + // 'stderr' event + if (self.listeners('stderr').length) { + stderrRing.callback(function (line) { + self.emit('stderr', line); + }); + } + + // 'codecData' event + if (self.listeners('codecData').length) { + var codecDataSent = false; + var codecObject = {}; + + stderrRing.callback(function (line) { + if (!codecDataSent) + codecDataSent = utils.extractCodecData(self, line, codecObject); + }); + } + + // 'progress' event + if (self.listeners('progress').length) { + stderrRing.callback(function (line) { + utils.extractProgress(self, line); + }); + } + } + }, + + function endCB(err, stdoutRing, stderrRing) { + clearTimeout(self.processTimer); + delete self.ffmpegProc; + + if (err) { + if (err.message.match(/ffmpeg exited with code/)) { + // Add ffmpeg error message + err.message += ': ' + utils.extractError(stderrRing.get()); + } + + emitEnd(err, stdoutRing.get(), stderrRing.get()); + } else { + // Find out which outputs need flv metadata + var flvmeta = self._outputs.filter(function (output) { + return output.flags.flvmeta; + }); + + if (flvmeta.length) { + self._getFlvtoolPath(function (err, flvtool) { + if (err) { + return emitEnd(err); + } + + async.each( + flvmeta, + function (output, cb) { + spawn(flvtool, ['-U', output.target], { windowsHide: true }) + .on('error', function (err) { + cb(new Error('Error running ' + flvtool + ' on ' + output.target + ': ' + err.message)); + }) + .on('exit', function (code, signal) { + if (code !== 0 || signal) { + cb( + new Error(flvtool + ' ' + + (signal ? 'received signal ' + signal + : 'exited with code ' + code)) + + ' when running on ' + output.target + ); + } else { + cb(); + } + }); + }, + function (err) { + if (err) { + emitEnd(err); + } else { + emitEnd(null, stdoutRing.get(), stderrRing.get()); + } + } + ); + }); + } else { + emitEnd(null, stdoutRing.get(), stderrRing.get()); + } + } + } + ); + }); + + return this; + }; + + + /** + * Renice current and/or future ffmpeg processes + * + * Ignored on Windows platforms. + * + * @method FfmpegCommand#renice + * @category Processing + * + * @param {Number} [niceness=0] niceness value between -20 (highest priority) and 20 (lowest priority) + * @return FfmpegCommand + */ + proto.renice = function (niceness) { + if (!utils.isWindows) { + niceness = niceness || 0; + + if (niceness < -20 || niceness > 20) { + this.logger.warn('Invalid niceness value: ' + niceness + ', must be between -20 and 20'); + } + + niceness = Math.min(20, Math.max(-20, niceness)); + this.options.niceness = niceness; + + if (this.ffmpegProc) { + var logger = this.logger; + var pid = this.ffmpegProc.pid; + var renice = spawn('renice', [niceness, '-p', pid], { windowsHide: true }); + + renice.on('error', function (err) { + logger.warn('could not renice process ' + pid + ': ' + err.message); + }); + + renice.on('exit', function (code, signal) { + if (signal) { + logger.warn('could not renice process ' + pid + ': renice was killed by signal ' + signal); + } else if (code) { + logger.warn('could not renice process ' + pid + ': renice exited with ' + code); + } else { + logger.info('successfully reniced process ' + pid + ' to ' + niceness + ' niceness'); + } + }); + } + } + + return this; + }; + + + /** + * Kill current ffmpeg process, if any + * + * @method FfmpegCommand#kill + * @category Processing + * + * @param {String} [signal=SIGKILL] signal name + * @return FfmpegCommand + */ + proto.kill = function (signal) { + if (!this.ffmpegProc) { + this.logger.warn('No running ffmpeg process, cannot send signal'); + } else { + this.ffmpegProc.kill(signal || 'SIGKILL'); + } + + return this; + }; +}; diff --git a/server/libs/fluentFfmpeg/recipes.js b/server/libs/fluentFfmpeg/recipes.js new file mode 100644 index 000000000..930c63284 --- /dev/null +++ b/server/libs/fluentFfmpeg/recipes.js @@ -0,0 +1,456 @@ +/*jshint node:true*/ +'use strict'; + +var fs = require('fs'); +var path = require('path'); +var PassThrough = require('stream').PassThrough; +var async = require('../async'); +var utils = require('./utils'); + + +/* + * Useful recipes for commands + */ + +module.exports = function recipes(proto) { + /** + * Execute ffmpeg command and save output to a file + * + * @method FfmpegCommand#save + * @category Processing + * @aliases saveToFile + * + * @param {String} output file path + * @return FfmpegCommand + */ + proto.saveToFile = + proto.save = function (output) { + this.output(output).run(); + return this; + }; + + + /** + * Execute ffmpeg command and save output to a stream + * + * If 'stream' is not specified, a PassThrough stream is created and returned. + * 'options' will be used when piping ffmpeg output to the output stream + * (@see http://nodejs.org/api/stream.html#stream_readable_pipe_destination_options) + * + * @method FfmpegCommand#pipe + * @category Processing + * @aliases stream,writeToStream + * + * @param {stream.Writable} [stream] output stream + * @param {Object} [options={}] pipe options + * @return Output stream + */ + proto.writeToStream = + proto.pipe = + proto.stream = function (stream, options) { + if (stream && !('writable' in stream)) { + options = stream; + stream = undefined; + } + + if (!stream) { + if (process.version.match(/v0\.8\./)) { + throw new Error('PassThrough stream is not supported on node v0.8'); + } + + stream = new PassThrough(); + } + + this.output(stream, options).run(); + return stream; + }; + + + /** + * Generate images from a video + * + * Note: this method makes the command emit a 'filenames' event with an array of + * the generated image filenames. + * + * @method FfmpegCommand#screenshots + * @category Processing + * @aliases takeScreenshots,thumbnail,thumbnails,screenshot + * + * @param {Number|Object} [config=1] screenshot count or configuration object with + * the following keys: + * @param {Number} [config.count] number of screenshots to take; using this option + * takes screenshots at regular intervals (eg. count=4 would take screens at 20%, 40%, + * 60% and 80% of the video length). + * @param {String} [config.folder='.'] output folder + * @param {String} [config.filename='tn.png'] output filename pattern, may contain the following + * tokens: + * - '%s': offset in seconds + * - '%w': screenshot width + * - '%h': screenshot height + * - '%r': screenshot resolution (same as '%wx%h') + * - '%f': input filename + * - '%b': input basename (filename w/o extension) + * - '%i': index of screenshot in timemark array (can be zero-padded by using it like `%000i`) + * @param {Number[]|String[]} [config.timemarks] array of timemarks to take screenshots + * at; each timemark may be a number of seconds, a '[[hh:]mm:]ss[.xxx]' string or a + * 'XX%' string. Overrides 'count' if present. + * @param {Number[]|String[]} [config.timestamps] alias for 'timemarks' + * @param {Boolean} [config.fastSeek] use fast seek (less accurate) + * @param {String} [config.size] screenshot size, with the same syntax as {@link FfmpegCommand#size} + * @param {String} [folder] output folder (legacy alias for 'config.folder') + * @return FfmpegCommand + */ + proto.takeScreenshots = + proto.thumbnail = + proto.thumbnails = + proto.screenshot = + proto.screenshots = function (config, folder) { + var self = this; + var source = this._currentInput.source; + config = config || { count: 1 }; + + // Accept a number of screenshots instead of a config object + if (typeof config === 'number') { + config = { + count: config + }; + } + + // Accept a second 'folder' parameter instead of config.folder + if (!('folder' in config)) { + config.folder = folder || '.'; + } + + // Accept 'timestamps' instead of 'timemarks' + if ('timestamps' in config) { + config.timemarks = config.timestamps; + } + + // Compute timemarks from count if not present + if (!('timemarks' in config)) { + if (!config.count) { + throw new Error('Cannot take screenshots: neither a count nor a timemark list are specified'); + } + + var interval = 100 / (1 + config.count); + config.timemarks = []; + for (var i = 0; i < config.count; i++) { + config.timemarks.push((interval * (i + 1)) + '%'); + } + } + + // Parse size option + if ('size' in config) { + var fixedSize = config.size.match(/^(\d+)x(\d+)$/); + var fixedWidth = config.size.match(/^(\d+)x\?$/); + var fixedHeight = config.size.match(/^\?x(\d+)$/); + var percentSize = config.size.match(/^(\d+)%$/); + + if (!fixedSize && !fixedWidth && !fixedHeight && !percentSize) { + throw new Error('Invalid size parameter: ' + config.size); + } + } + + // Metadata helper + var metadata; + function getMetadata(cb) { + if (metadata) { + cb(null, metadata); + } else { + self.ffprobe(function (err, meta) { + metadata = meta; + cb(err, meta); + }); + } + } + + async.waterfall([ + // Compute percent timemarks if any + function computeTimemarks(next) { + if (config.timemarks.some(function (t) { return ('' + t).match(/^[\d.]+%$/); })) { + if (typeof source !== 'string') { + return next(new Error('Cannot compute screenshot timemarks with an input stream, please specify fixed timemarks')); + } + + getMetadata(function (err, meta) { + if (err) { + next(err); + } else { + // Select video stream with the highest resolution + var vstream = meta.streams.reduce(function (biggest, stream) { + if (stream.codec_type === 'video' && stream.width * stream.height > biggest.width * biggest.height) { + return stream; + } else { + return biggest; + } + }, { width: 0, height: 0 }); + + if (vstream.width === 0) { + return next(new Error('No video stream in input, cannot take screenshots')); + } + + var duration = Number(vstream.duration); + if (isNaN(duration)) { + duration = Number(meta.format.duration); + } + + if (isNaN(duration)) { + return next(new Error('Could not get input duration, please specify fixed timemarks')); + } + + config.timemarks = config.timemarks.map(function (mark) { + if (('' + mark).match(/^([\d.]+)%$/)) { + return duration * parseFloat(mark) / 100; + } else { + return mark; + } + }); + + next(); + } + }); + } else { + next(); + } + }, + + // Turn all timemarks into numbers and sort them + function normalizeTimemarks(next) { + config.timemarks = config.timemarks.map(function (mark) { + return utils.timemarkToSeconds(mark); + }).sort(function (a, b) { return a - b; }); + + next(); + }, + + // Add '_%i' to pattern when requesting multiple screenshots and no variable token is present + function fixPattern(next) { + var pattern = config.filename || 'tn.png'; + + if (pattern.indexOf('.') === -1) { + pattern += '.png'; + } + + if (config.timemarks.length > 1 && !pattern.match(/%(s|0*i)/)) { + var ext = path.extname(pattern); + pattern = path.join(path.dirname(pattern), path.basename(pattern, ext) + '_%i' + ext); + } + + next(null, pattern); + }, + + // Replace filename tokens (%f, %b) in pattern + function replaceFilenameTokens(pattern, next) { + if (pattern.match(/%[bf]/)) { + if (typeof source !== 'string') { + return next(new Error('Cannot replace %f or %b when using an input stream')); + } + + pattern = pattern + .replace(/%f/g, path.basename(source)) + .replace(/%b/g, path.basename(source, path.extname(source))); + } + + next(null, pattern); + }, + + // Compute size if needed + function getSize(pattern, next) { + if (pattern.match(/%[whr]/)) { + if (fixedSize) { + return next(null, pattern, fixedSize[1], fixedSize[2]); + } + + getMetadata(function (err, meta) { + if (err) { + return next(new Error('Could not determine video resolution to replace %w, %h or %r')); + } + + var vstream = meta.streams.reduce(function (biggest, stream) { + if (stream.codec_type === 'video' && stream.width * stream.height > biggest.width * biggest.height) { + return stream; + } else { + return biggest; + } + }, { width: 0, height: 0 }); + + if (vstream.width === 0) { + return next(new Error('No video stream in input, cannot replace %w, %h or %r')); + } + + var width = vstream.width; + var height = vstream.height; + + if (fixedWidth) { + height = height * Number(fixedWidth[1]) / width; + width = Number(fixedWidth[1]); + } else if (fixedHeight) { + width = width * Number(fixedHeight[1]) / height; + height = Number(fixedHeight[1]); + } else if (percentSize) { + width = width * Number(percentSize[1]) / 100; + height = height * Number(percentSize[1]) / 100; + } + + next(null, pattern, Math.round(width / 2) * 2, Math.round(height / 2) * 2); + }); + } else { + next(null, pattern, -1, -1); + } + }, + + // Replace size tokens (%w, %h, %r) in pattern + function replaceSizeTokens(pattern, width, height, next) { + pattern = pattern + .replace(/%r/g, '%wx%h') + .replace(/%w/g, width) + .replace(/%h/g, height); + + next(null, pattern); + }, + + // Replace variable tokens in pattern (%s, %i) and generate filename list + function replaceVariableTokens(pattern, next) { + var filenames = config.timemarks.map(function (t, i) { + return pattern + .replace(/%s/g, utils.timemarkToSeconds(t)) + .replace(/%(0*)i/g, function (match, padding) { + var idx = '' + (i + 1); + return padding.substr(0, Math.max(0, padding.length + 1 - idx.length)) + idx; + }); + }); + + self.emit('filenames', filenames); + next(null, filenames); + }, + + // Create output directory + function createDirectory(filenames, next) { + fs.exists(config.folder, function (exists) { + if (!exists) { + fs.mkdir(config.folder, function (err) { + if (err) { + next(err); + } else { + next(null, filenames); + } + }); + } else { + next(null, filenames); + } + }); + } + ], function runCommand(err, filenames) { + if (err) { + return self.emit('error', err); + } + + var count = config.timemarks.length; + var split; + var filters = [split = { + filter: 'split', + options: count, + outputs: [] + }]; + + if ('size' in config) { + // Set size to generate size filters + self.size(config.size); + + // Get size filters and chain them with 'sizeN' stream names + var sizeFilters = self._currentOutput.sizeFilters.get().map(function (f, i) { + if (i > 0) { + f.inputs = 'size' + (i - 1); + } + + f.outputs = 'size' + i; + + return f; + }); + + // Input last size filter output into split filter + split.inputs = 'size' + (sizeFilters.length - 1); + + // Add size filters in front of split filter + filters = sizeFilters.concat(filters); + + // Remove size filters + self._currentOutput.sizeFilters.clear(); + } + + var first = 0; + for (var i = 0; i < count; i++) { + var stream = 'screen' + i; + split.outputs.push(stream); + + if (i === 0) { + first = config.timemarks[i]; + self.seekInput(first); + } + + self.output(path.join(config.folder, filenames[i])) + .frames(1) + .map(stream); + + if (i > 0) { + self.seek(config.timemarks[i] - first); + } + } + + self.complexFilter(filters); + self.run(); + }); + + return this; + }; + + + /** + * Merge (concatenate) inputs to a single file + * + * @method FfmpegCommand#concat + * @category Processing + * @aliases concatenate,mergeToFile + * + * @param {String|Writable} target output file or writable stream + * @param {Object} [options] pipe options (only used when outputting to a writable stream) + * @return FfmpegCommand + */ + proto.mergeToFile = + proto.concatenate = + proto.concat = function (target, options) { + // Find out which streams are present in the first non-stream input + var fileInput = this._inputs.filter(function (input) { + return !input.isStream; + })[0]; + + var self = this; + this.ffprobe(this._inputs.indexOf(fileInput), function (err, data) { + if (err) { + return self.emit('error', err); + } + + var hasAudioStreams = data.streams.some(function (stream) { + return stream.codec_type === 'audio'; + }); + + var hasVideoStreams = data.streams.some(function (stream) { + return stream.codec_type === 'video'; + }); + + // Setup concat filter and start processing + self.output(target, options) + .complexFilter({ + filter: 'concat', + options: { + n: self._inputs.length, + v: hasVideoStreams ? 1 : 0, + a: hasAudioStreams ? 1 : 0 + } + }) + .run(); + }); + + return this; + }; +}; diff --git a/server/libs/fluentFfmpeg/utils.js b/server/libs/fluentFfmpeg/utils.js new file mode 100644 index 000000000..6780e4dc3 --- /dev/null +++ b/server/libs/fluentFfmpeg/utils.js @@ -0,0 +1,454 @@ +/*jshint node:true*/ +'use strict'; + +var isWindows = require('os').platform().match(/win(32|64)/); +var which = require('../which'); + +var nlRegexp = /\r\n|\r|\n/g; +var streamRegexp = /^\[?(.*?)\]?$/; +var filterEscapeRegexp = /[,]/; +var whichCache = {}; + +/** + * Parse progress line from ffmpeg stderr + * + * @param {String} line progress line + * @return progress object + * @private + */ +function parseProgressLine(line) { + var progress = {}; + + // Remove all spaces after = and trim + line = line.replace(/=\s+/g, '=').trim(); + var progressParts = line.split(' '); + + // Split every progress part by "=" to get key and value + for (var i = 0; i < progressParts.length; i++) { + var progressSplit = progressParts[i].split('=', 2); + var key = progressSplit[0]; + var value = progressSplit[1]; + + // This is not a progress line + if (typeof value === 'undefined') + return null; + + progress[key] = value; + } + + return progress; +} + + +var utils = module.exports = { + isWindows: isWindows, + streamRegexp: streamRegexp, + + + /** + * Copy an object keys into another one + * + * @param {Object} source source object + * @param {Object} dest destination object + * @private + */ + copy: function (source, dest) { + Object.keys(source).forEach(function (key) { + dest[key] = source[key]; + }); + }, + + + /** + * Create an argument list + * + * Returns a function that adds new arguments to the list. + * It also has the following methods: + * - clear() empties the argument list + * - get() returns the argument list + * - find(arg, count) finds 'arg' in the list and return the following 'count' items, or undefined if not found + * - remove(arg, count) remove 'arg' in the list as well as the following 'count' items + * + * @private + */ + args: function () { + var list = []; + + // Append argument(s) to the list + var argfunc = function () { + if (arguments.length === 1 && Array.isArray(arguments[0])) { + list = list.concat(arguments[0]); + } else { + list = list.concat([].slice.call(arguments)); + } + }; + + // Clear argument list + argfunc.clear = function () { + list = []; + }; + + // Return argument list + argfunc.get = function () { + return list; + }; + + // Find argument 'arg' in list, and if found, return an array of the 'count' items that follow it + argfunc.find = function (arg, count) { + var index = list.indexOf(arg); + if (index !== -1) { + return list.slice(index + 1, index + 1 + (count || 0)); + } + }; + + // Find argument 'arg' in list, and if found, remove it as well as the 'count' items that follow it + argfunc.remove = function (arg, count) { + var index = list.indexOf(arg); + if (index !== -1) { + list.splice(index, (count || 0) + 1); + } + }; + + // Clone argument list + argfunc.clone = function () { + var cloned = utils.args(); + cloned(list); + return cloned; + }; + + return argfunc; + }, + + + /** + * Generate filter strings + * + * @param {String[]|Object[]} filters filter specifications. When using objects, + * each must have the following properties: + * @param {String} filters.filter filter name + * @param {String|Array} [filters.inputs] (array of) input stream specifier(s) for the filter, + * defaults to ffmpeg automatically choosing the first unused matching streams + * @param {String|Array} [filters.outputs] (array of) output stream specifier(s) for the filter, + * defaults to ffmpeg automatically assigning the output to the output file + * @param {Object|String|Array} [filters.options] filter options, can be omitted to not set any options + * @return String[] + * @private + */ + makeFilterStrings: function (filters) { + return filters.map(function (filterSpec) { + if (typeof filterSpec === 'string') { + return filterSpec; + } + + var filterString = ''; + + // Filter string format is: + // [input1][input2]...filter[output1][output2]... + // The 'filter' part can optionaly have arguments: + // filter=arg1:arg2:arg3 + // filter=arg1=v1:arg2=v2:arg3=v3 + + // Add inputs + if (Array.isArray(filterSpec.inputs)) { + filterString += filterSpec.inputs.map(function (streamSpec) { + return streamSpec.replace(streamRegexp, '[$1]'); + }).join(''); + } else if (typeof filterSpec.inputs === 'string') { + filterString += filterSpec.inputs.replace(streamRegexp, '[$1]'); + } + + // Add filter + filterString += filterSpec.filter; + + // Add options + if (filterSpec.options) { + if (typeof filterSpec.options === 'string' || typeof filterSpec.options === 'number') { + // Option string + filterString += '=' + filterSpec.options; + } else if (Array.isArray(filterSpec.options)) { + // Option array (unnamed options) + filterString += '=' + filterSpec.options.map(function (option) { + if (typeof option === 'string' && option.match(filterEscapeRegexp)) { + return '\'' + option + '\''; + } else { + return option; + } + }).join(':'); + } else if (Object.keys(filterSpec.options).length) { + // Option object (named options) + filterString += '=' + Object.keys(filterSpec.options).map(function (option) { + var value = filterSpec.options[option]; + + if (typeof value === 'string' && value.match(filterEscapeRegexp)) { + value = '\'' + value + '\''; + } + + return option + '=' + value; + }).join(':'); + } + } + + // Add outputs + if (Array.isArray(filterSpec.outputs)) { + filterString += filterSpec.outputs.map(function (streamSpec) { + return streamSpec.replace(streamRegexp, '[$1]'); + }).join(''); + } else if (typeof filterSpec.outputs === 'string') { + filterString += filterSpec.outputs.replace(streamRegexp, '[$1]'); + } + + return filterString; + }); + }, + + + /** + * Search for an executable + * + * Uses 'which' or 'where' depending on platform + * + * @param {String} name executable name + * @param {Function} callback callback with signature (err, path) + * @private + */ + which: function (name, callback) { + if (name in whichCache) { + return callback(null, whichCache[name]); + } + + which(name, function (err, result) { + if (err) { + // Treat errors as not found + return callback(null, whichCache[name] = ''); + } + callback(null, whichCache[name] = result); + }); + }, + + + /** + * Convert a [[hh:]mm:]ss[.xxx] timemark into seconds + * + * @param {String} timemark timemark string + * @return Number + * @private + */ + timemarkToSeconds: function (timemark) { + if (typeof timemark === 'number') { + return timemark; + } + + if (timemark.indexOf(':') === -1 && timemark.indexOf('.') >= 0) { + return Number(timemark); + } + + var parts = timemark.split(':'); + + // add seconds + var secs = Number(parts.pop()); + + if (parts.length) { + // add minutes + secs += Number(parts.pop()) * 60; + } + + if (parts.length) { + // add hours + secs += Number(parts.pop()) * 3600; + } + + return secs; + }, + + + /** + * Extract codec data from ffmpeg stderr and emit 'codecData' event if appropriate + * Call it with an initially empty codec object once with each line of stderr output until it returns true + * + * @param {FfmpegCommand} command event emitter + * @param {String} stderrLine ffmpeg stderr output line + * @param {Object} codecObject object used to accumulate codec data between calls + * @return {Boolean} true if codec data is complete (and event was emitted), false otherwise + * @private + */ + extractCodecData: function (command, stderrLine, codecsObject) { + var inputPattern = /Input #[0-9]+, ([^ ]+),/; + var durPattern = /Duration\: ([^,]+)/; + var audioPattern = /Audio\: (.*)/; + var videoPattern = /Video\: (.*)/; + + if (!('inputStack' in codecsObject)) { + codecsObject.inputStack = []; + codecsObject.inputIndex = -1; + codecsObject.inInput = false; + } + + var inputStack = codecsObject.inputStack; + var inputIndex = codecsObject.inputIndex; + var inInput = codecsObject.inInput; + + var format, dur, audio, video; + + if (format = stderrLine.match(inputPattern)) { + inInput = codecsObject.inInput = true; + inputIndex = codecsObject.inputIndex = codecsObject.inputIndex + 1; + + inputStack[inputIndex] = { format: format[1], audio: '', video: '', duration: '' }; + } else if (inInput && (dur = stderrLine.match(durPattern))) { + inputStack[inputIndex].duration = dur[1]; + } else if (inInput && (audio = stderrLine.match(audioPattern))) { + audio = audio[1].split(', '); + inputStack[inputIndex].audio = audio[0]; + inputStack[inputIndex].audio_details = audio; + } else if (inInput && (video = stderrLine.match(videoPattern))) { + video = video[1].split(', '); + inputStack[inputIndex].video = video[0]; + inputStack[inputIndex].video_details = video; + } else if (/Output #\d+/.test(stderrLine)) { + inInput = codecsObject.inInput = false; + } else if (/Stream mapping:|Press (\[q\]|ctrl-c) to stop/.test(stderrLine)) { + command.emit.apply(command, ['codecData'].concat(inputStack)); + return true; + } + + return false; + }, + + + /** + * Extract progress data from ffmpeg stderr and emit 'progress' event if appropriate + * + * @param {FfmpegCommand} command event emitter + * @param {String} stderrLine ffmpeg stderr data + * @private + */ + extractProgress: function (command, stderrLine) { + var progress = parseProgressLine(stderrLine); + + if (progress) { + // build progress report object + var ret = { + frames: parseInt(progress.frame, 10), + currentFps: parseInt(progress.fps, 10), + currentKbps: progress.bitrate ? parseFloat(progress.bitrate.replace('kbits/s', '')) : 0, + targetSize: parseInt(progress.size || progress.Lsize, 10), + timemark: progress.time + }; + + // calculate percent progress using duration + if (command._ffprobeData && command._ffprobeData.format && command._ffprobeData.format.duration) { + var duration = Number(command._ffprobeData.format.duration); + if (!isNaN(duration)) + ret.percent = (utils.timemarkToSeconds(ret.timemark) / duration) * 100; + } + command.emit('progress', ret); + } + }, + + + /** + * Extract error message(s) from ffmpeg stderr + * + * @param {String} stderr ffmpeg stderr data + * @return {String} + * @private + */ + extractError: function (stderr) { + // Only return the last stderr lines that don't start with a space or a square bracket + return stderr.split(nlRegexp).reduce(function (messages, message) { + if (message.charAt(0) === ' ' || message.charAt(0) === '[') { + return []; + } else { + messages.push(message); + return messages; + } + }, []).join('\n'); + }, + + + /** + * Creates a line ring buffer object with the following methods: + * - append(str) : appends a string or buffer + * - get() : returns the whole string + * - close() : prevents further append() calls and does a last call to callbacks + * - callback(cb) : calls cb for each line (incl. those already in the ring) + * + * @param {Numebr} maxLines maximum number of lines to store (<= 0 for unlimited) + */ + linesRing: function (maxLines) { + var cbs = []; + var lines = []; + var current = null; + var closed = false + var max = maxLines - 1; + + function emit(line) { + cbs.forEach(function (cb) { cb(line); }); + } + + return { + callback: function (cb) { + lines.forEach(function (l) { cb(l); }); + cbs.push(cb); + }, + + append: function (str) { + if (closed) return; + if (str instanceof Buffer) str = '' + str; + if (!str || str.length === 0) return; + + var newLines = str.split(nlRegexp); + + if (newLines.length === 1) { + if (current !== null) { + current = current + newLines.shift(); + } else { + current = newLines.shift(); + } + } else { + if (current !== null) { + current = current + newLines.shift(); + emit(current); + lines.push(current); + } + + current = newLines.pop(); + + newLines.forEach(function (l) { + emit(l); + lines.push(l); + }); + + if (max > -1 && lines.length > max) { + lines.splice(0, lines.length - max); + } + } + }, + + get: function () { + if (current !== null) { + return lines.concat([current]).join('\n'); + } else { + return lines.join('\n'); + } + }, + + close: function () { + if (closed) return; + + if (current !== null) { + emit(current); + lines.push(current); + + if (max > -1 && lines.length > max) { + lines.shift(); + } + + current = null; + } + + closed = true; + } + }; + } +}; diff --git a/server/libs/isexe/LICENSE b/server/libs/isexe/LICENSE new file mode 100644 index 000000000..a40af471f --- /dev/null +++ b/server/libs/isexe/LICENSE @@ -0,0 +1,15 @@ +The ISC License + +Copyright (c) 2016-2022 Isaac Z. Schlueter and Contributors + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR +IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. \ No newline at end of file diff --git a/server/libs/isexe/index.js b/server/libs/isexe/index.js new file mode 100644 index 000000000..8f82c3576 --- /dev/null +++ b/server/libs/isexe/index.js @@ -0,0 +1,61 @@ +// +// used by async +// SOURCE: https://github.com/isaacs/isexe +// + +var core +if (process.platform === 'win32' || global.TESTING_WINDOWS) { + core = require('./windows.js') +} else { + core = require('./mode.js') +} + +module.exports = isexe +isexe.sync = sync + +function isexe(path, options, cb) { + if (typeof options === 'function') { + cb = options + options = {} + } + + if (!cb) { + if (typeof Promise !== 'function') { + throw new TypeError('callback not provided') + } + + return new Promise(function (resolve, reject) { + isexe(path, options || {}, function (er, is) { + if (er) { + reject(er) + } else { + resolve(is) + } + }) + }) + } + + core(path, options || {}, function (er, is) { + // ignore EACCES because that just means we aren't allowed to run it + if (er) { + if (er.code === 'EACCES' || options && options.ignoreErrors) { + er = null + is = false + } + } + cb(er, is) + }) +} + +function sync(path, options) { + // my kingdom for a filtered catch + try { + return core.sync(path, options || {}) + } catch (er) { + if (options && options.ignoreErrors || er.code === 'EACCES') { + return false + } else { + throw er + } + } +} \ No newline at end of file diff --git a/server/libs/isexe/mode.js b/server/libs/isexe/mode.js new file mode 100644 index 000000000..1caaaabe0 --- /dev/null +++ b/server/libs/isexe/mode.js @@ -0,0 +1,41 @@ +module.exports = isexe +isexe.sync = sync + +var fs = require('fs') + +function isexe(path, options, cb) { + fs.stat(path, function (er, stat) { + cb(er, er ? false : checkStat(stat, options)) + }) +} + +function sync(path, options) { + return checkStat(fs.statSync(path), options) +} + +function checkStat(stat, options) { + return stat.isFile() && checkMode(stat, options) +} + +function checkMode(stat, options) { + var mod = stat.mode + var uid = stat.uid + var gid = stat.gid + + var myUid = options.uid !== undefined ? + options.uid : process.getuid && process.getuid() + var myGid = options.gid !== undefined ? + options.gid : process.getgid && process.getgid() + + var u = parseInt('100', 8) + var g = parseInt('010', 8) + var o = parseInt('001', 8) + var ug = u | g + + var ret = (mod & o) || + (mod & g) && gid === myGid || + (mod & u) && uid === myUid || + (mod & ug) && myUid === 0 + + return ret +} \ No newline at end of file diff --git a/server/libs/isexe/windows.js b/server/libs/isexe/windows.js new file mode 100644 index 000000000..2ee6f103e --- /dev/null +++ b/server/libs/isexe/windows.js @@ -0,0 +1,42 @@ +module.exports = isexe +isexe.sync = sync + +var fs = require('fs') + +function checkPathExt(path, options) { + var pathext = options.pathExt !== undefined ? + options.pathExt : process.env.PATHEXT + + if (!pathext) { + return true + } + + pathext = pathext.split(';') + if (pathext.indexOf('') !== -1) { + return true + } + for (var i = 0; i < pathext.length; i++) { + var p = pathext[i].toLowerCase() + if (p && path.substr(-p.length).toLowerCase() === p) { + return true + } + } + return false +} + +function checkStat(stat, path, options) { + if (!stat.isSymbolicLink() && !stat.isFile()) { + return false + } + return checkPathExt(path, options) +} + +function isexe(path, options, cb) { + fs.stat(path, function (er, stat) { + cb(er, er ? false : checkStat(stat, path, options)) + }) +} + +function sync(path, options) { + return checkStat(fs.statSync(path), path, options) +} \ No newline at end of file diff --git a/server/libs/properLockfile/index.js b/server/libs/properLockfile/index.js index 68cbba185..29a5da9e3 100644 --- a/server/libs/properLockfile/index.js +++ b/server/libs/properLockfile/index.js @@ -1,5 +1,11 @@ 'use strict'; +// +// used by njodb +// Source: https://github.com/moxystudio/node-proper-lockfile +// + + const lockfile = require('./lib/lockfile'); const { toPromise, toSync, toSyncOptions } = require('./lib/adapter'); diff --git a/server/libs/retry/index.js b/server/libs/retry/index.js index dcb576807..874cfc072 100644 --- a/server/libs/retry/index.js +++ b/server/libs/retry/index.js @@ -1,15 +1,20 @@ +// +// used by properLockFile +// Source: https://github.com/tim-kos/node-retry +// + var RetryOperation = require('./retry_operation'); -exports.operation = function(options) { +exports.operation = function (options) { var timeouts = exports.timeouts(options); return new RetryOperation(timeouts, { - forever: options && options.forever, - unref: options && options.unref, - maxRetryTime: options && options.maxRetryTime + forever: options && options.forever, + unref: options && options.unref, + maxRetryTime: options && options.maxRetryTime }); }; -exports.timeouts = function(options) { +exports.timeouts = function (options) { if (options instanceof Array) { return [].concat(options); } @@ -39,14 +44,14 @@ exports.timeouts = function(options) { } // sort the array numerically ascending - timeouts.sort(function(a,b) { + timeouts.sort(function (a, b) { return a - b; }); return timeouts; }; -exports.createTimeout = function(attempt, opts) { +exports.createTimeout = function (attempt, opts) { var random = (opts.randomize) ? (Math.random() + 1) : 1; @@ -57,7 +62,7 @@ exports.createTimeout = function(attempt, opts) { return timeout; }; -exports.wrap = function(obj, options, methods) { +exports.wrap = function (obj, options, methods) { if (options instanceof Array) { methods = options; options = null; @@ -73,15 +78,15 @@ exports.wrap = function(obj, options, methods) { } for (var i = 0; i < methods.length; i++) { - var method = methods[i]; + var method = methods[i]; var original = obj[method]; obj[method] = function retryWrapper(original) { - var op = exports.operation(options); - var args = Array.prototype.slice.call(arguments, 1); + var op = exports.operation(options); + var args = Array.prototype.slice.call(arguments, 1); var callback = args.pop(); - args.push(function(err) { + args.push(function (err) { if (op.retry(err)) { return; } @@ -91,7 +96,7 @@ exports.wrap = function(obj, options, methods) { callback.apply(this, arguments); }); - op.attempt(function() { + op.attempt(function () { original.apply(obj, args); }); }.bind(obj, original); diff --git a/server/libs/rss/index.js b/server/libs/rss/index.js index 09c059682..1fb811f45 100644 --- a/server/libs/rss/index.js +++ b/server/libs/rss/index.js @@ -37,7 +37,7 @@ function generateXML(data) { var channel = []; channel.push({ title: { _cdata: data.title } }); channel.push({ description: { _cdata: data.description || data.title } }); - channel.push({ link: data.site_url || 'http://github.com/dylang/node-rss' }); + channel.push({ link: data.site_url || 'https://github.com/advplyr/audiobookshelf' }); // image_url set? if (data.image_url) { channel.push({ image: [{ url: data.image_url }, { title: data.title }, { link: data.site_url }] }); diff --git a/server/libs/signalExit/index.js b/server/libs/signalExit/index.js index 93703f369..41c3569ce 100644 --- a/server/libs/signalExit/index.js +++ b/server/libs/signalExit/index.js @@ -1,3 +1,8 @@ +// +// used by properLockFile +// Source: https://github.com/tapjs/signal-exit +// + // Note: since nyc uses this module to output coverage, any lines // that are in the direct sync flow of nyc's outputCoverage are // ignored, since we can never get coverage for them. @@ -20,7 +25,7 @@ const processOk = function (process) { /* istanbul ignore if */ if (!processOk(process)) { module.exports = function () { - return function () {} + return function () { } } } else { var assert = require('assert') @@ -54,7 +59,7 @@ if (!processOk(process)) { module.exports = function (cb, opts) { /* istanbul ignore if */ if (!processOk(global.process)) { - return function () {} + return function () { } } assert.equal(typeof cb, 'function', 'a callback must be provided for exit handler') @@ -70,7 +75,7 @@ if (!processOk(process)) { var remove = function () { emitter.removeListener(ev, cb) if (emitter.listeners('exit').length === 0 && - emitter.listeners('afterexit').length === 0) { + emitter.listeners('afterexit').length === 0) { unload() } } @@ -79,7 +84,7 @@ if (!processOk(process)) { return remove } - var unload = function unload () { + var unload = function unload() { if (!loaded || !processOk(global.process)) { return } @@ -88,7 +93,7 @@ if (!processOk(process)) { signals.forEach(function (sig) { try { process.removeListener(sig, sigListeners[sig]) - } catch (er) {} + } catch (er) { } }) process.emit = originalProcessEmit process.reallyExit = originalProcessReallyExit @@ -96,7 +101,7 @@ if (!processOk(process)) { } module.exports.unload = unload - var emit = function emit (event, code, signal) { + var emit = function emit(event, code, signal) { /* istanbul ignore if */ if (emitter.emitted[event]) { return @@ -108,7 +113,7 @@ if (!processOk(process)) { // { : , ... } var sigListeners = {} signals.forEach(function (sig) { - sigListeners[sig] = function listener () { + sigListeners[sig] = function listener() { /* istanbul ignore if */ if (!processOk(global.process)) { return @@ -141,7 +146,7 @@ if (!processOk(process)) { var loaded = false - var load = function load () { + var load = function load() { if (loaded || !processOk(global.process)) { return } @@ -168,7 +173,7 @@ if (!processOk(process)) { module.exports.load = load var originalProcessReallyExit = process.reallyExit - var processReallyExit = function processReallyExit (code) { + var processReallyExit = function processReallyExit(code) { /* istanbul ignore if */ if (!processOk(global.process)) { return @@ -182,7 +187,7 @@ if (!processOk(process)) { } var originalProcessEmit = process.emit - var processEmit = function processEmit (ev, arg) { + var processEmit = function processEmit(ev, arg) { if (ev === 'exit' && processOk(global.process)) { /* istanbul ignore else */ if (arg !== undefined) { diff --git a/server/libs/universalify/index.js b/server/libs/universalify/index.js index 853f50b56..cb561976b 100644 --- a/server/libs/universalify/index.js +++ b/server/libs/universalify/index.js @@ -1,5 +1,10 @@ 'use strict' +// +// used by fsExtra +// Source: https://github.com/RyanZim/universalify +// + exports.fromCallback = function (fn) { return Object.defineProperty(function (...args) { if (typeof args[args.length - 1] === 'function') fn.apply(this, args) diff --git a/server/libs/which/LICENSE b/server/libs/which/LICENSE new file mode 100644 index 000000000..3cb6837a6 --- /dev/null +++ b/server/libs/which/LICENSE @@ -0,0 +1,15 @@ +The ISC License + +Copyright (c) Isaac Z. Schlueter and Contributors + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR +IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. \ No newline at end of file diff --git a/server/libs/which/index.js b/server/libs/which/index.js new file mode 100644 index 000000000..e7045f829 --- /dev/null +++ b/server/libs/which/index.js @@ -0,0 +1,130 @@ +// +// used by fluentFfmpeg +// SOURCE: https://github.com/isaacs/isexe +// + +const isWindows = process.platform === 'win32' || + process.env.OSTYPE === 'cygwin' || + process.env.OSTYPE === 'msys' + +const path = require('path') +const COLON = isWindows ? ';' : ':' +const isexe = require('../isexe') + +const getNotFoundError = (cmd) => + Object.assign(new Error(`not found: ${cmd}`), { code: 'ENOENT' }) + +const getPathInfo = (cmd, opt) => { + const colon = opt.colon || COLON + + // If it has a slash, then we don't bother searching the pathenv. + // just check the file itself, and that's it. + const pathEnv = cmd.match(/\//) || isWindows && cmd.match(/\\/) ? [''] + : ( + [ + // windows always checks the cwd first + ...(isWindows ? [process.cwd()] : []), + ...(opt.path || process.env.PATH || + /* istanbul ignore next: very unusual */ '').split(colon), + ] + ) + const pathExtExe = isWindows + ? opt.pathExt || process.env.PATHEXT || '.EXE;.CMD;.BAT;.COM' + : '' + const pathExt = isWindows ? pathExtExe.split(colon) : [''] + + if (isWindows) { + if (cmd.indexOf('.') !== -1 && pathExt[0] !== '') + pathExt.unshift('') + } + + return { + pathEnv, + pathExt, + pathExtExe, + } +} + +const which = (cmd, opt, cb) => { + if (typeof opt === 'function') { + cb = opt + opt = {} + } + if (!opt) + opt = {} + + const { pathEnv, pathExt, pathExtExe } = getPathInfo(cmd, opt) + const found = [] + + const step = i => new Promise((resolve, reject) => { + if (i === pathEnv.length) + return opt.all && found.length ? resolve(found) + : reject(getNotFoundError(cmd)) + + const ppRaw = pathEnv[i] + const pathPart = /^".*"$/.test(ppRaw) ? ppRaw.slice(1, -1) : ppRaw + + const pCmd = path.join(pathPart, cmd) + const p = !pathPart && /^\.[\\\/]/.test(cmd) ? cmd.slice(0, 2) + pCmd + : pCmd + + resolve(subStep(p, i, 0)) + }) + + const subStep = (p, i, ii) => new Promise((resolve, reject) => { + if (ii === pathExt.length) + return resolve(step(i + 1)) + const ext = pathExt[ii] + isexe(p + ext, { pathExt: pathExtExe }, (er, is) => { + if (!er && is) { + if (opt.all) + found.push(p + ext) + else + return resolve(p + ext) + } + return resolve(subStep(p, i, ii + 1)) + }) + }) + + return cb ? step(0).then(res => cb(null, res), cb) : step(0) +} + +const whichSync = (cmd, opt) => { + opt = opt || {} + + const { pathEnv, pathExt, pathExtExe } = getPathInfo(cmd, opt) + const found = [] + + for (let i = 0; i < pathEnv.length; i++) { + const ppRaw = pathEnv[i] + const pathPart = /^".*"$/.test(ppRaw) ? ppRaw.slice(1, -1) : ppRaw + + const pCmd = path.join(pathPart, cmd) + const p = !pathPart && /^\.[\\\/]/.test(cmd) ? cmd.slice(0, 2) + pCmd + : pCmd + + for (let j = 0; j < pathExt.length; j++) { + const cur = p + pathExt[j] + try { + const is = isexe.sync(cur, { pathExt: pathExtExe }) + if (is) { + if (opt.all) + found.push(cur) + else + return cur + } + } catch (ex) { } + } + } + + if (opt.all && found.length) + return found + + if (opt.nothrow) + return null + + throw getNotFoundError(cmd) +} + +module.exports = which +which.sync = whichSync \ No newline at end of file diff --git a/server/objects/Stream.js b/server/objects/Stream.js index 139f669aa..6e27033cd 100644 --- a/server/objects/Stream.js +++ b/server/objects/Stream.js @@ -1,4 +1,4 @@ -const Ffmpeg = require('fluent-ffmpeg') +const Ffmpeg = require('../libs/fluentFfmpeg') const EventEmitter = require('events') const Path = require('path') const fs = require('../libs/fsExtra') diff --git a/server/utils/downloadWorker.js b/server/utils/downloadWorker.js index dfb89d15c..61bb7c40b 100644 --- a/server/utils/downloadWorker.js +++ b/server/utils/downloadWorker.js @@ -1,4 +1,4 @@ -const Ffmpeg = require('fluent-ffmpeg') +const Ffmpeg = require('../libs/fluentFfmpeg') if (process.env.FFMPEG_PATH) { Ffmpeg.setFfmpegPath(process.env.FFMPEG_PATH) diff --git a/server/utils/ffmpegHelpers.js b/server/utils/ffmpegHelpers.js index 4136759f8..aaab46b7f 100644 --- a/server/utils/ffmpegHelpers.js +++ b/server/utils/ffmpegHelpers.js @@ -1,4 +1,4 @@ -const Ffmpeg = require('fluent-ffmpeg') +const Ffmpeg = require('../libs/fluentFfmpeg') const fs = require('../libs/fsExtra') const Path = require('path') const package = require('../../package.json') From 954cf3e14e8013e60a595fafece8d2b8a802cc2d Mon Sep 17 00:00:00 2001 From: advplyr Date: Wed, 6 Jul 2022 18:45:43 -0500 Subject: [PATCH 003/100] Remove jsonwebtoken dependency --- package-lock.json | 91 ------ package.json | 1 - server/Auth.js | 2 +- server/libs/jsonwebtoken/LICENSE | 21 ++ server/libs/jsonwebtoken/decode.js | 30 ++ server/libs/jsonwebtoken/index.js | 17 + .../jsonwebtoken/lib/JsonWebTokenError.js | 14 + .../libs/jsonwebtoken/lib/NotBeforeError.js | 13 + .../jsonwebtoken/lib/TokenExpiredError.js | 13 + server/libs/jsonwebtoken/lib/timespan.js | 18 ++ server/libs/jsonwebtoken/sign.js | 214 +++++++++++++ server/libs/jsonwebtoken/verify.js | 225 +++++++++++++ server/libs/jwa/LICENSE | 17 + .../jwa/buffer-equal-constant-time/LICENSE | 12 + .../jwa/buffer-equal-constant-time/index.js | 41 +++ server/libs/jwa/ecdsa-sig-formatter/LICENSE | 201 ++++++++++++ server/libs/jwa/ecdsa-sig-formatter/index.js | 187 +++++++++++ .../param-bytes-for-alg.js | 23 ++ server/libs/jwa/index.js | 257 +++++++++++++++ server/libs/jws/LICENSE | 17 + server/libs/jws/index.js | 27 ++ server/libs/jws/lib/data-stream.js | 55 ++++ server/libs/jws/lib/sign-stream.js | 78 +++++ server/libs/jws/lib/tostring.js | 10 + server/libs/jws/lib/verify-stream.js | 120 +++++++ server/libs/lodash.once/LICENSE | 47 +++ server/libs/lodash.once/index.js | 298 ++++++++++++++++++ server/libs/ms/LICENSE | 21 ++ server/libs/ms/index.js | 153 +++++++++ 29 files changed, 2130 insertions(+), 93 deletions(-) create mode 100644 server/libs/jsonwebtoken/LICENSE create mode 100644 server/libs/jsonwebtoken/decode.js create mode 100644 server/libs/jsonwebtoken/index.js create mode 100644 server/libs/jsonwebtoken/lib/JsonWebTokenError.js create mode 100644 server/libs/jsonwebtoken/lib/NotBeforeError.js create mode 100644 server/libs/jsonwebtoken/lib/TokenExpiredError.js create mode 100644 server/libs/jsonwebtoken/lib/timespan.js create mode 100644 server/libs/jsonwebtoken/sign.js create mode 100644 server/libs/jsonwebtoken/verify.js create mode 100644 server/libs/jwa/LICENSE create mode 100644 server/libs/jwa/buffer-equal-constant-time/LICENSE create mode 100644 server/libs/jwa/buffer-equal-constant-time/index.js create mode 100644 server/libs/jwa/ecdsa-sig-formatter/LICENSE create mode 100644 server/libs/jwa/ecdsa-sig-formatter/index.js create mode 100644 server/libs/jwa/ecdsa-sig-formatter/param-bytes-for-alg.js create mode 100644 server/libs/jwa/index.js create mode 100644 server/libs/jws/LICENSE create mode 100644 server/libs/jws/index.js create mode 100644 server/libs/jws/lib/data-stream.js create mode 100644 server/libs/jws/lib/sign-stream.js create mode 100644 server/libs/jws/lib/tostring.js create mode 100644 server/libs/jws/lib/verify-stream.js create mode 100644 server/libs/lodash.once/LICENSE create mode 100644 server/libs/lodash.once/index.js create mode 100644 server/libs/ms/LICENSE create mode 100644 server/libs/ms/index.js diff --git a/package-lock.json b/package-lock.json index bcd222472..700eba81c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -188,11 +188,6 @@ "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==" }, - "buffer-equal-constant-time": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", - "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==" - }, "busboy": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", @@ -354,14 +349,6 @@ "domhandler": "^5.0.1" } }, - "ecdsa-sig-formatter": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", - "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", - "requires": { - "safe-buffer": "^5.0.1" - } - }, "ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", @@ -641,49 +628,6 @@ "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" }, - "jsonwebtoken": { - "version": "8.5.1", - "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz", - "integrity": "sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w==", - "requires": { - "jws": "^3.2.2", - "lodash.includes": "^4.3.0", - "lodash.isboolean": "^3.0.3", - "lodash.isinteger": "^4.0.4", - "lodash.isnumber": "^3.0.3", - "lodash.isplainobject": "^4.0.6", - "lodash.isstring": "^4.0.1", - "lodash.once": "^4.0.0", - "ms": "^2.1.1", - "semver": "^5.6.0" - }, - "dependencies": { - "ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" - } - } - }, - "jwa": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", - "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", - "requires": { - "buffer-equal-constant-time": "1.0.1", - "ecdsa-sig-formatter": "1.0.11", - "safe-buffer": "^5.0.1" - } - }, - "jws": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", - "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", - "requires": { - "jwa": "^1.4.1", - "safe-buffer": "^5.0.1" - } - }, "lazystream": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.1.tgz", @@ -741,41 +685,11 @@ "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz", "integrity": "sha512-C5N2Z3DgnnKr0LOpv/hKCgKdb7ZZwafIrsesve6lmzvZIRZRGaZ/l6Q8+2W7NaT+ZwO3fFlSCzCzrDCFdJfZ4g==" }, - "lodash.includes": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", - "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==" - }, - "lodash.isboolean": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", - "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==" - }, - "lodash.isinteger": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", - "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==" - }, - "lodash.isnumber": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", - "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==" - }, "lodash.isplainobject": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==" }, - "lodash.isstring": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", - "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==" - }, - "lodash.once": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", - "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==" - }, "lodash.union": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/lodash.union/-/lodash.union-4.6.0.tgz", @@ -949,11 +863,6 @@ "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" }, - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" - }, "send": { "version": "0.18.0", "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", diff --git a/package.json b/package.json index 2cf504c6b..631144b1b 100644 --- a/package.json +++ b/package.json @@ -39,7 +39,6 @@ "express-fileupload": "^1.2.1", "express-rate-limit": "^5.3.0", "htmlparser2": "^8.0.1", - "jsonwebtoken": "^8.5.1", "socket.io": "^4.4.1", "xml2js": "^0.4.23" } diff --git a/server/Auth.js b/server/Auth.js index 9736e1fde..de86f393b 100644 --- a/server/Auth.js +++ b/server/Auth.js @@ -1,5 +1,5 @@ const bcrypt = require('bcryptjs') -const jwt = require('jsonwebtoken') +const jwt = require('./libs/jsonwebtoken') const Logger = require('./Logger') class Auth { diff --git a/server/libs/jsonwebtoken/LICENSE b/server/libs/jsonwebtoken/LICENSE new file mode 100644 index 000000000..bcd1854c4 --- /dev/null +++ b/server/libs/jsonwebtoken/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2015 Auth0, Inc. (http://auth0.com) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/server/libs/jsonwebtoken/decode.js b/server/libs/jsonwebtoken/decode.js new file mode 100644 index 000000000..5f2cf6af5 --- /dev/null +++ b/server/libs/jsonwebtoken/decode.js @@ -0,0 +1,30 @@ +var jws = require('../jws'); + +module.exports = function (jwt, options) { + options = options || {}; + var decoded = jws.decode(jwt, options); + if (!decoded) { return null; } + var payload = decoded.payload; + + //try parse the payload + if (typeof payload === 'string') { + try { + var obj = JSON.parse(payload); + if (obj !== null && typeof obj === 'object') { + payload = obj; + } + } catch (e) { } + } + + //return header if `complete` option is enabled. header includes claims + //such as `kid` and `alg` used to select the key within a JWKS needed to + //verify the signature + if (options.complete === true) { + return { + header: decoded.header, + payload: payload, + signature: decoded.signature + }; + } + return payload; +}; diff --git a/server/libs/jsonwebtoken/index.js b/server/libs/jsonwebtoken/index.js new file mode 100644 index 000000000..6f8ce1c53 --- /dev/null +++ b/server/libs/jsonwebtoken/index.js @@ -0,0 +1,17 @@ +// +// modified for use in audiobookshelf +// Source: https://github.com/auth0/node-jsonwebtoken +// + +module.exports = { + verify: require('./verify'), + sign: require('./sign'), + JsonWebTokenError: require('./lib/JsonWebTokenError'), + NotBeforeError: require('./lib/NotBeforeError'), + TokenExpiredError: require('./lib/TokenExpiredError'), +}; + +Object.defineProperty(module.exports, 'decode', { + enumerable: false, + value: require('./decode'), +}); diff --git a/server/libs/jsonwebtoken/lib/JsonWebTokenError.js b/server/libs/jsonwebtoken/lib/JsonWebTokenError.js new file mode 100644 index 000000000..e068222a0 --- /dev/null +++ b/server/libs/jsonwebtoken/lib/JsonWebTokenError.js @@ -0,0 +1,14 @@ +var JsonWebTokenError = function (message, error) { + Error.call(this, message); + if(Error.captureStackTrace) { + Error.captureStackTrace(this, this.constructor); + } + this.name = 'JsonWebTokenError'; + this.message = message; + if (error) this.inner = error; +}; + +JsonWebTokenError.prototype = Object.create(Error.prototype); +JsonWebTokenError.prototype.constructor = JsonWebTokenError; + +module.exports = JsonWebTokenError; diff --git a/server/libs/jsonwebtoken/lib/NotBeforeError.js b/server/libs/jsonwebtoken/lib/NotBeforeError.js new file mode 100644 index 000000000..7b30084fb --- /dev/null +++ b/server/libs/jsonwebtoken/lib/NotBeforeError.js @@ -0,0 +1,13 @@ +var JsonWebTokenError = require('./JsonWebTokenError'); + +var NotBeforeError = function (message, date) { + JsonWebTokenError.call(this, message); + this.name = 'NotBeforeError'; + this.date = date; +}; + +NotBeforeError.prototype = Object.create(JsonWebTokenError.prototype); + +NotBeforeError.prototype.constructor = NotBeforeError; + +module.exports = NotBeforeError; \ No newline at end of file diff --git a/server/libs/jsonwebtoken/lib/TokenExpiredError.js b/server/libs/jsonwebtoken/lib/TokenExpiredError.js new file mode 100644 index 000000000..abb704f23 --- /dev/null +++ b/server/libs/jsonwebtoken/lib/TokenExpiredError.js @@ -0,0 +1,13 @@ +var JsonWebTokenError = require('./JsonWebTokenError'); + +var TokenExpiredError = function (message, expiredAt) { + JsonWebTokenError.call(this, message); + this.name = 'TokenExpiredError'; + this.expiredAt = expiredAt; +}; + +TokenExpiredError.prototype = Object.create(JsonWebTokenError.prototype); + +TokenExpiredError.prototype.constructor = TokenExpiredError; + +module.exports = TokenExpiredError; \ No newline at end of file diff --git a/server/libs/jsonwebtoken/lib/timespan.js b/server/libs/jsonwebtoken/lib/timespan.js new file mode 100644 index 000000000..4d4574c2e --- /dev/null +++ b/server/libs/jsonwebtoken/lib/timespan.js @@ -0,0 +1,18 @@ +var ms = require('../../ms'); + +module.exports = function (time, iat) { + var timestamp = iat || Math.floor(Date.now() / 1000); + + if (typeof time === 'string') { + var milliseconds = ms(time); + if (typeof milliseconds === 'undefined') { + return; + } + return Math.floor(timestamp + milliseconds / 1000); + } else if (typeof time === 'number') { + return timestamp + time; + } else { + return; + } + +}; \ No newline at end of file diff --git a/server/libs/jsonwebtoken/sign.js b/server/libs/jsonwebtoken/sign.js new file mode 100644 index 000000000..f1512f1f6 --- /dev/null +++ b/server/libs/jsonwebtoken/sign.js @@ -0,0 +1,214 @@ +var timespan = require('./lib/timespan'); +var PS_SUPPORTED = true +var jws = require('../jws'); +var once = require('../lodash.once'); + +var SUPPORTED_ALGS = ['RS256', 'RS384', 'RS512', 'ES256', 'ES384', 'ES512', 'HS256', 'HS384', 'HS512', 'none']; +if (PS_SUPPORTED) { + SUPPORTED_ALGS.splice(3, 0, 'PS256', 'PS384', 'PS512'); +} + +function isPlainObject(value) { + var type = typeof value; + return !!value && type == 'object' && !Array.isArray(value); +} +function isInteger(val) { + return !isNaN(val) && val !== null && !String(val).includes('.') +} +function isNumber(val) { + return !isNaN(val) && val !== null +} +function isString(val) { + return typeof val == 'string' +} + +var sign_options_schema = { + expiresIn: { isValid: function (value) { return isInteger(value) || (isString(value) && value); }, message: '"expiresIn" should be a number of seconds or string representing a timespan' }, + notBefore: { isValid: function (value) { return isInteger(value) || (isString(value) && value); }, message: '"notBefore" should be a number of seconds or string representing a timespan' }, + audience: { isValid: function (value) { return isString(value) || Array.isArray(value); }, message: '"audience" must be a string or array' }, + algorithm: { isValid: function (value) { return SUPPORTED_ALGS.includes(value); }, message: '"algorithm" must be a valid string enum value' }, + header: { isValid: isPlainObject, message: '"header" must be an object' }, + encoding: { isValid: isString, message: '"encoding" must be a string' }, + issuer: { isValid: isString, message: '"issuer" must be a string' }, + subject: { isValid: isString, message: '"subject" must be a string' }, + jwtid: { isValid: isString, message: '"jwtid" must be a string' }, + noTimestamp: { isValid: function (value) { return value === true || value === false; }, message: '"noTimestamp" must be a boolean' }, + keyid: { isValid: isString, message: '"keyid" must be a string' }, + mutatePayload: { isValid: function (value) { return value === true || value === false; }, message: '"mutatePayload" must be a boolean' } +}; + +var registered_claims_schema = { + iat: { isValid: isNumber, message: '"iat" should be a number of seconds' }, + exp: { isValid: isNumber, message: '"exp" should be a number of seconds' }, + nbf: { isValid: isNumber, message: '"nbf" should be a number of seconds' } +}; + +function validate(schema, allowUnknown, object, parameterName) { + if (!isPlainObject(object)) { + throw new Error('Expected "' + parameterName + '" to be a plain object.'); + } + Object.keys(object) + .forEach(function (key) { + var validator = schema[key]; + if (!validator) { + if (!allowUnknown) { + throw new Error('"' + key + '" is not allowed in "' + parameterName + '"'); + } + return; + } + if (!validator.isValid(object[key])) { + throw new Error(validator.message); + } + }); +} + +function validateOptions(options) { + return validate(sign_options_schema, false, options, 'options'); +} + +function validatePayload(payload) { + return validate(registered_claims_schema, true, payload, 'payload'); +} + +var options_to_payload = { + 'audience': 'aud', + 'issuer': 'iss', + 'subject': 'sub', + 'jwtid': 'jti' +}; + +var options_for_objects = [ + 'expiresIn', + 'notBefore', + 'noTimestamp', + 'audience', + 'issuer', + 'subject', + 'jwtid', +]; + +module.exports = function (payload, secretOrPrivateKey, options, callback) { + if (typeof options === 'function') { + callback = options; + options = {}; + } else { + options = options || {}; + } + + var isObjectPayload = typeof payload === 'object' && + !Buffer.isBuffer(payload); + + var header = Object.assign({ + alg: options.algorithm || 'HS256', + typ: isObjectPayload ? 'JWT' : undefined, + kid: options.keyid + }, options.header); + + function failure(err) { + if (callback) { + return callback(err); + } + throw err; + } + + if (!secretOrPrivateKey && options.algorithm !== 'none') { + return failure(new Error('secretOrPrivateKey must have a value')); + } + + if (typeof payload === 'undefined') { + return failure(new Error('payload is required')); + } else if (isObjectPayload) { + try { + validatePayload(payload); + } + catch (error) { + return failure(error); + } + if (!options.mutatePayload) { + payload = Object.assign({}, payload); + } + } else { + var invalid_options = options_for_objects.filter(function (opt) { + return typeof options[opt] !== 'undefined'; + }); + + if (invalid_options.length > 0) { + return failure(new Error('invalid ' + invalid_options.join(',') + ' option for ' + (typeof payload) + ' payload')); + } + } + + if (typeof payload.exp !== 'undefined' && typeof options.expiresIn !== 'undefined') { + return failure(new Error('Bad "options.expiresIn" option the payload already has an "exp" property.')); + } + + if (typeof payload.nbf !== 'undefined' && typeof options.notBefore !== 'undefined') { + return failure(new Error('Bad "options.notBefore" option the payload already has an "nbf" property.')); + } + + try { + validateOptions(options); + } + catch (error) { + return failure(error); + } + + var timestamp = payload.iat || Math.floor(Date.now() / 1000); + + if (options.noTimestamp) { + delete payload.iat; + } else if (isObjectPayload) { + payload.iat = timestamp; + } + + if (typeof options.notBefore !== 'undefined') { + try { + payload.nbf = timespan(options.notBefore, timestamp); + } + catch (err) { + return failure(err); + } + if (typeof payload.nbf === 'undefined') { + return failure(new Error('"notBefore" should be a number of seconds or string representing a timespan eg: "1d", "20h", 60')); + } + } + + if (typeof options.expiresIn !== 'undefined' && typeof payload === 'object') { + try { + payload.exp = timespan(options.expiresIn, timestamp); + } + catch (err) { + return failure(err); + } + if (typeof payload.exp === 'undefined') { + return failure(new Error('"expiresIn" should be a number of seconds or string representing a timespan eg: "1d", "20h", 60')); + } + } + + Object.keys(options_to_payload).forEach(function (key) { + var claim = options_to_payload[key]; + if (typeof options[key] !== 'undefined') { + if (typeof payload[claim] !== 'undefined') { + return failure(new Error('Bad "options.' + key + '" option. The payload already has an "' + claim + '" property.')); + } + payload[claim] = options[key]; + } + }); + + var encoding = options.encoding || 'utf8'; + + if (typeof callback === 'function') { + callback = callback && once(callback); + + jws.createSign({ + header: header, + privateKey: secretOrPrivateKey, + payload: payload, + encoding: encoding + }).once('error', callback) + .once('done', function (signature) { + callback(null, signature); + }); + } else { + return jws.sign({ header: header, payload: payload, secret: secretOrPrivateKey, encoding: encoding }); + } +}; diff --git a/server/libs/jsonwebtoken/verify.js b/server/libs/jsonwebtoken/verify.js new file mode 100644 index 000000000..df7413cf9 --- /dev/null +++ b/server/libs/jsonwebtoken/verify.js @@ -0,0 +1,225 @@ +var JsonWebTokenError = require('./lib/JsonWebTokenError'); +var NotBeforeError = require('./lib/NotBeforeError'); +var TokenExpiredError = require('./lib/TokenExpiredError'); +var decode = require('./decode'); +var timespan = require('./lib/timespan'); +var PS_SUPPORTED = true +var jws = require('../jws'); + +var PUB_KEY_ALGS = ['RS256', 'RS384', 'RS512', 'ES256', 'ES384', 'ES512']; +var RSA_KEY_ALGS = ['RS256', 'RS384', 'RS512']; +var HS_ALGS = ['HS256', 'HS384', 'HS512']; + +if (PS_SUPPORTED) { + PUB_KEY_ALGS.splice(3, 0, 'PS256', 'PS384', 'PS512'); + RSA_KEY_ALGS.splice(3, 0, 'PS256', 'PS384', 'PS512'); +} + +module.exports = function (jwtString, secretOrPublicKey, options, callback) { + if ((typeof options === 'function') && !callback) { + callback = options; + options = {}; + } + + if (!options) { + options = {}; + } + + //clone this object since we are going to mutate it. + options = Object.assign({}, options); + + var done; + + if (callback) { + done = callback; + } else { + done = function (err, data) { + if (err) throw err; + return data; + }; + } + + if (options.clockTimestamp && typeof options.clockTimestamp !== 'number') { + return done(new JsonWebTokenError('clockTimestamp must be a number')); + } + + if (options.nonce !== undefined && (typeof options.nonce !== 'string' || options.nonce.trim() === '')) { + return done(new JsonWebTokenError('nonce must be a non-empty string')); + } + + var clockTimestamp = options.clockTimestamp || Math.floor(Date.now() / 1000); + + if (!jwtString) { + return done(new JsonWebTokenError('jwt must be provided')); + } + + if (typeof jwtString !== 'string') { + return done(new JsonWebTokenError('jwt must be a string')); + } + + var parts = jwtString.split('.'); + + if (parts.length !== 3) { + return done(new JsonWebTokenError('jwt malformed')); + } + + var decodedToken; + + try { + decodedToken = decode(jwtString, { complete: true }); + } catch (err) { + return done(err); + } + + if (!decodedToken) { + return done(new JsonWebTokenError('invalid token')); + } + + var header = decodedToken.header; + var getSecret; + + if (typeof secretOrPublicKey === 'function') { + if (!callback) { + return done(new JsonWebTokenError('verify must be called asynchronous if secret or public key is provided as a callback')); + } + + getSecret = secretOrPublicKey; + } + else { + getSecret = function (header, secretCallback) { + return secretCallback(null, secretOrPublicKey); + }; + } + + return getSecret(header, function (err, secretOrPublicKey) { + if (err) { + return done(new JsonWebTokenError('error in secret or public key callback: ' + err.message)); + } + + var hasSignature = parts[2].trim() !== ''; + + if (!hasSignature && secretOrPublicKey) { + return done(new JsonWebTokenError('jwt signature is required')); + } + + if (hasSignature && !secretOrPublicKey) { + return done(new JsonWebTokenError('secret or public key must be provided')); + } + + if (!hasSignature && !options.algorithms) { + options.algorithms = ['none']; + } + + if (!options.algorithms) { + options.algorithms = secretOrPublicKey.toString().includes('BEGIN CERTIFICATE') || + secretOrPublicKey.toString().includes('BEGIN PUBLIC KEY') ? PUB_KEY_ALGS : + secretOrPublicKey.toString().includes('BEGIN RSA PUBLIC KEY') ? RSA_KEY_ALGS : HS_ALGS; + + } + + if (!~options.algorithms.indexOf(decodedToken.header.alg)) { + return done(new JsonWebTokenError('invalid algorithm')); + } + + var valid; + + try { + valid = jws.verify(jwtString, decodedToken.header.alg, secretOrPublicKey); + } catch (e) { + return done(e); + } + + if (!valid) { + return done(new JsonWebTokenError('invalid signature')); + } + + var payload = decodedToken.payload; + + if (typeof payload.nbf !== 'undefined' && !options.ignoreNotBefore) { + if (typeof payload.nbf !== 'number') { + return done(new JsonWebTokenError('invalid nbf value')); + } + if (payload.nbf > clockTimestamp + (options.clockTolerance || 0)) { + return done(new NotBeforeError('jwt not active', new Date(payload.nbf * 1000))); + } + } + + if (typeof payload.exp !== 'undefined' && !options.ignoreExpiration) { + if (typeof payload.exp !== 'number') { + return done(new JsonWebTokenError('invalid exp value')); + } + if (clockTimestamp >= payload.exp + (options.clockTolerance || 0)) { + return done(new TokenExpiredError('jwt expired', new Date(payload.exp * 1000))); + } + } + + if (options.audience) { + var audiences = Array.isArray(options.audience) ? options.audience : [options.audience]; + var target = Array.isArray(payload.aud) ? payload.aud : [payload.aud]; + + var match = target.some(function (targetAudience) { + return audiences.some(function (audience) { + return audience instanceof RegExp ? audience.test(targetAudience) : audience === targetAudience; + }); + }); + + if (!match) { + return done(new JsonWebTokenError('jwt audience invalid. expected: ' + audiences.join(' or '))); + } + } + + if (options.issuer) { + var invalid_issuer = + (typeof options.issuer === 'string' && payload.iss !== options.issuer) || + (Array.isArray(options.issuer) && options.issuer.indexOf(payload.iss) === -1); + + if (invalid_issuer) { + return done(new JsonWebTokenError('jwt issuer invalid. expected: ' + options.issuer)); + } + } + + if (options.subject) { + if (payload.sub !== options.subject) { + return done(new JsonWebTokenError('jwt subject invalid. expected: ' + options.subject)); + } + } + + if (options.jwtid) { + if (payload.jti !== options.jwtid) { + return done(new JsonWebTokenError('jwt jwtid invalid. expected: ' + options.jwtid)); + } + } + + if (options.nonce) { + if (payload.nonce !== options.nonce) { + return done(new JsonWebTokenError('jwt nonce invalid. expected: ' + options.nonce)); + } + } + + if (options.maxAge) { + if (typeof payload.iat !== 'number') { + return done(new JsonWebTokenError('iat required when maxAge is specified')); + } + + var maxAgeTimestamp = timespan(options.maxAge, payload.iat); + if (typeof maxAgeTimestamp === 'undefined') { + return done(new JsonWebTokenError('"maxAge" should be a number of seconds or string representing a timespan eg: "1d", "20h", 60')); + } + if (clockTimestamp >= maxAgeTimestamp + (options.clockTolerance || 0)) { + return done(new TokenExpiredError('maxAge exceeded', new Date(maxAgeTimestamp * 1000))); + } + } + + if (options.complete === true) { + var signature = decodedToken.signature; + + return done(null, { + header: header, + payload: payload, + signature: signature + }); + } + + return done(null, payload); + }); +}; diff --git a/server/libs/jwa/LICENSE b/server/libs/jwa/LICENSE new file mode 100644 index 000000000..468d04af6 --- /dev/null +++ b/server/libs/jwa/LICENSE @@ -0,0 +1,17 @@ +Copyright (c) 2013 Brian J. Brennan + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the +Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/server/libs/jwa/buffer-equal-constant-time/LICENSE b/server/libs/jwa/buffer-equal-constant-time/LICENSE new file mode 100644 index 000000000..9a064f3f4 --- /dev/null +++ b/server/libs/jwa/buffer-equal-constant-time/LICENSE @@ -0,0 +1,12 @@ +Copyright (c) 2013, GoInstant Inc., a salesforce.com company +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + +* Neither the name of salesforce.com, nor GoInstant, nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/server/libs/jwa/buffer-equal-constant-time/index.js b/server/libs/jwa/buffer-equal-constant-time/index.js new file mode 100644 index 000000000..07c142662 --- /dev/null +++ b/server/libs/jwa/buffer-equal-constant-time/index.js @@ -0,0 +1,41 @@ +/*jshint node:true */ +'use strict'; +var Buffer = require('buffer').Buffer; // browserify +var SlowBuffer = require('buffer').SlowBuffer; + +module.exports = bufferEq; + +function bufferEq(a, b) { + + // shortcutting on type is necessary for correctness + if (!Buffer.isBuffer(a) || !Buffer.isBuffer(b)) { + return false; + } + + // buffer sizes should be well-known information, so despite this + // shortcutting, it doesn't leak any information about the *contents* of the + // buffers. + if (a.length !== b.length) { + return false; + } + + var c = 0; + for (var i = 0; i < a.length; i++) { + /*jshint bitwise:false */ + c |= a[i] ^ b[i]; // XOR + } + return c === 0; +} + +bufferEq.install = function () { + Buffer.prototype.equal = SlowBuffer.prototype.equal = function equal(that) { + return bufferEq(this, that); + }; +}; + +var origBufEqual = Buffer.prototype.equal; +var origSlowBufEqual = SlowBuffer.prototype.equal; +bufferEq.restore = function () { + Buffer.prototype.equal = origBufEqual; + SlowBuffer.prototype.equal = origSlowBufEqual; +}; diff --git a/server/libs/jwa/ecdsa-sig-formatter/LICENSE b/server/libs/jwa/ecdsa-sig-formatter/LICENSE new file mode 100644 index 000000000..9b3b0105e --- /dev/null +++ b/server/libs/jwa/ecdsa-sig-formatter/LICENSE @@ -0,0 +1,201 @@ +Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2015 D2L Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. \ No newline at end of file diff --git a/server/libs/jwa/ecdsa-sig-formatter/index.js b/server/libs/jwa/ecdsa-sig-formatter/index.js new file mode 100644 index 000000000..dcb7ddf00 --- /dev/null +++ b/server/libs/jwa/ecdsa-sig-formatter/index.js @@ -0,0 +1,187 @@ +'use strict'; + +var Buffer = require('safe-buffer').Buffer; + +var getParamBytesForAlg = require('./param-bytes-for-alg'); + +var MAX_OCTET = 0x80, + CLASS_UNIVERSAL = 0, + PRIMITIVE_BIT = 0x20, + TAG_SEQ = 0x10, + TAG_INT = 0x02, + ENCODED_TAG_SEQ = (TAG_SEQ | PRIMITIVE_BIT) | (CLASS_UNIVERSAL << 6), + ENCODED_TAG_INT = TAG_INT | (CLASS_UNIVERSAL << 6); + +function base64Url(base64) { + return base64 + .replace(/=/g, '') + .replace(/\+/g, '-') + .replace(/\//g, '_'); +} + +function signatureAsBuffer(signature) { + if (Buffer.isBuffer(signature)) { + return signature; + } else if ('string' === typeof signature) { + return Buffer.from(signature, 'base64'); + } + + throw new TypeError('ECDSA signature must be a Base64 string or a Buffer'); +} + +function derToJose(signature, alg) { + signature = signatureAsBuffer(signature); + var paramBytes = getParamBytesForAlg(alg); + + // the DER encoded param should at most be the param size, plus a padding + // zero, since due to being a signed integer + var maxEncodedParamLength = paramBytes + 1; + + var inputLength = signature.length; + + var offset = 0; + if (signature[offset++] !== ENCODED_TAG_SEQ) { + throw new Error('Could not find expected "seq"'); + } + + var seqLength = signature[offset++]; + if (seqLength === (MAX_OCTET | 1)) { + seqLength = signature[offset++]; + } + + if (inputLength - offset < seqLength) { + throw new Error('"seq" specified length of "' + seqLength + '", only "' + (inputLength - offset) + '" remaining'); + } + + if (signature[offset++] !== ENCODED_TAG_INT) { + throw new Error('Could not find expected "int" for "r"'); + } + + var rLength = signature[offset++]; + + if (inputLength - offset - 2 < rLength) { + throw new Error('"r" specified length of "' + rLength + '", only "' + (inputLength - offset - 2) + '" available'); + } + + if (maxEncodedParamLength < rLength) { + throw new Error('"r" specified length of "' + rLength + '", max of "' + maxEncodedParamLength + '" is acceptable'); + } + + var rOffset = offset; + offset += rLength; + + if (signature[offset++] !== ENCODED_TAG_INT) { + throw new Error('Could not find expected "int" for "s"'); + } + + var sLength = signature[offset++]; + + if (inputLength - offset !== sLength) { + throw new Error('"s" specified length of "' + sLength + '", expected "' + (inputLength - offset) + '"'); + } + + if (maxEncodedParamLength < sLength) { + throw new Error('"s" specified length of "' + sLength + '", max of "' + maxEncodedParamLength + '" is acceptable'); + } + + var sOffset = offset; + offset += sLength; + + if (offset !== inputLength) { + throw new Error('Expected to consume entire buffer, but "' + (inputLength - offset) + '" bytes remain'); + } + + var rPadding = paramBytes - rLength, + sPadding = paramBytes - sLength; + + var dst = Buffer.allocUnsafe(rPadding + rLength + sPadding + sLength); + + for (offset = 0; offset < rPadding; ++offset) { + dst[offset] = 0; + } + signature.copy(dst, offset, rOffset + Math.max(-rPadding, 0), rOffset + rLength); + + offset = paramBytes; + + for (var o = offset; offset < o + sPadding; ++offset) { + dst[offset] = 0; + } + signature.copy(dst, offset, sOffset + Math.max(-sPadding, 0), sOffset + sLength); + + dst = dst.toString('base64'); + dst = base64Url(dst); + + return dst; +} + +function countPadding(buf, start, stop) { + var padding = 0; + while (start + padding < stop && buf[start + padding] === 0) { + ++padding; + } + + var needsSign = buf[start + padding] >= MAX_OCTET; + if (needsSign) { + --padding; + } + + return padding; +} + +function joseToDer(signature, alg) { + signature = signatureAsBuffer(signature); + var paramBytes = getParamBytesForAlg(alg); + + var signatureBytes = signature.length; + if (signatureBytes !== paramBytes * 2) { + throw new TypeError('"' + alg + '" signatures must be "' + paramBytes * 2 + '" bytes, saw "' + signatureBytes + '"'); + } + + var rPadding = countPadding(signature, 0, paramBytes); + var sPadding = countPadding(signature, paramBytes, signature.length); + var rLength = paramBytes - rPadding; + var sLength = paramBytes - sPadding; + + var rsBytes = 1 + 1 + rLength + 1 + 1 + sLength; + + var shortLength = rsBytes < MAX_OCTET; + + var dst = Buffer.allocUnsafe((shortLength ? 2 : 3) + rsBytes); + + var offset = 0; + dst[offset++] = ENCODED_TAG_SEQ; + if (shortLength) { + // Bit 8 has value "0" + // bits 7-1 give the length. + dst[offset++] = rsBytes; + } else { + // Bit 8 of first octet has value "1" + // bits 7-1 give the number of additional length octets. + dst[offset++] = MAX_OCTET | 1; + // length, base 256 + dst[offset++] = rsBytes & 0xff; + } + dst[offset++] = ENCODED_TAG_INT; + dst[offset++] = rLength; + if (rPadding < 0) { + dst[offset++] = 0; + offset += signature.copy(dst, offset, 0, paramBytes); + } else { + offset += signature.copy(dst, offset, rPadding, paramBytes); + } + dst[offset++] = ENCODED_TAG_INT; + dst[offset++] = sLength; + if (sPadding < 0) { + dst[offset++] = 0; + signature.copy(dst, offset, paramBytes); + } else { + signature.copy(dst, offset, paramBytes + sPadding); + } + + return dst; +} + +module.exports = { + derToJose: derToJose, + joseToDer: joseToDer +}; \ No newline at end of file diff --git a/server/libs/jwa/ecdsa-sig-formatter/param-bytes-for-alg.js b/server/libs/jwa/ecdsa-sig-formatter/param-bytes-for-alg.js new file mode 100644 index 000000000..07837d7d4 --- /dev/null +++ b/server/libs/jwa/ecdsa-sig-formatter/param-bytes-for-alg.js @@ -0,0 +1,23 @@ +'use strict'; + +function getParamSize(keySize) { + var result = ((keySize / 8) | 0) + (keySize % 8 === 0 ? 0 : 1); + return result; +} + +var paramBytesForAlg = { + ES256: getParamSize(256), + ES384: getParamSize(384), + ES512: getParamSize(521) +}; + +function getParamBytesForAlg(alg) { + var paramBytes = paramBytesForAlg[alg]; + if (paramBytes) { + return paramBytes; + } + + throw new Error('Unknown algorithm "' + alg + '"'); +} + +module.exports = getParamBytesForAlg; \ No newline at end of file diff --git a/server/libs/jwa/index.js b/server/libs/jwa/index.js new file mode 100644 index 000000000..c0b188341 --- /dev/null +++ b/server/libs/jwa/index.js @@ -0,0 +1,257 @@ +// +// used by jws +// Source: https://github.com/auth0/node-jwa +// + +var bufferEqual = require('./buffer-equal-constant-time'); +var Buffer = require('safe-buffer').Buffer; +var crypto = require('crypto'); +var formatEcdsa = require('./ecdsa-sig-formatter'); +var util = require('util'); + +var MSG_INVALID_ALGORITHM = '"%s" is not a valid algorithm.\n Supported algorithms are:\n "HS256", "HS384", "HS512", "RS256", "RS384", "RS512", "PS256", "PS384", "PS512", "ES256", "ES384", "ES512" and "none".' +var MSG_INVALID_SECRET = 'secret must be a string or buffer'; +var MSG_INVALID_VERIFIER_KEY = 'key must be a string or a buffer'; +var MSG_INVALID_SIGNER_KEY = 'key must be a string, a buffer or an object'; + +var supportsKeyObjects = typeof crypto.createPublicKey === 'function'; +if (supportsKeyObjects) { + MSG_INVALID_VERIFIER_KEY += ' or a KeyObject'; + MSG_INVALID_SECRET += 'or a KeyObject'; +} + +function checkIsPublicKey(key) { + if (Buffer.isBuffer(key)) { + return; + } + + if (typeof key === 'string') { + return; + } + + if (!supportsKeyObjects) { + throw typeError(MSG_INVALID_VERIFIER_KEY); + } + + if (typeof key !== 'object') { + throw typeError(MSG_INVALID_VERIFIER_KEY); + } + + if (typeof key.type !== 'string') { + throw typeError(MSG_INVALID_VERIFIER_KEY); + } + + if (typeof key.asymmetricKeyType !== 'string') { + throw typeError(MSG_INVALID_VERIFIER_KEY); + } + + if (typeof key.export !== 'function') { + throw typeError(MSG_INVALID_VERIFIER_KEY); + } +}; + +function checkIsPrivateKey(key) { + if (Buffer.isBuffer(key)) { + return; + } + + if (typeof key === 'string') { + return; + } + + if (typeof key === 'object') { + return; + } + + throw typeError(MSG_INVALID_SIGNER_KEY); +}; + +function checkIsSecretKey(key) { + if (Buffer.isBuffer(key)) { + return; + } + + if (typeof key === 'string') { + return key; + } + + if (!supportsKeyObjects) { + throw typeError(MSG_INVALID_SECRET); + } + + if (typeof key !== 'object') { + throw typeError(MSG_INVALID_SECRET); + } + + if (key.type !== 'secret') { + throw typeError(MSG_INVALID_SECRET); + } + + if (typeof key.export !== 'function') { + throw typeError(MSG_INVALID_SECRET); + } +} + +function fromBase64(base64) { + return base64 + .replace(/=/g, '') + .replace(/\+/g, '-') + .replace(/\//g, '_'); +} + +function toBase64(base64url) { + base64url = base64url.toString(); + + var padding = 4 - base64url.length % 4; + if (padding !== 4) { + for (var i = 0; i < padding; ++i) { + base64url += '='; + } + } + + return base64url + .replace(/\-/g, '+') + .replace(/_/g, '/'); +} + +function typeError(template) { + var args = [].slice.call(arguments, 1); + var errMsg = util.format.bind(util, template).apply(null, args); + return new TypeError(errMsg); +} + +function bufferOrString(obj) { + return Buffer.isBuffer(obj) || typeof obj === 'string'; +} + +function normalizeInput(thing) { + if (!bufferOrString(thing)) + thing = JSON.stringify(thing); + return thing; +} + +function createHmacSigner(bits) { + return function sign(thing, secret) { + checkIsSecretKey(secret); + thing = normalizeInput(thing); + var hmac = crypto.createHmac('sha' + bits, secret); + var sig = (hmac.update(thing), hmac.digest('base64')) + return fromBase64(sig); + } +} + +function createHmacVerifier(bits) { + return function verify(thing, signature, secret) { + var computedSig = createHmacSigner(bits)(thing, secret); + return bufferEqual(Buffer.from(signature), Buffer.from(computedSig)); + } +} + +function createKeySigner(bits) { + return function sign(thing, privateKey) { + checkIsPrivateKey(privateKey); + thing = normalizeInput(thing); + // Even though we are specifying "RSA" here, this works with ECDSA + // keys as well. + var signer = crypto.createSign('RSA-SHA' + bits); + var sig = (signer.update(thing), signer.sign(privateKey, 'base64')); + return fromBase64(sig); + } +} + +function createKeyVerifier(bits) { + return function verify(thing, signature, publicKey) { + checkIsPublicKey(publicKey); + thing = normalizeInput(thing); + signature = toBase64(signature); + var verifier = crypto.createVerify('RSA-SHA' + bits); + verifier.update(thing); + return verifier.verify(publicKey, signature, 'base64'); + } +} + +function createPSSKeySigner(bits) { + return function sign(thing, privateKey) { + checkIsPrivateKey(privateKey); + thing = normalizeInput(thing); + var signer = crypto.createSign('RSA-SHA' + bits); + var sig = (signer.update(thing), signer.sign({ + key: privateKey, + padding: crypto.constants.RSA_PKCS1_PSS_PADDING, + saltLength: crypto.constants.RSA_PSS_SALTLEN_DIGEST + }, 'base64')); + return fromBase64(sig); + } +} + +function createPSSKeyVerifier(bits) { + return function verify(thing, signature, publicKey) { + checkIsPublicKey(publicKey); + thing = normalizeInput(thing); + signature = toBase64(signature); + var verifier = crypto.createVerify('RSA-SHA' + bits); + verifier.update(thing); + return verifier.verify({ + key: publicKey, + padding: crypto.constants.RSA_PKCS1_PSS_PADDING, + saltLength: crypto.constants.RSA_PSS_SALTLEN_DIGEST + }, signature, 'base64'); + } +} + +function createECDSASigner(bits) { + var inner = createKeySigner(bits); + return function sign() { + var signature = inner.apply(null, arguments); + signature = formatEcdsa.derToJose(signature, 'ES' + bits); + return signature; + }; +} + +function createECDSAVerifer(bits) { + var inner = createKeyVerifier(bits); + return function verify(thing, signature, publicKey) { + signature = formatEcdsa.joseToDer(signature, 'ES' + bits).toString('base64'); + var result = inner(thing, signature, publicKey); + return result; + }; +} + +function createNoneSigner() { + return function sign() { + return ''; + } +} + +function createNoneVerifier() { + return function verify(thing, signature) { + return signature === ''; + } +} + +module.exports = function jwa(algorithm) { + var signerFactories = { + hs: createHmacSigner, + rs: createKeySigner, + ps: createPSSKeySigner, + es: createECDSASigner, + none: createNoneSigner, + } + var verifierFactories = { + hs: createHmacVerifier, + rs: createKeyVerifier, + ps: createPSSKeyVerifier, + es: createECDSAVerifer, + none: createNoneVerifier, + } + var match = algorithm.match(/^(RS|PS|ES|HS)(256|384|512)$|^(none)$/); + if (!match) + throw typeError(MSG_INVALID_ALGORITHM, algorithm); + var algo = (match[1] || match[3]).toLowerCase(); + var bits = match[2]; + + return { + sign: signerFactories[algo](bits), + verify: verifierFactories[algo](bits), + } +}; \ No newline at end of file diff --git a/server/libs/jws/LICENSE b/server/libs/jws/LICENSE new file mode 100644 index 000000000..468d04af6 --- /dev/null +++ b/server/libs/jws/LICENSE @@ -0,0 +1,17 @@ +Copyright (c) 2013 Brian J. Brennan + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the +Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/server/libs/jws/index.js b/server/libs/jws/index.js new file mode 100644 index 000000000..6272349d2 --- /dev/null +++ b/server/libs/jws/index.js @@ -0,0 +1,27 @@ +// +// used by jsonwebtoken +// Source: https://github.com/auth0/node-jws +// + +/*global exports*/ +var SignStream = require('./lib/sign-stream'); +var VerifyStream = require('./lib/verify-stream'); + +var ALGORITHMS = [ + 'HS256', 'HS384', 'HS512', + 'RS256', 'RS384', 'RS512', + 'PS256', 'PS384', 'PS512', + 'ES256', 'ES384', 'ES512' +]; + +exports.ALGORITHMS = ALGORITHMS; +exports.sign = SignStream.sign; +exports.verify = VerifyStream.verify; +exports.decode = VerifyStream.decode; +exports.isValid = VerifyStream.isValid; +exports.createSign = function createSign(opts) { + return new SignStream(opts); +}; +exports.createVerify = function createVerify(opts) { + return new VerifyStream(opts); +}; \ No newline at end of file diff --git a/server/libs/jws/lib/data-stream.js b/server/libs/jws/lib/data-stream.js new file mode 100644 index 000000000..72b9a9c28 --- /dev/null +++ b/server/libs/jws/lib/data-stream.js @@ -0,0 +1,55 @@ +/*global module, process*/ +var Buffer = require('safe-buffer').Buffer; +var Stream = require('stream'); +var util = require('util'); + +function DataStream(data) { + this.buffer = null; + this.writable = true; + this.readable = true; + + // No input + if (!data) { + this.buffer = Buffer.alloc(0); + return this; + } + + // Stream + if (typeof data.pipe === 'function') { + this.buffer = Buffer.alloc(0); + data.pipe(this); + return this; + } + + // Buffer or String + // or Object (assumedly a passworded key) + if (data.length || typeof data === 'object') { + this.buffer = data; + this.writable = false; + process.nextTick(function () { + this.emit('end', data); + this.readable = false; + this.emit('close'); + }.bind(this)); + return this; + } + + throw new TypeError('Unexpected data type (' + typeof data + ')'); +} +util.inherits(DataStream, Stream); + +DataStream.prototype.write = function write(data) { + this.buffer = Buffer.concat([this.buffer, Buffer.from(data)]); + this.emit('data', data); +}; + +DataStream.prototype.end = function end(data) { + if (data) + this.write(data); + this.emit('end', data); + this.emit('close'); + this.writable = false; + this.readable = false; +}; + +module.exports = DataStream; \ No newline at end of file diff --git a/server/libs/jws/lib/sign-stream.js b/server/libs/jws/lib/sign-stream.js new file mode 100644 index 000000000..4d023a105 --- /dev/null +++ b/server/libs/jws/lib/sign-stream.js @@ -0,0 +1,78 @@ +/*global module*/ +var Buffer = require('safe-buffer').Buffer; +var DataStream = require('./data-stream'); +var jwa = require('../../jwa'); +var Stream = require('stream'); +var toString = require('./tostring'); +var util = require('util'); + +function base64url(string, encoding) { + return Buffer + .from(string, encoding) + .toString('base64') + .replace(/=/g, '') + .replace(/\+/g, '-') + .replace(/\//g, '_'); +} + +function jwsSecuredInput(header, payload, encoding) { + encoding = encoding || 'utf8'; + var encodedHeader = base64url(toString(header), 'binary'); + var encodedPayload = base64url(toString(payload), encoding); + return util.format('%s.%s', encodedHeader, encodedPayload); +} + +function jwsSign(opts) { + var header = opts.header; + var payload = opts.payload; + var secretOrKey = opts.secret || opts.privateKey; + var encoding = opts.encoding; + var algo = jwa(header.alg); + var securedInput = jwsSecuredInput(header, payload, encoding); + var signature = algo.sign(securedInput, secretOrKey); + return util.format('%s.%s', securedInput, signature); +} + +function SignStream(opts) { + var secret = opts.secret || opts.privateKey || opts.key; + var secretStream = new DataStream(secret); + this.readable = true; + this.header = opts.header; + this.encoding = opts.encoding; + this.secret = this.privateKey = this.key = secretStream; + this.payload = new DataStream(opts.payload); + this.secret.once('close', function () { + if (!this.payload.writable && this.readable) + this.sign(); + }.bind(this)); + + this.payload.once('close', function () { + if (!this.secret.writable && this.readable) + this.sign(); + }.bind(this)); +} +util.inherits(SignStream, Stream); + +SignStream.prototype.sign = function sign() { + try { + var signature = jwsSign({ + header: this.header, + payload: this.payload.buffer, + secret: this.secret.buffer, + encoding: this.encoding + }); + this.emit('done', signature); + this.emit('data', signature); + this.emit('end'); + this.readable = false; + return signature; + } catch (e) { + this.readable = false; + this.emit('error', e); + this.emit('close'); + } +}; + +SignStream.sign = jwsSign; + +module.exports = SignStream; \ No newline at end of file diff --git a/server/libs/jws/lib/tostring.js b/server/libs/jws/lib/tostring.js new file mode 100644 index 000000000..c2f6999b2 --- /dev/null +++ b/server/libs/jws/lib/tostring.js @@ -0,0 +1,10 @@ +/*global module*/ +var Buffer = require('buffer').Buffer; + +module.exports = function toString(obj) { + if (typeof obj === 'string') + return obj; + if (typeof obj === 'number' || Buffer.isBuffer(obj)) + return obj.toString(); + return JSON.stringify(obj); +}; \ No newline at end of file diff --git a/server/libs/jws/lib/verify-stream.js b/server/libs/jws/lib/verify-stream.js new file mode 100644 index 000000000..b8b79d29f --- /dev/null +++ b/server/libs/jws/lib/verify-stream.js @@ -0,0 +1,120 @@ +/*global module*/ +var Buffer = require('safe-buffer').Buffer; +var DataStream = require('./data-stream'); +var jwa = require('../../jwa'); +var Stream = require('stream'); +var toString = require('./tostring'); +var util = require('util'); +var JWS_REGEX = /^[a-zA-Z0-9\-_]+?\.[a-zA-Z0-9\-_]+?\.([a-zA-Z0-9\-_]+)?$/; + +function isObject(thing) { + return Object.prototype.toString.call(thing) === '[object Object]'; +} + +function safeJsonParse(thing) { + if (isObject(thing)) + return thing; + try { return JSON.parse(thing); } + catch (e) { return undefined; } +} + +function headerFromJWS(jwsSig) { + var encodedHeader = jwsSig.split('.', 1)[0]; + return safeJsonParse(Buffer.from(encodedHeader, 'base64').toString('binary')); +} + +function securedInputFromJWS(jwsSig) { + return jwsSig.split('.', 2).join('.'); +} + +function signatureFromJWS(jwsSig) { + return jwsSig.split('.')[2]; +} + +function payloadFromJWS(jwsSig, encoding) { + encoding = encoding || 'utf8'; + var payload = jwsSig.split('.')[1]; + return Buffer.from(payload, 'base64').toString(encoding); +} + +function isValidJws(string) { + return JWS_REGEX.test(string) && !!headerFromJWS(string); +} + +function jwsVerify(jwsSig, algorithm, secretOrKey) { + if (!algorithm) { + var err = new Error("Missing algorithm parameter for jws.verify"); + err.code = "MISSING_ALGORITHM"; + throw err; + } + jwsSig = toString(jwsSig); + var signature = signatureFromJWS(jwsSig); + var securedInput = securedInputFromJWS(jwsSig); + var algo = jwa(algorithm); + return algo.verify(securedInput, signature, secretOrKey); +} + +function jwsDecode(jwsSig, opts) { + opts = opts || {}; + jwsSig = toString(jwsSig); + + if (!isValidJws(jwsSig)) + return null; + + var header = headerFromJWS(jwsSig); + + if (!header) + return null; + + var payload = payloadFromJWS(jwsSig); + if (header.typ === 'JWT' || opts.json) + payload = JSON.parse(payload, opts.encoding); + + return { + header: header, + payload: payload, + signature: signatureFromJWS(jwsSig) + }; +} + +function VerifyStream(opts) { + opts = opts || {}; + var secretOrKey = opts.secret || opts.publicKey || opts.key; + var secretStream = new DataStream(secretOrKey); + this.readable = true; + this.algorithm = opts.algorithm; + this.encoding = opts.encoding; + this.secret = this.publicKey = this.key = secretStream; + this.signature = new DataStream(opts.signature); + this.secret.once('close', function () { + if (!this.signature.writable && this.readable) + this.verify(); + }.bind(this)); + + this.signature.once('close', function () { + if (!this.secret.writable && this.readable) + this.verify(); + }.bind(this)); +} +util.inherits(VerifyStream, Stream); +VerifyStream.prototype.verify = function verify() { + try { + var valid = jwsVerify(this.signature.buffer, this.algorithm, this.key.buffer); + var obj = jwsDecode(this.signature.buffer, this.encoding); + this.emit('done', valid, obj); + this.emit('data', valid); + this.emit('end'); + this.readable = false; + return valid; + } catch (e) { + this.readable = false; + this.emit('error', e); + this.emit('close'); + } +}; + +VerifyStream.decode = jwsDecode; +VerifyStream.isValid = isValidJws; +VerifyStream.verify = jwsVerify; + +module.exports = VerifyStream; \ No newline at end of file diff --git a/server/libs/lodash.once/LICENSE b/server/libs/lodash.once/LICENSE new file mode 100644 index 000000000..e0c69d560 --- /dev/null +++ b/server/libs/lodash.once/LICENSE @@ -0,0 +1,47 @@ +Copyright jQuery Foundation and other contributors + +Based on Underscore.js, copyright Jeremy Ashkenas, +DocumentCloud and Investigative Reporters & Editors + +This software consists of voluntary contributions made by many +individuals. For exact contribution history, see the revision history +available at https://github.com/lodash/lodash + +The following license applies to all parts of this software except as +documented below: + +==== + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +==== + +Copyright and related rights for sample code are waived via CC0. Sample +code is defined as all source code displayed within the prose of the +documentation. + +CC0: http://creativecommons.org/publicdomain/zero/1.0/ + +==== + +Files located in the node_modules and vendor directories are externally +maintained libraries used by this software which have their own +licenses; we recommend you read them, as their terms may differ from the +terms above. diff --git a/server/libs/lodash.once/index.js b/server/libs/lodash.once/index.js new file mode 100644 index 000000000..0b6ea6c2a --- /dev/null +++ b/server/libs/lodash.once/index.js @@ -0,0 +1,298 @@ +// +// used by jsonwebtoken +// + +/** + * lodash (Custom Build) + * Build: `lodash modularize exports="npm" -o ./` + * Copyright jQuery Foundation and other contributors + * Released under MIT license + * Based on Underscore.js 1.8.3 + * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors + */ + +/** Used as the `TypeError` message for "Functions" methods. */ +var FUNC_ERROR_TEXT = 'Expected a function'; + +/** Used as references for various `Number` constants. */ +var INFINITY = 1 / 0, + MAX_INTEGER = 1.7976931348623157e+308, + NAN = 0 / 0; + +/** `Object#toString` result references. */ +var symbolTag = '[object Symbol]'; + +/** Used to match leading and trailing whitespace. */ +var reTrim = /^\s+|\s+$/g; + +/** Used to detect bad signed hexadecimal string values. */ +var reIsBadHex = /^[-+]0x[0-9a-f]+$/i; + +/** Used to detect binary string values. */ +var reIsBinary = /^0b[01]+$/i; + +/** Used to detect octal string values. */ +var reIsOctal = /^0o[0-7]+$/i; + +/** Built-in method references without a dependency on `root`. */ +var freeParseInt = parseInt; + +/** Used for built-in method references. */ +var objectProto = Object.prototype; + +/** + * Used to resolve the + * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring) + * of values. + */ +var objectToString = objectProto.toString; + +/** + * Creates a function that invokes `func`, with the `this` binding and arguments + * of the created function, while it's called less than `n` times. Subsequent + * calls to the created function return the result of the last `func` invocation. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Function + * @param {number} n The number of calls at which `func` is no longer invoked. + * @param {Function} func The function to restrict. + * @returns {Function} Returns the new restricted function. + * @example + * + * jQuery(element).on('click', _.before(5, addContactToList)); + * // => Allows adding up to 4 contacts to the list. + */ +function before(n, func) { + var result; + if (typeof func != 'function') { + throw new TypeError(FUNC_ERROR_TEXT); + } + n = toInteger(n); + return function () { + if (--n > 0) { + result = func.apply(this, arguments); + } + if (n <= 1) { + func = undefined; + } + return result; + }; +} + +/** + * Creates a function that is restricted to invoking `func` once. Repeat calls + * to the function return the value of the first invocation. The `func` is + * invoked with the `this` binding and arguments of the created function. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Function + * @param {Function} func The function to restrict. + * @returns {Function} Returns the new restricted function. + * @example + * + * var initialize = _.once(createApplication); + * initialize(); + * initialize(); + * // => `createApplication` is invoked once + */ +function once(func) { + return before(2, func); +} + +/** + * Checks if `value` is the + * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types) + * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`) + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an object, else `false`. + * @example + * + * _.isObject({}); + * // => true + * + * _.isObject([1, 2, 3]); + * // => true + * + * _.isObject(_.noop); + * // => true + * + * _.isObject(null); + * // => false + */ +function isObject(value) { + var type = typeof value; + return !!value && (type == 'object' || type == 'function'); +} + +/** + * Checks if `value` is object-like. A value is object-like if it's not `null` + * and has a `typeof` result of "object". + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is object-like, else `false`. + * @example + * + * _.isObjectLike({}); + * // => true + * + * _.isObjectLike([1, 2, 3]); + * // => true + * + * _.isObjectLike(_.noop); + * // => false + * + * _.isObjectLike(null); + * // => false + */ +function isObjectLike(value) { + return !!value && typeof value == 'object'; +} + +/** + * Checks if `value` is classified as a `Symbol` primitive or object. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a symbol, else `false`. + * @example + * + * _.isSymbol(Symbol.iterator); + * // => true + * + * _.isSymbol('abc'); + * // => false + */ +function isSymbol(value) { + return typeof value == 'symbol' || + (isObjectLike(value) && objectToString.call(value) == symbolTag); +} + +/** + * Converts `value` to a finite number. + * + * @static + * @memberOf _ + * @since 4.12.0 + * @category Lang + * @param {*} value The value to convert. + * @returns {number} Returns the converted number. + * @example + * + * _.toFinite(3.2); + * // => 3.2 + * + * _.toFinite(Number.MIN_VALUE); + * // => 5e-324 + * + * _.toFinite(Infinity); + * // => 1.7976931348623157e+308 + * + * _.toFinite('3.2'); + * // => 3.2 + */ +function toFinite(value) { + if (!value) { + return value === 0 ? value : 0; + } + value = toNumber(value); + if (value === INFINITY || value === -INFINITY) { + var sign = (value < 0 ? -1 : 1); + return sign * MAX_INTEGER; + } + return value === value ? value : 0; +} + +/** + * Converts `value` to an integer. + * + * **Note:** This method is loosely based on + * [`ToInteger`](http://www.ecma-international.org/ecma-262/7.0/#sec-tointeger). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to convert. + * @returns {number} Returns the converted integer. + * @example + * + * _.toInteger(3.2); + * // => 3 + * + * _.toInteger(Number.MIN_VALUE); + * // => 0 + * + * _.toInteger(Infinity); + * // => 1.7976931348623157e+308 + * + * _.toInteger('3.2'); + * // => 3 + */ +function toInteger(value) { + var result = toFinite(value), + remainder = result % 1; + + return result === result ? (remainder ? result - remainder : result) : 0; +} + +/** + * Converts `value` to a number. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to process. + * @returns {number} Returns the number. + * @example + * + * _.toNumber(3.2); + * // => 3.2 + * + * _.toNumber(Number.MIN_VALUE); + * // => 5e-324 + * + * _.toNumber(Infinity); + * // => Infinity + * + * _.toNumber('3.2'); + * // => 3.2 + */ +function toNumber(value) { + if (typeof value == 'number') { + return value; + } + if (isSymbol(value)) { + return NAN; + } + if (isObject(value)) { + var other = typeof value.valueOf == 'function' ? value.valueOf() : value; + value = isObject(other) ? (other + '') : other; + } + if (typeof value != 'string') { + return value === 0 ? value : +value; + } + value = value.replace(reTrim, ''); + var isBinary = reIsBinary.test(value); + return (isBinary || reIsOctal.test(value)) + ? freeParseInt(value.slice(2), isBinary ? 2 : 8) + : (reIsBadHex.test(value) ? NAN : +value); +} + +module.exports = once; diff --git a/server/libs/ms/LICENSE b/server/libs/ms/LICENSE new file mode 100644 index 000000000..69b61253a --- /dev/null +++ b/server/libs/ms/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2016 Zeit, Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/server/libs/ms/index.js b/server/libs/ms/index.js new file mode 100644 index 000000000..31a3ec72d --- /dev/null +++ b/server/libs/ms/index.js @@ -0,0 +1,153 @@ +// +// used by jsonwebtoken +// Source: https://github.com/vercel/ms +// + +var s = 1000; +var m = s * 60; +var h = m * 60; +var d = h * 24; +var y = d * 365.25; + +/** + * Parse or format the given `val`. + * + * Options: + * + * - `long` verbose formatting [false] + * + * @param {String|Number} val + * @param {Object} [options] + * @throws {Error} throw an error if val is not a non-empty string or a number + * @return {String|Number} + * @api public + */ + +module.exports = function (val, options) { + options = options || {}; + var type = typeof val; + if (type === 'string' && val.length > 0) { + return parse(val); + } else if (type === 'number' && isNaN(val) === false) { + return options.long ? fmtLong(val) : fmtShort(val); + } + throw new Error( + 'val is not a non-empty string or a valid number. val=' + + JSON.stringify(val) + ); +}; + +/** + * Parse the given `str` and return milliseconds. + * + * @param {String} str + * @return {Number} + * @api private + */ + +function parse(str) { + str = String(str); + if (str.length > 100) { + return; + } + var match = /^((?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|years?|yrs?|y)?$/i.exec( + str + ); + if (!match) { + return; + } + var n = parseFloat(match[1]); + var type = (match[2] || 'ms').toLowerCase(); + switch (type) { + case 'years': + case 'year': + case 'yrs': + case 'yr': + case 'y': + return n * y; + case 'days': + case 'day': + case 'd': + return n * d; + case 'hours': + case 'hour': + case 'hrs': + case 'hr': + case 'h': + return n * h; + case 'minutes': + case 'minute': + case 'mins': + case 'min': + case 'm': + return n * m; + case 'seconds': + case 'second': + case 'secs': + case 'sec': + case 's': + return n * s; + case 'milliseconds': + case 'millisecond': + case 'msecs': + case 'msec': + case 'ms': + return n; + default: + return undefined; + } +} + +/** + * Short format for `ms`. + * + * @param {Number} ms + * @return {String} + * @api private + */ + +function fmtShort(ms) { + if (ms >= d) { + return Math.round(ms / d) + 'd'; + } + if (ms >= h) { + return Math.round(ms / h) + 'h'; + } + if (ms >= m) { + return Math.round(ms / m) + 'm'; + } + if (ms >= s) { + return Math.round(ms / s) + 's'; + } + return ms + 'ms'; +} + +/** + * Long format for `ms`. + * + * @param {Number} ms + * @return {String} + * @api private + */ + +function fmtLong(ms) { + return plural(ms, d, 'day') || + plural(ms, h, 'hour') || + plural(ms, m, 'minute') || + plural(ms, s, 'second') || + ms + ' ms'; +} + +/** + * Pluralization helper. + */ + +function plural(ms, n, name) { + if (ms < n) { + return; + } + if (ms < n * 1.5) { + return Math.floor(ms / n) + ' ' + name; + } + return Math.ceil(ms / n) + ' ' + name + 's'; +} From 4e1aacb44fa99ecbc1b8b5cf64ba80aa9dceb992 Mon Sep 17 00:00:00 2001 From: advplyr Date: Wed, 6 Jul 2022 18:56:13 -0500 Subject: [PATCH 004/100] Remove command-line-args dependency --- package-lock.json | 34 - package.json | 1 - prod.js | 2 +- server/libs/commandLineArgs/index.js | 1399 ++++++++++++++++++++++++++ 4 files changed, 1400 insertions(+), 36 deletions(-) create mode 100644 server/libs/commandLineArgs/index.js diff --git a/package-lock.json b/package-lock.json index 700eba81c..c6cf8a006 100644 --- a/package-lock.json +++ b/package-lock.json @@ -93,11 +93,6 @@ } } }, - "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", @@ -210,17 +205,6 @@ "get-intrinsic": "^1.0.2" } }, - "command-line-args": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/command-line-args/-/command-line-args-5.2.1.tgz", - "integrity": "sha512-H4UfQhZyakIjC74I9d34fGYDwk3XpSr17QhEd0Q3I9Xq1CETHo4Hcuo87WyWHpAF1aSLjLRf5lD9ZGX2qStUvg==", - "requires": { - "array-back": "^3.1.0", - "find-replace": "^3.0.0", - "lodash.camelcase": "^4.3.0", - "typical": "^4.0.0" - } - }, "component-emitter": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", @@ -489,14 +473,6 @@ "unpipe": "~1.0.0" } }, - "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" - } - }, "follow-redirects": { "version": "1.15.1", "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.1.tgz", @@ -665,11 +641,6 @@ } } }, - "lodash.camelcase": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", - "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==" - }, "lodash.defaults": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", @@ -1018,11 +989,6 @@ "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", diff --git a/package.json b/package.json index 631144b1b..d6a346874 100644 --- a/package.json +++ b/package.json @@ -33,7 +33,6 @@ "archiver": "^5.3.0", "axios": "^0.26.1", "bcryptjs": "^2.4.3", - "command-line-args": "^5.2.0", "date-and-time": "^2.3.1", "express": "^4.17.1", "express-fileupload": "^1.2.1", diff --git a/prod.js b/prod.js index 20ea004d6..22f84234e 100644 --- a/prod.js +++ b/prod.js @@ -6,7 +6,7 @@ const optionDefinitions = [ { name: 'source', alias: 's', type: String } ] -const commandLineArgs = require('command-line-args') +const commandLineArgs = require('./server/libs/commandLineArgs') const options = commandLineArgs(optionDefinitions) const Path = require('path') diff --git a/server/libs/commandLineArgs/index.js b/server/libs/commandLineArgs/index.js new file mode 100644 index 000000000..5d727dbbd --- /dev/null +++ b/server/libs/commandLineArgs/index.js @@ -0,0 +1,1399 @@ +'use strict'; + +// +// modified for use in audiobookshelf (removed camelCase opt) +// Source: https://github.com/75lb/command-line-args +// + +/** + * Takes any input and guarantees an array back. + * + * - Converts array-like objects (e.g. `arguments`, `Set`) to a real array. + * - Converts `undefined` to an empty array. + * - Converts any another other, singular value (including `null`, objects and iterables other than `Set`) into an array containing that value. + * - Ignores input which is already an array. + * + * @module array-back + * @example + * > const arrayify = require('array-back') + * + * > arrayify(undefined) + * [] + * + * > arrayify(null) + * [ null ] + * + * > arrayify(0) + * [ 0 ] + * + * > arrayify([ 1, 2 ]) + * [ 1, 2 ] + * + * > arrayify(new Set([ 1, 2 ])) + * [ 1, 2 ] + * + * > function f(){ return arrayify(arguments); } + * > f(1,2,3) + * [ 1, 2, 3 ] + */ + +function isObject(input) { + return typeof input === 'object' && input !== null +} + +function isArrayLike(input) { + return isObject(input) && typeof input.length === 'number' +} + +/** + * @param {*} - The input value to convert to an array + * @returns {Array} + * @alias module:array-back + */ +function arrayify(input) { + if (Array.isArray(input)) { + return input + } + + if (input === undefined) { + return [] + } + + if (isArrayLike(input) || input instanceof Set) { + return Array.from(input) + } + + return [input] +} + +/** + * Takes any input and guarantees an array back. + * + * - converts array-like objects (e.g. `arguments`) to a real array + * - converts `undefined` to an empty array + * - converts any another other, singular value (including `null`) into an array containing that value + * - ignores input which is already an array + * + * @module array-back + * @example + * > const arrayify = require('array-back') + * + * > arrayify(undefined) + * [] + * + * > arrayify(null) + * [ null ] + * + * > arrayify(0) + * [ 0 ] + * + * > arrayify([ 1, 2 ]) + * [ 1, 2 ] + * + * > function f(){ return arrayify(arguments); } + * > f(1,2,3) + * [ 1, 2, 3 ] + */ + +function isObject$1(input) { + return typeof input === 'object' && input !== null +} + +function isArrayLike$1(input) { + return isObject$1(input) && typeof input.length === 'number' +} + +/** + * @param {*} - the input value to convert to an array + * @returns {Array} + * @alias module:array-back + */ +function arrayify$1(input) { + if (Array.isArray(input)) { + return input + } else { + if (input === undefined) { + return [] + } else if (isArrayLike$1(input)) { + return Array.prototype.slice.call(input) + } else { + return [input] + } + } +} + +/** + * Find and either replace or remove items in an array. + * + * @module find-replace + * @example + * > const findReplace = require('find-replace') + * > const numbers = [ 1, 2, 3] + * + * > findReplace(numbers, n => n === 2, 'two') + * [ 1, 'two', 3 ] + * + * > findReplace(numbers, n => n === 2, [ 'two', 'zwei' ]) + * [ 1, [ 'two', 'zwei' ], 3 ] + * + * > findReplace(numbers, n => n === 2, 'two', 'zwei') + * [ 1, 'two', 'zwei', 3 ] + * + * > findReplace(numbers, n => n === 2) // no replacement, so remove + * [ 1, 3 ] + */ + +/** + * @param {array} - The input array + * @param {testFn} - A predicate function which, if returning `true` causes the current item to be operated on. + * @param [replaceWith] {...any} - If specified, found values will be replaced with these values, else removed. + * @returns {array} + * @alias module:find-replace + */ +function findReplace(array, testFn) { + const found = []; + const replaceWiths = arrayify$1(arguments); + replaceWiths.splice(0, 2); + + arrayify$1(array).forEach((value, index) => { + let expanded = []; + replaceWiths.forEach(replaceWith => { + if (typeof replaceWith === 'function') { + expanded = expanded.concat(replaceWith(value)); + } else { + expanded.push(replaceWith); + } + }); + + if (testFn(value)) { + found.push({ + index: index, + replaceWithValue: expanded + }); + } + }); + + found.reverse().forEach(item => { + const spliceArgs = [item.index, 1].concat(item.replaceWithValue); + array.splice.apply(array, spliceArgs); + }); + + return array +} + +/** + * Some useful tools for working with `process.argv`. + * + * @module argv-tools + * @typicalName argvTools + * @example + * const argvTools = require('argv-tools') + */ + +/** + * Regular expressions for matching option formats. + * @static + */ +const re = { + short: /^-([^\d-])$/, + long: /^--(\S+)/, + combinedShort: /^-[^\d-]{2,}$/, + optEquals: /^(--\S+?)=(.*)/ +}; + +/** + * Array subclass encapsulating common operations on `process.argv`. + * @static + */ +class ArgvArray extends Array { + /** + * Clears the array has loads the supplied input. + * @param {string[]} argv - The argv list to load. Defaults to `process.argv`. + */ + load(argv) { + this.clear(); + if (argv && argv !== process.argv) { + argv = arrayify(argv); + } else { + /* if no argv supplied, assume we are parsing process.argv */ + argv = process.argv.slice(0); + const deleteCount = process.execArgv.some(isExecArg) ? 1 : 2; + argv.splice(0, deleteCount); + } + argv.forEach(arg => this.push(String(arg))); + } + + /** + * Clear the array. + */ + clear() { + this.length = 0; + } + + /** + * expand ``--option=value` style args. + */ + expandOptionEqualsNotation() { + if (this.some(arg => re.optEquals.test(arg))) { + const expandedArgs = []; + this.forEach(arg => { + const matches = arg.match(re.optEquals); + if (matches) { + expandedArgs.push(matches[1], matches[2]); + } else { + expandedArgs.push(arg); + } + }); + this.clear(); + this.load(expandedArgs); + } + } + + /** + * expand getopt-style combinedShort options. + */ + expandGetoptNotation() { + if (this.hasCombinedShortOptions()) { + findReplace(this, re.combinedShort, expandCombinedShortArg); + } + } + + /** + * Returns true if the array contains combined short options (e.g. `-ab`). + * @returns {boolean} + */ + hasCombinedShortOptions() { + return this.some(arg => re.combinedShort.test(arg)) + } + + static from(argv) { + const result = new this(); + result.load(argv); + return result + } +} + +/** + * Expand a combined short option. + * @param {string} - the string to expand, e.g. `-ab` + * @returns {string[]} + * @static + */ +function expandCombinedShortArg(arg) { + /* remove initial hypen */ + arg = arg.slice(1); + return arg.split('').map(letter => '-' + letter) +} + +/** + * Returns true if the supplied arg matches `--option=value` notation. + * @param {string} - the arg to test, e.g. `--one=something` + * @returns {boolean} + * @static + */ +function isOptionEqualsNotation(arg) { + return re.optEquals.test(arg) +} + +/** + * Returns true if the supplied arg is in either long (`--one`) or short (`-o`) format. + * @param {string} - the arg to test, e.g. `--one` + * @returns {boolean} + * @static + */ +function isOption(arg) { + return (re.short.test(arg) || re.long.test(arg)) && !re.optEquals.test(arg) +} + +/** + * Returns true if the supplied arg is in long (`--one`) format. + * @param {string} - the arg to test, e.g. `--one` + * @returns {boolean} + * @static + */ +function isLongOption(arg) { + return re.long.test(arg) && !isOptionEqualsNotation(arg) +} + +/** + * Returns the name from a long, short or `--options=value` arg. + * @param {string} - the arg to inspect, e.g. `--one` + * @returns {string} + * @static + */ +function getOptionName(arg) { + if (re.short.test(arg)) { + return arg.match(re.short)[1] + } else if (isLongOption(arg)) { + return arg.match(re.long)[1] + } else if (isOptionEqualsNotation(arg)) { + return arg.match(re.optEquals)[1].replace(/^--/, '') + } else { + return null + } +} + +function isValue(arg) { + return !(isOption(arg) || re.combinedShort.test(arg) || re.optEquals.test(arg)) +} + +function isExecArg(arg) { + return ['--eval', '-e'].indexOf(arg) > -1 || arg.startsWith('--eval=') +} + +/** + * For type-checking Javascript values. + * @module typical + * @typicalname t + * @example + * const t = require('typical') + */ + +/** + * Returns true if input is a number + * @param {*} - the input to test + * @returns {boolean} + * @static + * @example + * > t.isNumber(0) + * true + * > t.isNumber(1) + * true + * > t.isNumber(1.1) + * true + * > t.isNumber(0xff) + * true + * > t.isNumber(0644) + * true + * > t.isNumber(6.2e5) + * true + * > t.isNumber(NaN) + * false + * > t.isNumber(Infinity) + * false + */ +function isNumber(n) { + return !isNaN(parseFloat(n)) && isFinite(n) +} + +/** + * A plain object is a simple object literal, it is not an instance of a class. Returns true if the input `typeof` is `object` and directly decends from `Object`. + * + * @param {*} - the input to test + * @returns {boolean} + * @static + * @example + * > t.isPlainObject({ something: 'one' }) + * true + * > t.isPlainObject(new Date()) + * false + * > t.isPlainObject([ 0, 1 ]) + * false + * > t.isPlainObject(/test/) + * false + * > t.isPlainObject(1) + * false + * > t.isPlainObject('one') + * false + * > t.isPlainObject(null) + * false + * > t.isPlainObject((function * () {})()) + * false + * > t.isPlainObject(function * () {}) + * false + */ +function isPlainObject(input) { + return input !== null && typeof input === 'object' && input.constructor === Object +} + +/** + * An array-like value has all the properties of an array, but is not an array instance. Examples in the `arguments` object. Returns true if the input value is an object, not null and has a `length` property with a numeric value. + * + * @param {*} - the input to test + * @returns {boolean} + * @static + * @example + * function sum(x, y){ + * console.log(t.isArrayLike(arguments)) + * // prints `true` + * } + */ +function isArrayLike$2(input) { + return isObject$2(input) && typeof input.length === 'number' +} + +/** + * returns true if the typeof input is `'object'`, but not null! + * @param {*} - the input to test + * @returns {boolean} + * @static + */ +function isObject$2(input) { + return typeof input === 'object' && input !== null +} + +/** + * Returns true if the input value is defined + * @param {*} - the input to test + * @returns {boolean} + * @static + */ +function isDefined(input) { + return typeof input !== 'undefined' +} + +/** + * Returns true if the input value is a string + * @param {*} - the input to test + * @returns {boolean} + * @static + */ +function isString(input) { + return typeof input === 'string' +} + +/** + * Returns true if the input value is a boolean + * @param {*} - the input to test + * @returns {boolean} + * @static + */ +function isBoolean(input) { + return typeof input === 'boolean' +} + +/** + * Returns true if the input value is a function + * @param {*} - the input to test + * @returns {boolean} + * @static + */ +function isFunction(input) { + return typeof input === 'function' +} + +/** + * Returns true if the input value is an es2015 `class`. + * @param {*} - the input to test + * @returns {boolean} + * @static + */ +function isClass(input) { + if (isFunction(input)) { + return /^class /.test(Function.prototype.toString.call(input)) + } else { + return false + } +} + +/** + * Returns true if the input is a string, number, symbol, boolean, null or undefined value. + * @param {*} - the input to test + * @returns {boolean} + * @static + */ +function isPrimitive(input) { + if (input === null) return true + switch (typeof input) { + case 'string': + case 'number': + case 'symbol': + case 'undefined': + case 'boolean': + return true + default: + return false + } +} + +/** + * Returns true if the input is a Promise. + * @param {*} - the input to test + * @returns {boolean} + * @static + */ +function isPromise(input) { + if (input) { + const isPromise = isDefined(Promise) && input instanceof Promise; + const isThenable = input.then && typeof input.then === 'function'; + return !!(isPromise || isThenable) + } else { + return false + } +} + +/** + * Returns true if the input is an iterable (`Map`, `Set`, `Array`, Generator etc.). + * @param {*} - the input to test + * @returns {boolean} + * @static + * @example + * > t.isIterable('string') + * true + * > t.isIterable(new Map()) + * true + * > t.isIterable([]) + * true + * > t.isIterable((function * () {})()) + * true + * > t.isIterable(Promise.resolve()) + * false + * > t.isIterable(Promise) + * false + * > t.isIterable(true) + * false + * > t.isIterable({}) + * false + * > t.isIterable(0) + * false + * > t.isIterable(1.1) + * false + * > t.isIterable(NaN) + * false + * > t.isIterable(Infinity) + * false + * > t.isIterable(function () {}) + * false + * > t.isIterable(Date) + * false + * > t.isIterable() + * false + * > t.isIterable({ then: function () {} }) + * false + */ +function isIterable(input) { + if (input === null || !isDefined(input)) { + return false + } else { + return ( + typeof input[Symbol.iterator] === 'function' || + typeof input[Symbol.asyncIterator] === 'function' + ) + } +} + +var t = { + isNumber, + isString, + isBoolean, + isPlainObject, + isArrayLike: isArrayLike$2, + isObject: isObject$2, + isDefined, + isFunction, + isClass, + isPrimitive, + isPromise, + isIterable +}; + +/** + * @module option-definition + */ + +/** + * Describes a command-line option. Additionally, if generating a usage guide with [command-line-usage](https://github.com/75lb/command-line-usage) you could optionally add `description` and `typeLabel` properties to each definition. + * + * @alias module:option-definition + * @typicalname option + */ +class OptionDefinition { + constructor(definition) { + /** + * The only required definition property is `name`, so the simplest working example is + * ```js + * const optionDefinitions = [ + * { name: 'file' }, + * { name: 'depth' } + * ] + * ``` + * + * Where a `type` property is not specified it will default to `String`. + * + * | # | argv input | commandLineArgs() output | + * | --- | -------------------- | ------------ | + * | 1 | `--file` | `{ file: null }` | + * | 2 | `--file lib.js` | `{ file: 'lib.js' }` | + * | 3 | `--depth 2` | `{ depth: '2' }` | + * + * Unicode option names and aliases are valid, for example: + * ```js + * const optionDefinitions = [ + * { name: 'один' }, + * { name: '两' }, + * { name: 'три', alias: 'т' } + * ] + * ``` + * @type {string} + */ + this.name = definition.name; + + /** + * The `type` value is a setter function (you receive the output from this), enabling you to be specific about the type and value received. + * + * The most common values used are `String` (the default), `Number` and `Boolean` but you can use a custom function, for example: + * + * ```js + * const fs = require('fs') + * + * class FileDetails { + * constructor (filename) { + * this.filename = filename + * this.exists = fs.existsSync(filename) + * } + * } + * + * const cli = commandLineArgs([ + * { name: 'file', type: filename => new FileDetails(filename) }, + * { name: 'depth', type: Number } + * ]) + * ``` + * + * | # | argv input | commandLineArgs() output | + * | --- | ----------------- | ------------ | + * | 1 | `--file asdf.txt` | `{ file: { filename: 'asdf.txt', exists: false } }` | + * + * The `--depth` option expects a `Number`. If no value was set, you will receive `null`. + * + * | # | argv input | commandLineArgs() output | + * | --- | ----------------- | ------------ | + * | 2 | `--depth` | `{ depth: null }` | + * | 3 | `--depth 2` | `{ depth: 2 }` | + * + * @type {function} + * @default String + */ + this.type = definition.type || String; + + /** + * getopt-style short option names. Can be any single character (unicode included) except a digit or hyphen. + * + * ```js + * const optionDefinitions = [ + * { name: 'hot', alias: 'h', type: Boolean }, + * { name: 'discount', alias: 'd', type: Boolean }, + * { name: 'courses', alias: 'c' , type: Number } + * ] + * ``` + * + * | # | argv input | commandLineArgs() output | + * | --- | ------------ | ------------ | + * | 1 | `-hcd` | `{ hot: true, courses: null, discount: true }` | + * | 2 | `-hdc 3` | `{ hot: true, discount: true, courses: 3 }` | + * + * @type {string} + */ + this.alias = definition.alias; + + /** + * Set this flag if the option takes a list of values. You will receive an array of values, each passed through the `type` function (if specified). + * + * ```js + * const optionDefinitions = [ + * { name: 'files', type: String, multiple: true } + * ] + * ``` + * + * Note, examples 1 and 3 below demonstrate "greedy" parsing which can be disabled by using `lazyMultiple`. + * + * | # | argv input | commandLineArgs() output | + * | --- | ------------ | ------------ | + * | 1 | `--files one.js two.js` | `{ files: [ 'one.js', 'two.js' ] }` | + * | 2 | `--files one.js --files two.js` | `{ files: [ 'one.js', 'two.js' ] }` | + * | 3 | `--files *` | `{ files: [ 'one.js', 'two.js' ] }` | + * + * @type {boolean} + */ + this.multiple = definition.multiple; + + /** + * Identical to `multiple` but with greedy parsing disabled. + * + * ```js + * const optionDefinitions = [ + * { name: 'files', lazyMultiple: true }, + * { name: 'verbose', alias: 'v', type: Boolean, lazyMultiple: true } + * ] + * ``` + * + * | # | argv input | commandLineArgs() output | + * | --- | ------------ | ------------ | + * | 1 | `--files one.js --files two.js` | `{ files: [ 'one.js', 'two.js' ] }` | + * | 2 | `-vvv` | `{ verbose: [ true, true, true ] }` | + * + * @type {boolean} + */ + this.lazyMultiple = definition.lazyMultiple; + + /** + * Any values unaccounted for by an option definition will be set on the `defaultOption`. This flag is typically set on the most commonly-used option to make for more concise usage (i.e. `$ example *.js` instead of `$ example --files *.js`). + * + * ```js + * const optionDefinitions = [ + * { name: 'files', multiple: true, defaultOption: true } + * ] + * ``` + * + * | # | argv input | commandLineArgs() output | + * | --- | ------------ | ------------ | + * | 1 | `--files one.js two.js` | `{ files: [ 'one.js', 'two.js' ] }` | + * | 2 | `one.js two.js` | `{ files: [ 'one.js', 'two.js' ] }` | + * | 3 | `*` | `{ files: [ 'one.js', 'two.js' ] }` | + * + * @type {boolean} + */ + this.defaultOption = definition.defaultOption; + + /** + * An initial value for the option. + * + * ```js + * const optionDefinitions = [ + * { name: 'files', multiple: true, defaultValue: [ 'one.js' ] }, + * { name: 'max', type: Number, defaultValue: 3 } + * ] + * ``` + * + * | # | argv input | commandLineArgs() output | + * | --- | ------------ | ------------ | + * | 1 | | `{ files: [ 'one.js' ], max: 3 }` | + * | 2 | `--files two.js` | `{ files: [ 'two.js' ], max: 3 }` | + * | 3 | `--max 4` | `{ files: [ 'one.js' ], max: 4 }` | + * + * @type {*} + */ + this.defaultValue = definition.defaultValue; + + /** + * When your app has a large amount of options it makes sense to organise them in groups. + * + * There are two automatic groups: `_all` (contains all options) and `_none` (contains options without a `group` specified in their definition). + * + * ```js + * const optionDefinitions = [ + * { name: 'verbose', group: 'standard' }, + * { name: 'help', group: [ 'standard', 'main' ] }, + * { name: 'compress', group: [ 'server', 'main' ] }, + * { name: 'static', group: 'server' }, + * { name: 'debug' } + * ] + * ``` + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
#Command LinecommandLineArgs() output
1--verbose

+    *{
+    *  _all: { verbose: true },
+    *  standard: { verbose: true }
+    *}
+    *
2--debug

+    *{
+    *  _all: { debug: true },
+    *  _none: { debug: true }
+    *}
+    *
3--verbose --debug --compress

+    *{
+    *  _all: {
+    *    verbose: true,
+    *    debug: true,
+    *    compress: true
+    *  },
+    *  standard: { verbose: true },
+    *  server: { compress: true },
+    *  main: { compress: true },
+    *  _none: { debug: true }
+    *}
+    *
4--compress

+    *{
+    *  _all: { compress: true },
+    *  server: { compress: true },
+    *  main: { compress: true }
+    *}
+    *
+ * + * @type {string|string[]} + */ + this.group = definition.group; + + /* pick up any remaining properties */ + for (const prop in definition) { + if (!this[prop]) this[prop] = definition[prop]; + } + } + + isBoolean() { + return this.type === Boolean || (t.isFunction(this.type) && this.type.name === 'Boolean') + } + + isMultiple() { + return this.multiple || this.lazyMultiple + } + + static create(def) { + const result = new this(def); + return result + } +} + +/** + * @module option-definitions + */ + +/** + * @alias module:option-definitions + */ +class Definitions extends Array { + /** + * validate option definitions + * @param {boolean} [caseInsensitive=false] - whether arguments will be parsed in a case insensitive manner + * @returns {string} + */ + validate(caseInsensitive) { + const someHaveNoName = this.some(def => !def.name); + if (someHaveNoName) { + halt( + 'INVALID_DEFINITIONS', + 'Invalid option definitions: the `name` property is required on each definition' + ); + } + + const someDontHaveFunctionType = this.some(def => def.type && typeof def.type !== 'function'); + if (someDontHaveFunctionType) { + halt( + 'INVALID_DEFINITIONS', + 'Invalid option definitions: the `type` property must be a setter fuction (default: `Boolean`)' + ); + } + + let invalidOption; + + const numericAlias = this.some(def => { + invalidOption = def; + return t.isDefined(def.alias) && t.isNumber(def.alias) + }); + if (numericAlias) { + halt( + 'INVALID_DEFINITIONS', + 'Invalid option definition: to avoid ambiguity an alias cannot be numeric [--' + invalidOption.name + ' alias is -' + invalidOption.alias + ']' + ); + } + + const multiCharacterAlias = this.some(def => { + invalidOption = def; + return t.isDefined(def.alias) && def.alias.length !== 1 + }); + if (multiCharacterAlias) { + halt( + 'INVALID_DEFINITIONS', + 'Invalid option definition: an alias must be a single character' + ); + } + + const hypenAlias = this.some(def => { + invalidOption = def; + return def.alias === '-' + }); + if (hypenAlias) { + halt( + 'INVALID_DEFINITIONS', + 'Invalid option definition: an alias cannot be "-"' + ); + } + + const duplicateName = hasDuplicates(this.map(def => caseInsensitive ? def.name.toLowerCase() : def.name)); + if (duplicateName) { + halt( + 'INVALID_DEFINITIONS', + 'Two or more option definitions have the same name' + ); + } + + const duplicateAlias = hasDuplicates(this.map(def => caseInsensitive && t.isDefined(def.alias) ? def.alias.toLowerCase() : def.alias)); + if (duplicateAlias) { + halt( + 'INVALID_DEFINITIONS', + 'Two or more option definitions have the same alias' + ); + } + + const duplicateDefaultOption = this.filter(def => def.defaultOption === true).length > 1; + if (duplicateDefaultOption) { + halt( + 'INVALID_DEFINITIONS', + 'Only one option definition can be the defaultOption' + ); + } + + const defaultBoolean = this.some(def => { + invalidOption = def; + return def.isBoolean() && def.defaultOption + }); + if (defaultBoolean) { + halt( + 'INVALID_DEFINITIONS', + `A boolean option ["${invalidOption.name}"] can not also be the defaultOption.` + ); + } + } + + /** + * Get definition by option arg (e.g. `--one` or `-o`) + * @param {string} [arg] the argument name to get the definition for + * @param {boolean} [caseInsensitive] whether to use case insensitive comparisons when finding the appropriate definition + * @returns {Definition} + */ + get(arg, caseInsensitive) { + if (isOption(arg)) { + if (re.short.test(arg)) { + const shortOptionName = getOptionName(arg); + if (caseInsensitive) { + const lowercaseShortOptionName = shortOptionName.toLowerCase(); + return this.find(def => t.isDefined(def.alias) && def.alias.toLowerCase() === lowercaseShortOptionName) + } else { + return this.find(def => def.alias === shortOptionName) + } + } else { + const optionName = getOptionName(arg); + if (caseInsensitive) { + const lowercaseOptionName = optionName.toLowerCase(); + return this.find(def => def.name.toLowerCase() === lowercaseOptionName) + } else { + return this.find(def => def.name === optionName) + } + } + } else { + return this.find(def => def.name === arg) + } + } + + getDefault() { + return this.find(def => def.defaultOption === true) + } + + isGrouped() { + return this.some(def => def.group) + } + + whereGrouped() { + return this.filter(containsValidGroup) + } + + whereNotGrouped() { + return this.filter(def => !containsValidGroup(def)) + } + + whereDefaultValueSet() { + return this.filter(def => t.isDefined(def.defaultValue)) + } + + static from(definitions, caseInsensitive) { + if (definitions instanceof this) return definitions + const result = super.from(arrayify(definitions), def => OptionDefinition.create(def)); + result.validate(caseInsensitive); + return result + } +} + +function halt(name, message) { + const err = new Error(message); + err.name = name; + throw err +} + +function containsValidGroup(def) { + return arrayify(def.group).some(group => group) +} + +function hasDuplicates(array) { + const items = {}; + for (let i = 0; i < array.length; i++) { + const value = array[i]; + if (items[value]) { + return true + } else { + if (t.isDefined(value)) items[value] = true; + } + } +} + +/** + * @module argv-parser + */ + +/** + * @alias module:argv-parser + */ +class ArgvParser { + /** + * @param {OptionDefinitions} - Definitions array + * @param {object} [options] - Options + * @param {string[]} [options.argv] - Overrides `process.argv` + * @param {boolean} [options.stopAtFirstUnknown] - + * @param {boolean} [options.caseInsensitive] - Arguments will be parsed in a case insensitive manner. Defaults to false. + */ + constructor(definitions, options) { + this.options = Object.assign({}, options); + /** + * Option Definitions + */ + this.definitions = Definitions.from(definitions, this.options.caseInsensitive); + + /** + * Argv + */ + this.argv = ArgvArray.from(this.options.argv); + if (this.argv.hasCombinedShortOptions()) { + findReplace(this.argv, re.combinedShort.test.bind(re.combinedShort), arg => { + arg = arg.slice(1); + return arg.split('').map(letter => ({ origArg: `-${arg}`, arg: '-' + letter })) + }); + } + } + + /** + * Yields one `{ event, name, value, arg, def }` argInfo object for each arg in `process.argv` (or `options.argv`). + */ + *[Symbol.iterator]() { + const definitions = this.definitions; + + let def; + let value; + let name; + let event; + let singularDefaultSet = false; + let unknownFound = false; + let origArg; + + for (let arg of this.argv) { + if (t.isPlainObject(arg)) { + origArg = arg.origArg; + arg = arg.arg; + } + + if (unknownFound && this.options.stopAtFirstUnknown) { + yield { event: 'unknown_value', arg, name: '_unknown', value: undefined }; + continue + } + + /* handle long or short option */ + if (isOption(arg)) { + def = definitions.get(arg, this.options.caseInsensitive); + value = undefined; + if (def) { + value = def.isBoolean() ? true : null; + event = 'set'; + } else { + event = 'unknown_option'; + } + + /* handle --option-value notation */ + } else if (isOptionEqualsNotation(arg)) { + const matches = arg.match(re.optEquals); + def = definitions.get(matches[1], this.options.caseInsensitive); + if (def) { + if (def.isBoolean()) { + yield { event: 'unknown_value', arg, name: '_unknown', value, def }; + event = 'set'; + value = true; + } else { + event = 'set'; + value = matches[2]; + } + } else { + event = 'unknown_option'; + } + + /* handle value */ + } else if (isValue(arg)) { + if (def) { + value = arg; + event = 'set'; + } else { + /* get the defaultOption */ + def = this.definitions.getDefault(); + if (def && !singularDefaultSet) { + value = arg; + event = 'set'; + } else { + event = 'unknown_value'; + def = undefined; + } + } + } + + name = def ? def.name : '_unknown'; + const argInfo = { event, arg, name, value, def }; + if (origArg) { + argInfo.subArg = arg; + argInfo.arg = origArg; + } + yield argInfo; + + /* unknownFound logic */ + if (name === '_unknown') unknownFound = true; + + /* singularDefaultSet logic */ + if (def && def.defaultOption && !def.isMultiple() && event === 'set') singularDefaultSet = true; + + /* reset values once consumed and yielded */ + if (def && def.isBoolean()) def = undefined; + /* reset the def if it's a singular which has been set */ + if (def && !def.multiple && t.isDefined(value) && value !== null) { + def = undefined; + } + value = undefined; + event = undefined; + name = undefined; + origArg = undefined; + } + } +} + +const _value = new WeakMap(); + +/** + * Encapsulates behaviour (defined by an OptionDefinition) when setting values + */ +class Option { + constructor(definition) { + this.definition = new OptionDefinition(definition); + this.state = null; /* set or default */ + this.resetToDefault(); + } + + get() { + return _value.get(this) + } + + set(val) { + this._set(val, 'set'); + } + + _set(val, state) { + const def = this.definition; + if (def.isMultiple()) { + /* don't add null or undefined to a multiple */ + if (val !== null && val !== undefined) { + const arr = this.get(); + if (this.state === 'default') arr.length = 0; + arr.push(def.type(val)); + this.state = state; + } + } else { + /* throw if already set on a singlar defaultOption */ + if (!def.isMultiple() && this.state === 'set') { + const err = new Error(`Singular option already set [${this.definition.name}=${this.get()}]`); + err.name = 'ALREADY_SET'; + err.value = val; + err.optionName = def.name; + throw err + } else if (val === null || val === undefined) { + _value.set(this, val); + // /* required to make 'partial: defaultOption with value equal to defaultValue 2' pass */ + // if (!(def.defaultOption && !def.isMultiple())) { + // this.state = state + // } + } else { + _value.set(this, def.type(val)); + this.state = state; + } + } + } + + resetToDefault() { + if (t.isDefined(this.definition.defaultValue)) { + if (this.definition.isMultiple()) { + _value.set(this, arrayify(this.definition.defaultValue).slice()); + } else { + _value.set(this, this.definition.defaultValue); + } + } else { + if (this.definition.isMultiple()) { + _value.set(this, []); + } else { + _value.set(this, null); + } + } + this.state = 'default'; + } + + static create(definition) { + definition = new OptionDefinition(definition); + if (definition.isBoolean()) { + return FlagOption.create(definition) + } else { + return new this(definition) + } + } +} + +class FlagOption extends Option { + set(val) { + super.set(true); + } + + static create(def) { + return new this(def) + } +} + +/** + * A map of { DefinitionNameString: Option }. By default, an Output has an `_unknown` property and any options with defaultValues. + */ +class Output extends Map { + constructor(definitions) { + super(); + /** + * @type {OptionDefinitions} + */ + this.definitions = Definitions.from(definitions); + + /* by default, an Output has an `_unknown` property and any options with defaultValues */ + this.set('_unknown', Option.create({ name: '_unknown', multiple: true })); + for (const def of this.definitions.whereDefaultValueSet()) { + this.set(def.name, Option.create(def)); + } + } + + toObject(options) { + options = options || {}; + const output = {}; + for (const item of this) { + const name = item[0]; + const option = item[1]; + if (name === '_unknown' && !option.get().length) continue + output[name] = option.get(); + } + + if (options.skipUnknown) delete output._unknown; + return output + } +} + +class GroupedOutput extends Output { + toObject(options) { + const superOutputNoCamel = super.toObject({ skipUnknown: options.skipUnknown }); + const superOutput = super.toObject(options); + const unknown = superOutput._unknown; + delete superOutput._unknown; + const grouped = { + _all: superOutput + }; + if (unknown && unknown.length) grouped._unknown = unknown; + + this.definitions.whereGrouped().forEach(def => { + const name = def.name; + const outputValue = superOutputNoCamel[def.name]; + for (const groupName of arrayify(def.group)) { + grouped[groupName] = grouped[groupName] || {}; + if (t.isDefined(outputValue)) { + grouped[groupName][name] = outputValue; + } + } + }); + + this.definitions.whereNotGrouped().forEach(def => { + const name = def.name; + const outputValue = superOutputNoCamel[def.name]; + if (t.isDefined(outputValue)) { + if (!grouped._none) grouped._none = {}; + grouped._none[name] = outputValue; + } + }); + return grouped + } +} + +/** + * @module command-line-args + */ + +/** + * Returns an object containing all option values set on the command line. By default it parses the global [`process.argv`](https://nodejs.org/api/process.html#process_process_argv) array. + * + * Parsing is strict by default - an exception is thrown if the user sets a singular option more than once or sets an unknown value or option (one without a valid [definition](https://github.com/75lb/command-line-args/blob/master/doc/option-definition.md)). To be more permissive, enabling [partial](https://github.com/75lb/command-line-args/wiki/Partial-mode-example) or [stopAtFirstUnknown](https://github.com/75lb/command-line-args/wiki/stopAtFirstUnknown) modes will return known options in the usual manner while collecting unknown arguments in a separate `_unknown` property. + * + * @param {Array} - An array of [OptionDefinition](https://github.com/75lb/command-line-args/blob/master/doc/option-definition.md) objects + * @param {object} [options] - Options. + * @param {string[]} [options.argv] - An array of strings which, if present will be parsed instead of `process.argv`. + * @param {boolean} [options.partial] - If `true`, an array of unknown arguments is returned in the `_unknown` property of the output. + * @param {boolean} [options.stopAtFirstUnknown] - If `true`, parsing will stop at the first unknown argument and the remaining arguments returned in `_unknown`. When set, `partial: true` is also implied. + * @param {boolean} [options.caseInsensitive] - If `true`, the case of each option name or alias parsed is insignificant. In other words, both `--Verbose` and `--verbose`, `-V` and `-v` would be equivalent. Defaults to false. + * @returns {object} + * @throws `UNKNOWN_OPTION` If `options.partial` is false and the user set an undefined option. The `err.optionName` property contains the arg that specified an unknown option, e.g. `--one`. + * @throws `UNKNOWN_VALUE` If `options.partial` is false and the user set a value unaccounted for by an option definition. The `err.value` property contains the unknown value, e.g. `5`. + * @throws `ALREADY_SET` If a user sets a singular, non-multiple option more than once. The `err.optionName` property contains the option name that has already been set, e.g. `one`. + * @throws `INVALID_DEFINITIONS` + * - If an option definition is missing the required `name` property + * - If an option definition has a `type` value that's not a function + * - If an alias is numeric, a hyphen or a length other than 1 + * - If an option definition name was used more than once + * - If an option definition alias was used more than once + * - If more than one option definition has `defaultOption: true` + * - If a `Boolean` option is also set as the `defaultOption`. + * @alias module:command-line-args + */ +function commandLineArgs(optionDefinitions, options) { + options = options || {}; + if (options.stopAtFirstUnknown) options.partial = true; + optionDefinitions = Definitions.from(optionDefinitions, options.caseInsensitive); + + const parser = new ArgvParser(optionDefinitions, { + argv: options.argv, + stopAtFirstUnknown: options.stopAtFirstUnknown, + caseInsensitive: options.caseInsensitive + }); + + const OutputClass = optionDefinitions.isGrouped() ? GroupedOutput : Output; + const output = new OutputClass(optionDefinitions); + + /* Iterate the parser setting each known value to the output. Optionally, throw on unknowns. */ + for (const argInfo of parser) { + const arg = argInfo.subArg || argInfo.arg; + if (!options.partial) { + if (argInfo.event === 'unknown_value') { + const err = new Error(`Unknown value: ${arg}`); + err.name = 'UNKNOWN_VALUE'; + err.value = arg; + throw err + } else if (argInfo.event === 'unknown_option') { + const err = new Error(`Unknown option: ${arg}`); + err.name = 'UNKNOWN_OPTION'; + err.optionName = arg; + throw err + } + } + + let option; + if (output.has(argInfo.name)) { + option = output.get(argInfo.name); + } else { + option = Option.create(argInfo.def); + output.set(argInfo.name, option); + } + + if (argInfo.name === '_unknown') { + option.set(arg); + } else { + option.set(argInfo.value); + } + } + + return output.toObject({ skipUnknown: !options.partial }) +} + +module.exports = commandLineArgs; \ No newline at end of file From 1dbfb5637a5b66271329795e481015ce5f0858c4 Mon Sep 17 00:00:00 2001 From: advplyr Date: Wed, 6 Jul 2022 19:01:27 -0500 Subject: [PATCH 005/100] Remove bcryptjs dependency --- package-lock.json | 5 --- package.json | 1 - server/Auth.js | 2 +- server/libs/bcryptjs/LICENSE | 50 ++++++++++++++++++++++++++++++ server/libs/bcryptjs/index.js | 57 +++++++++++++++++++++++++++++++++++ 5 files changed, 108 insertions(+), 7 deletions(-) create mode 100644 server/libs/bcryptjs/LICENSE create mode 100644 server/libs/bcryptjs/index.js diff --git a/package-lock.json b/package-lock.json index c6cf8a006..740556771 100644 --- a/package-lock.json +++ b/package-lock.json @@ -126,11 +126,6 @@ "resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz", "integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==" }, - "bcryptjs": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-2.4.3.tgz", - "integrity": "sha512-V/Hy/X9Vt7f3BbPJEi8BdVFMByHi+jNXrYkW3huaybV/kQ0KJg0Y6PkEMbn+zeT+i+SiKZ/HMqJGIIt4LZDqNQ==" - }, "bl": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", diff --git a/package.json b/package.json index d6a346874..2a0b8e771 100644 --- a/package.json +++ b/package.json @@ -32,7 +32,6 @@ "dependencies": { "archiver": "^5.3.0", "axios": "^0.26.1", - "bcryptjs": "^2.4.3", "date-and-time": "^2.3.1", "express": "^4.17.1", "express-fileupload": "^1.2.1", diff --git a/server/Auth.js b/server/Auth.js index de86f393b..29fdbffcf 100644 --- a/server/Auth.js +++ b/server/Auth.js @@ -1,4 +1,4 @@ -const bcrypt = require('bcryptjs') +const bcrypt = require('./libs/bcryptjs') const jwt = require('./libs/jsonwebtoken') const Logger = require('./Logger') diff --git a/server/libs/bcryptjs/LICENSE b/server/libs/bcryptjs/LICENSE new file mode 100644 index 000000000..913d59eb4 --- /dev/null +++ b/server/libs/bcryptjs/LICENSE @@ -0,0 +1,50 @@ +bcrypt.js +--------- +Copyright (c) 2012 Nevins Bartolomeo +Copyright (c) 2012 Shane Girish +Copyright (c) 2014 Daniel Wirtz + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +isaac.js +-------- +Copyright (c) 2012 Yves-Marie K. Rinquin + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/server/libs/bcryptjs/index.js b/server/libs/bcryptjs/index.js new file mode 100644 index 000000000..75dc7ae1b --- /dev/null +++ b/server/libs/bcryptjs/index.js @@ -0,0 +1,57 @@ +/* + bcrypt.js (c) 2013 Daniel Wirtz + Released under the Apache License, Version 2.0 + see: https://github.com/dcodeIO/bcrypt.js for details +*/ +var $jscomp=$jscomp||{};$jscomp.scope={};$jscomp.ASSUME_ES5=!1;$jscomp.ASSUME_NO_NATIVE_MAP=!1;$jscomp.ASSUME_NO_NATIVE_SET=!1;$jscomp.defineProperty=$jscomp.ASSUME_ES5||"function"==typeof Object.defineProperties?Object.defineProperty:function(a,g,p){a!=Array.prototype&&a!=Object.prototype&&(a[g]=p.value)};$jscomp.getGlobal=function(a){return"undefined"!=typeof window&&window===a?a:"undefined"!=typeof global&&null!=global?global:a};$jscomp.global=$jscomp.getGlobal(this);$jscomp.SYMBOL_PREFIX="jscomp_symbol_"; +$jscomp.initSymbol=function(){$jscomp.initSymbol=function(){};$jscomp.global.Symbol||($jscomp.global.Symbol=$jscomp.Symbol)};$jscomp.Symbol=function(){var a=0;return function(g){return $jscomp.SYMBOL_PREFIX+(g||"")+a++}}(); +$jscomp.initSymbolIterator=function(){$jscomp.initSymbol();var a=$jscomp.global.Symbol.iterator;a||(a=$jscomp.global.Symbol.iterator=$jscomp.global.Symbol("iterator"));"function"!=typeof Array.prototype[a]&&$jscomp.defineProperty(Array.prototype,a,{configurable:!0,writable:!0,value:function(){return $jscomp.arrayIterator(this)}});$jscomp.initSymbolIterator=function(){}};$jscomp.arrayIterator=function(a){var g=0;return $jscomp.iteratorPrototype(function(){return g=k||k>n.length)throw Error("Illegal len: "+k);for(;a>2&63]);e=(e&3)<<4;if(a>=k){c.push(x[e&63]);break}var f=n[a++]&255;e|=f>>4&15;c.push(x[e&63]);e=(f&15)<<2;if(a>=k){c.push(x[e&63]);break}f=n[a++]&255;e|=f>>6&3;c.push(x[e&63]);c.push(x[f&63])}return c.join("")}function q(a,k){var n=0,c=a.length,e=0,f=[];if(0>= +k)throw Error("Illegal len: "+k);for(;n>>0;d|=(h&48)>>4;f.push(B(d));if(++e>=k||n>=c)break;d=a.charCodeAt(n++);b=d>>0;d|=(b&60)>>2;f.push(B(d));if(++e>=k||n>=c)break;d=a.charCodeAt(n++);h=d>>0;d|=h;f.push(B(d));++e}a=[];for(n=0;n>>24];d+=c[256|e>>16&255];d^=c[512|e>>8&255];d+=c[768|e&255];f^=d^l[1];d=c[f>>>24];d+=c[256|f>>16&255];d^=c[512|f>>8&255];d+=c[768|f&255];e^=d^l[2];d=c[e>>>24];d+=c[256|e>>16&255];d^=c[512|e>>8&255];d+=c[768|e&255];f^=d^l[3];d=c[f>>>24];d+=c[256|f>>16&255];d^=c[512|f>>8&255];d+=c[768|f&255];e^=d^l[4];d=c[e>>>24];d+=c[256|e>>16&255];d^=c[512|e>>8&255];d+=c[768|e&255];f^=d^l[5];d=c[f>>>24];d+=c[256|f>>16&255];d^=c[512|f>>8&255];d+=c[768|f&255];e^=d^l[6];d=c[e>>>24];d+= +c[256|e>>16&255];d^=c[512|e>>8&255];d+=c[768|e&255];f^=d^l[7];d=c[f>>>24];d+=c[256|f>>16&255];d^=c[512|f>>8&255];d+=c[768|f&255];e^=d^l[8];d=c[e>>>24];d+=c[256|e>>16&255];d^=c[512|e>>8&255];d+=c[768|e&255];f^=d^l[9];d=c[f>>>24];d+=c[256|f>>16&255];d^=c[512|f>>8&255];d+=c[768|f&255];e^=d^l[10];d=c[e>>>24];d+=c[256|e>>16&255];d^=c[512|e>>8&255];d+=c[768|e&255];f^=d^l[11];d=c[f>>>24];d+=c[256|f>>16&255];d^=c[512|f>>8&255];d+=c[768|f&255];e^=d^l[12];d=c[e>>>24];d+=c[256|e>>16&255];d^=c[512|e>>8&255]; +d+=c[768|e&255];f^=d^l[13];d=c[f>>>24];d+=c[256|f>>16&255];d^=c[512|f>>8&255];d+=c[768|f&255];e^=d^l[14];d=c[e>>>24];d+=c[256|e>>16&255];d^=c[512|e>>8&255];d+=c[768|e&255];f^=d^l[15];d=c[f>>>24];d+=c[256|f>>16&255];d^=c[512|f>>8&255];d+=c[768|f&255];e^=d^l[16];a[k]=f^l[17];a[k+1]=e;return a}function v(a,k){for(var n=0,c=0;4>n;++n)c=c<<8|a[k]&255,k=(k+1)%a.length;return{key:c,offp:k}}function b(a,k,l){for(var c=0,e=[0,0],f=k.length,d=l.length,n,b=0;bm;m++)for(p=0;p>1;p++)h(d,p<<1,q,y);g=[];for(m=0;m>24&255)>>>0),g.push((d[m]>>16&255)>>>0),g.push((d[m]>>8&255)>>>0),g.push((d[m]&255)>>>0);if(c){c(null,g);return}return g}c&&r(f)}var d=C.slice(),n=d.length;if(4>l||31>>0;var m=0,p;if(Int32Array){var q=new Int32Array(D);var y=new Int32Array(E)}else q=D.slice(),y=E.slice();A(k,a,q,y);if("undefined"!==typeof c)f();else for(;;)if("undefined"!==typeof(g=f()))return g||[]}function t(a,k,b,c){function e(a){var c=[];c.push("$2");"a"<=f&&c.push(f);c.push("$");10>l&&c.push("0");c.push(l.toString());c.push("$");c.push(p(h,h.length));c.push(p(a,4*C.length-1));return c.join("")}if("string"!==typeof a||"string"!==typeof k){c=Error("Invalid string / salt: Not a string"); +if(b){r(b.bind(this,c));return}throw c;}if("$"!==k.charAt(0)||"2"!==k.charAt(1)){c=Error("Invalid salt version: "+k.substring(0,2));if(b){r(b.bind(this,c));return}throw c;}if("$"===k.charAt(2)){var f=String.fromCharCode(0);var d=3}else{f=k.charAt(2);if("a"!==f&&"b"!==f&&"y"!==f||"$"!==k.charAt(3)){c=Error("Invalid salt revision: "+k.substring(2,4));if(b){r(b.bind(this,c));return}throw c;}d=4}if("$"b?b=4:31b&&k.push("0");k.push(b.toString());k.push("$");k.push(p(a(16), +16));return k.join("")};m.genSalt=function(a,b,g){function c(c){r(function(){try{c(null,m.genSaltSync(a))}catch(f){c(f)}})}"function"===typeof b&&(g=b,b=void 0);"function"===typeof a&&(g=a,a=void 0);if("undefined"===typeof a)a=10;else if("number"!==typeof a)throw Error("illegal arguments: "+typeof a);if(g){if("function"!==typeof g)throw Error("Illegal callback: "+typeof g);c(g)}else return new Promise(function(a,b){c(function(c,f){c?b(c):a(f)})})};m.hashSync=function(a,b){"undefined"===typeof b&& +(b=10);"number"===typeof b&&(b=m.genSaltSync(b));if("string"!==typeof a||"string"!==typeof b)throw Error("Illegal arguments: "+typeof a+", "+typeof b);return t(a,b)};m.hash=function(a,b,g,c){function e(f){"string"===typeof a&&"number"===typeof b?m.genSalt(b,function(b,e){t(a,e,f,c)}):"string"===typeof a&&"string"===typeof b?t(a,b,f,c):r(f.bind(this,Error("Illegal arguments: "+typeof a+", "+typeof b)))}if(g){if("function"!==typeof g)throw Error("Illegal callback: "+typeof g);e(g)}else return new Promise(function(a, +c){e(function(b,d){b?c(b):a(d)})})};m.compareSync=function(a,b){if("string"!==typeof a||"string"!==typeof b)throw Error("Illegal arguments: "+typeof a+", "+typeof b);return 60!==b.length?!1:g(m.hashSync(a,b.substr(0,b.length-31)),b)};m.compare=function(a,b,h,c){function e(f){"string"!==typeof a||"string"!==typeof b?r(f.bind(this,Error("Illegal arguments: "+typeof a+", "+typeof b))):60!==b.length?r(f.bind(this,null,!1)):m.hash(a,b.substr(0,29),function(a,c){a?f(a):f(null,g(c,b))},c)}if(h){if("function"!== +typeof h)throw Error("Illegal callback: "+typeof h);e(h)}else return new Promise(function(a,c){e(function(b,d){b?c(b):a(d)})})};m.getRounds=function(a){if("string"!==typeof a)throw Error("Illegal arguments: "+typeof a);return parseInt(a.split("$")[2],10)};m.getSalt=function(a){if("string"!==typeof a)throw Error("Illegal arguments: "+typeof a);if(60!==a.length)throw Error("Illegal hash length: "+a.length+" != 60");return a.substring(0,29)};var r="undefined"!==typeof process&&process&&"function"=== +typeof process.nextTick?"function"===typeof setImmediate?setImmediate:process.nextTick:setTimeout,F=function(a){var b=0,g;var c=Array;for(var e=0,f,d=0;df?e+=1:2048>f?e+=2:55296===(f&64512)&&56320===(a.charCodeAt(d+1)&64512)?(++d,e+=4):e+=3;e=new c(e);f=0;for(d=a.length;fc?e[b++]=c:(2048>c?e[b++]=c>>6|192:(55296===(c&64512)&&56320===((g=a.charCodeAt(f+1))&64512)?(c=65536+((c&1023)<<10)+(g&1023),++f,e[b++]=c>>18|240,e[b++]=c>>12&63|128): +e[b++]=c>>12|224,e[b++]=c>>6&63|128),e[b++]=c&63|128);return e},x="./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789".split(""),u=[-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,0,1,54,55,56,57,58,59,60,61,62,63,-1,-1,-1,-1,-1,-1,-1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,-1,-1,-1,-1,-1,-1,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52, +53,-1,-1,-1,-1,-1],B=String.fromCharCode;Date.now=Date.now||function(){return+new Date};var D=[608135816,2242054355,320440878,57701188,2752067618,698298832,137296536,3964562569,1160258022,953160567,3193202383,887688300,3232508343,3380367581,1065670069,3041331479,2450970073,2306472731],E=[3509652390,2564797868,805139163,3491422135,3101798381,1780907670,3128725573,4046225305,614570311,3012652279,134345442,2240740374,1667834072,1901547113,2757295779,4103290238,227898511,1921955416,1904987480,2182433518, +2069144605,3260701109,2620446009,720527379,3318853667,677414384,3393288472,3101374703,2390351024,1614419982,1822297739,2954791486,3608508353,3174124327,2024746970,1432378464,3864339955,2857741204,1464375394,1676153920,1439316330,715854006,3033291828,289532110,2706671279,2087905683,3018724369,1668267050,732546397,1947742710,3462151702,2609353502,2950085171,1814351708,2050118529,680887927,999245976,1800124847,3300911131,1713906067,1641548236,4213287313,1216130144,1575780402,4018429277,3917837745,3693486850, +3949271944,596196993,3549867205,258830323,2213823033,772490370,2760122372,1774776394,2652871518,566650946,4142492826,1728879713,2882767088,1783734482,3629395816,2517608232,2874225571,1861159788,326777828,3124490320,2130389656,2716951837,967770486,1724537150,2185432712,2364442137,1164943284,2105845187,998989502,3765401048,2244026483,1075463327,1455516326,1322494562,910128902,469688178,1117454909,936433444,3490320968,3675253459,1240580251,122909385,2157517691,634681816,4142456567,3825094682,3061402683, +2540495037,79693498,3249098678,1084186820,1583128258,426386531,1761308591,1047286709,322548459,995290223,1845252383,2603652396,3431023940,2942221577,3202600964,3727903485,1712269319,422464435,3234572375,1170764815,3523960633,3117677531,1434042557,442511882,3600875718,1076654713,1738483198,4213154764,2393238008,3677496056,1014306527,4251020053,793779912,2902807211,842905082,4246964064,1395751752,1040244610,2656851899,3396308128,445077038,3742853595,3577915638,679411651,2892444358,2354009459,1767581616, +3150600392,3791627101,3102740896,284835224,4246832056,1258075500,768725851,2589189241,3069724005,3532540348,1274779536,3789419226,2764799539,1660621633,3471099624,4011903706,913787905,3497959166,737222580,2514213453,2928710040,3937242737,1804850592,3499020752,2949064160,2386320175,2390070455,2415321851,4061277028,2290661394,2416832540,1336762016,1754252060,3520065937,3014181293,791618072,3188594551,3933548030,2332172193,3852520463,3043980520,413987798,3465142937,3030929376,4245938359,2093235073,3534596313, +375366246,2157278981,2479649556,555357303,3870105701,2008414854,3344188149,4221384143,3956125452,2067696032,3594591187,2921233993,2428461,544322398,577241275,1471733935,610547355,4027169054,1432588573,1507829418,2025931657,3646575487,545086370,48609733,2200306550,1653985193,298326376,1316178497,3007786442,2064951626,458293330,2589141269,3591329599,3164325604,727753846,2179363840,146436021,1461446943,4069977195,705550613,3059967265,3887724982,4281599278,3313849956,1404054877,2845806497,146425753,1854211946, +1266315497,3048417604,3681880366,3289982499,290971E4,1235738493,2632868024,2414719590,3970600049,1771706367,1449415276,3266420449,422970021,1963543593,2690192192,3826793022,1062508698,1531092325,1804592342,2583117782,2714934279,4024971509,1294809318,4028980673,1289560198,2221992742,1669523910,35572830,157838143,1052438473,1016535060,1802137761,1753167236,1386275462,3080475397,2857371447,1040679964,2145300060,2390574316,1461121720,2956646967,4031777805,4028374788,33600511,2920084762,1018524850,629373528, +3691585981,3515945977,2091462646,2486323059,586499841,988145025,935516892,3367335476,2599673255,2839830854,265290510,3972581182,2759138881,3795373465,1005194799,847297441,406762289,1314163512,1332590856,1866599683,4127851711,750260880,613907577,1450815602,3165620655,3734664991,3650291728,3012275730,3704569646,1427272223,778793252,1343938022,2676280711,2052605720,1946737175,3164576444,3914038668,3967478842,3682934266,1661551462,3294938066,4011595847,840292616,3712170807,616741398,312560963,711312465, +1351876610,322626781,1910503582,271666773,2175563734,1594956187,70604529,3617834859,1007753275,1495573769,4069517037,2549218298,2663038764,504708206,2263041392,3941167025,2249088522,1514023603,1998579484,1312622330,694541497,2582060303,2151582166,1382467621,776784248,2618340202,3323268794,2497899128,2784771155,503983604,4076293799,907881277,423175695,432175456,1378068232,4145222326,3954048622,3938656102,3820766613,2793130115,2977904593,26017576,3274890735,3194772133,1700274565,1756076034,4006520079, +3677328699,720338349,1533947780,354530856,688349552,3973924725,1637815568,332179504,3949051286,53804574,2852348879,3044236432,1282449977,3583942155,3416972820,4006381244,1617046695,2628476075,3002303598,1686838959,431878346,2686675385,1700445008,1080580658,1009431731,832498133,3223435511,2605976345,2271191193,2516031870,1648197032,4164389018,2548247927,300782431,375919233,238389289,3353747414,2531188641,2019080857,1475708069,455242339,2609103871,448939670,3451063019,1395535956,2413381860,1841049896, +1491858159,885456874,4264095073,4001119347,1565136089,3898914787,1108368660,540939232,1173283510,2745871338,3681308437,4207628240,3343053890,4016749493,1699691293,1103962373,3625875870,2256883143,3830138730,1031889488,3479347698,1535977030,4236805024,3251091107,2132092099,1774941330,1199868427,1452454533,157007616,2904115357,342012276,595725824,1480756522,206960106,497939518,591360097,863170706,2375253569,3596610801,1814182875,2094937945,3421402208,1082520231,3463918190,2785509508,435703966,3908032597, +1641649973,2842273706,3305899714,1510255612,2148256476,2655287854,3276092548,4258621189,236887753,3681803219,274041037,1734335097,3815195456,3317970021,1899903192,1026095262,4050517792,356393447,2410691914,3873677099,3682840055,3913112168,2491498743,4132185628,2489919796,1091903735,1979897079,3170134830,3567386728,3557303409,857797738,1136121015,1342202287,507115054,2535736646,337727348,3213592640,1301675037,2528481711,1895095763,1721773893,3216771564,62756741,2142006736,835421444,2531993523,1442658625, +3659876326,2882144922,676362277,1392781812,170690266,3921047035,1759253602,3611846912,1745797284,664899054,1329594018,3901205900,3045908486,2062866102,2865634940,3543621612,3464012697,1080764994,553557557,3656615353,3996768171,991055499,499776247,1265440854,648242737,3940784050,980351604,3713745714,1749149687,3396870395,4211799374,3640570775,1161844396,3125318951,1431517754,545492359,4268468663,3499529547,1437099964,2702547544,3433638243,2581715763,2787789398,1060185593,1593081372,2418618748,4260947970, +69676912,2159744348,86519011,2512459080,3838209314,1220612927,3339683548,133810670,1090789135,1078426020,1569222167,845107691,3583754449,4072456591,1091646820,628848692,1613405280,3757631651,526609435,236106946,48312990,2942717905,3402727701,1797494240,859738849,992217954,4005476642,2243076622,3870952857,3732016268,765654824,3490871365,2511836413,1685915746,3888969200,1414112111,2273134842,3281911079,4080962846,172450625,2569994100,980381355,4109958455,2819808352,2716589560,2568741196,3681446669, +3329971472,1835478071,660984891,3704678404,4045999559,3422617507,3040415634,1762651403,1719377915,3470491036,2693910283,3642056355,3138596744,1364962596,2073328063,1983633131,926494387,3423689081,2150032023,4096667949,1749200295,3328846651,309677260,2016342300,1779581495,3079819751,111262694,1274766160,443224088,298511866,1025883608,3806446537,1145181785,168956806,3641502830,3584813610,1689216846,3666258015,3200248200,1692713982,2646376535,4042768518,1618508792,1610833997,3523052358,4130873264,2001055236, +3610705100,2202168115,4028541809,2961195399,1006657119,2006996926,3186142756,1430667929,3210227297,1314452623,4074634658,4101304120,2273951170,1399257539,3367210612,3027628629,1190975929,2062231137,2333990788,2221543033,2438960610,1181637006,548689776,2362791313,3372408396,3104550113,3145860560,296247880,1970579870,3078560182,3769228297,1714227617,3291629107,3898220290,166772364,1251581989,493813264,448347421,195405023,2709975567,677966185,3703036547,1463355134,2715995803,1338867538,1343315457,2802222074, +2684532164,233230375,2599980071,2000651841,3277868038,1638401717,4028070440,3237316320,6314154,819756386,300326615,590932579,1405279636,3267499572,3150704214,2428286686,3959192993,3461946742,1862657033,1266418056,963775037,2089974820,2263052895,1917689273,448879540,3550394620,3981727096,150775221,3627908307,1303187396,508620638,2975983352,2726630617,1817252668,1876281319,1457606340,908771278,3720792119,3617206836,2455994898,1729034894,1080033504,976866871,3556439503,2881648439,1522871579,1555064734, +1336096578,3548522304,2579274686,3574697629,3205460757,3593280638,3338716283,3079412587,564236357,2993598910,1781952180,1464380207,3163844217,3332601554,1699332808,1393555694,1183702653,3581086237,1288719814,691649499,2847557200,2895455976,3193889540,2717570544,1781354906,1676643554,2592534050,3230253752,1126444790,2770207658,2633158820,2210423226,2615765581,2414155088,3127139286,673620729,2805611233,1269405062,4015350505,3341807571,4149409754,1057255273,2012875353,2162469141,2276492801,2601117357, +993977747,3918593370,2654263191,753973209,36408145,2530585658,25011837,3520020182,2088578344,530523599,2918365339,1524020338,1518925132,3760827505,3759777254,1202760957,3985898139,3906192525,674977740,4174734889,2031300136,2019492241,3983892565,4153806404,3822280332,352677332,2297720250,60907813,90501309,3286998549,1016092578,2535922412,2839152426,457141659,509813237,4120667899,652014361,1966332200,2975202805,55981186,2327461051,676427537,3255491064,2882294119,3433927263,1307055953,942726286,933058658, +2468411793,3933900994,4215176142,1361170020,2001714738,2830558078,3274259782,1222529897,1679025792,2729314320,3714953764,1770335741,151462246,3013232138,1682292957,1483529935,471910574,1539241949,458788160,3436315007,1807016891,3718408830,978976581,1043663428,3165965781,1927990952,4200891579,2372276910,3208408903,3533431907,1412390302,2931980059,4132332400,1947078029,3881505623,4168226417,2941484381,1077988104,1320477388,886195818,18198404,3786409E3,2509781533,112762804,3463356488,1866414978,891333506, +18488651,661792760,1628790961,3885187036,3141171499,876946877,2693282273,1372485963,791857591,2686433993,3759982718,3167212022,3472953795,2716379847,445679433,3561995674,3504004811,3574258232,54117162,3331405415,2381918588,3769707343,4154350007,1140177722,4074052095,668550556,3214352940,367459370,261225585,2610173221,4209349473,3468074219,3265815641,314222801,3066103646,3808782860,282218597,3406013506,3773591054,379116347,1285071038,846784868,2669647154,3771962079,3550491691,2305946142,453669953, +1268987020,3317592352,3279303384,3744833421,2610507566,3859509063,266596637,3847019092,517658769,3462560207,3443424879,370717030,4247526661,2224018117,4143653529,4112773975,2788324899,2477274417,1456262402,2901442914,1517677493,1846949527,2295493580,3734397586,2176403920,1280348187,1908823572,3871786941,846861322,1172426758,3287448474,3383383037,1655181056,3139813346,901632758,1897031941,2986607138,3066810236,3447102507,1393639104,373351379,950779232,625454576,3124240540,4148612726,2007998917,544563296, +2244738638,2330496472,2058025392,1291430526,424198748,50039436,29584100,3605783033,2429876329,2791104160,1057563949,3255363231,3075367218,3463963227,1469046755,985887462],C=[1332899944,1700884034,1701343084,1684370003,1668446532,1869963892];m.encodeBase64=p;m.decodeBase64=q;return m}); \ No newline at end of file From 7aa7e662b267e654db4f18fcbc0b9f30176f6cf1 Mon Sep 17 00:00:00 2001 From: advplyr Date: Wed, 6 Jul 2022 19:10:25 -0500 Subject: [PATCH 006/100] Remove dependency express-fileupload --- package-lock.json | 21 - package.json | 1 - server/Server.js | 2 +- server/libs/busboy/LICENSE | 19 + server/libs/busboy/index.js | 62 ++ server/libs/busboy/types/multipart.js | 657 ++++++++++++++++++ server/libs/busboy/types/urlencoded.js | 350 ++++++++++ server/libs/busboy/utils.js | 596 ++++++++++++++++ server/libs/expressFileupload/LICENSE | 21 + server/libs/expressFileupload/fileFactory.js | 65 ++ server/libs/expressFileupload/index.js | 39 ++ .../expressFileupload/isEligibleRequest.js | 34 + server/libs/expressFileupload/memHandler.js | 42 ++ .../expressFileupload/processMultipart.js | 168 +++++ .../libs/expressFileupload/processNested.js | 35 + .../libs/expressFileupload/tempFileHandler.js | 64 ++ server/libs/expressFileupload/uploadtimer.js | 26 + server/libs/expressFileupload/utilities.js | 311 +++++++++ server/libs/streamsearch/LICENSE | 19 + server/libs/streamsearch/index.js | 273 ++++++++ 20 files changed, 2782 insertions(+), 23 deletions(-) create mode 100644 server/libs/busboy/LICENSE create mode 100644 server/libs/busboy/index.js create mode 100644 server/libs/busboy/types/multipart.js create mode 100644 server/libs/busboy/types/urlencoded.js create mode 100644 server/libs/busboy/utils.js create mode 100644 server/libs/expressFileupload/LICENSE create mode 100644 server/libs/expressFileupload/fileFactory.js create mode 100644 server/libs/expressFileupload/index.js create mode 100644 server/libs/expressFileupload/isEligibleRequest.js create mode 100644 server/libs/expressFileupload/memHandler.js create mode 100644 server/libs/expressFileupload/processMultipart.js create mode 100644 server/libs/expressFileupload/processNested.js create mode 100644 server/libs/expressFileupload/tempFileHandler.js create mode 100644 server/libs/expressFileupload/uploadtimer.js create mode 100644 server/libs/expressFileupload/utilities.js create mode 100644 server/libs/streamsearch/LICENSE create mode 100644 server/libs/streamsearch/index.js diff --git a/package-lock.json b/package-lock.json index 740556771..01052b96b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -178,14 +178,6 @@ "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==" }, - "busboy": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", - "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", - "requires": { - "streamsearch": "^1.1.0" - } - }, "bytes": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", @@ -441,14 +433,6 @@ "vary": "~1.1.2" } }, - "express-fileupload": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/express-fileupload/-/express-fileupload-1.4.0.tgz", - "integrity": "sha512-RjzLCHxkv3umDeZKeFeMg8w7qe0V09w3B7oGZprr/oO2H/ISCgNzuqzn7gV3HRWb37GjRk429CCpSLS2KNTqMQ==", - "requires": { - "busboy": "^1.6.0" - } - }, "express-rate-limit": { "version": "5.5.1", "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-5.5.1.tgz", @@ -945,11 +929,6 @@ "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==" }, - "streamsearch": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", - "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==" - }, "string_decoder": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", diff --git a/package.json b/package.json index 2a0b8e771..61d31ef56 100644 --- a/package.json +++ b/package.json @@ -34,7 +34,6 @@ "axios": "^0.26.1", "date-and-time": "^2.3.1", "express": "^4.17.1", - "express-fileupload": "^1.2.1", "express-rate-limit": "^5.3.0", "htmlparser2": "^8.0.1", "socket.io": "^4.4.1", diff --git a/server/Server.js b/server/Server.js index 9484a43d0..f43d46c72 100644 --- a/server/Server.js +++ b/server/Server.js @@ -3,7 +3,7 @@ const express = require('express') const http = require('http') const SocketIO = require('socket.io') const fs = require('./libs/fsExtra') -const fileUpload = require('express-fileupload') +const fileUpload = require('./libs/expressFileupload') const rateLimit = require('express-rate-limit') const { version } = require('../package.json') diff --git a/server/libs/busboy/LICENSE b/server/libs/busboy/LICENSE new file mode 100644 index 000000000..290762e94 --- /dev/null +++ b/server/libs/busboy/LICENSE @@ -0,0 +1,19 @@ +Copyright Brian White. All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to +deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +sell copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +IN THE SOFTWARE. \ No newline at end of file diff --git a/server/libs/busboy/index.js b/server/libs/busboy/index.js new file mode 100644 index 000000000..40d37c446 --- /dev/null +++ b/server/libs/busboy/index.js @@ -0,0 +1,62 @@ +'use strict'; + +// +// used by expressFileUpload +// Source: https://github.com/mscdex/busboy +// + +const { parseContentType } = require('./utils.js'); + +function getInstance(cfg) { + const headers = cfg.headers; + const conType = parseContentType(headers['content-type']); + if (!conType) + throw new Error('Malformed content type'); + + for (const type of TYPES) { + const matched = type.detect(conType); + if (!matched) + continue; + + const instanceCfg = { + limits: cfg.limits, + headers, + conType, + highWaterMark: undefined, + fileHwm: undefined, + defCharset: undefined, + defParamCharset: undefined, + preservePath: false, + }; + if (cfg.highWaterMark) + instanceCfg.highWaterMark = cfg.highWaterMark; + if (cfg.fileHwm) + instanceCfg.fileHwm = cfg.fileHwm; + instanceCfg.defCharset = cfg.defCharset; + instanceCfg.defParamCharset = cfg.defParamCharset; + instanceCfg.preservePath = cfg.preservePath; + return new type(instanceCfg); + } + + throw new Error(`Unsupported content type: ${headers['content-type']}`); +} + +// Note: types are explicitly listed here for easier bundling +// See: https://github.com/mscdex/busboy/issues/121 +const TYPES = [ + require('./types/multipart'), + require('./types/urlencoded'), +].filter(function (typemod) { return typeof typemod.detect === 'function'; }); + +module.exports = (cfg) => { + if (typeof cfg !== 'object' || cfg === null) + cfg = {}; + + if (typeof cfg.headers !== 'object' + || cfg.headers === null + || typeof cfg.headers['content-type'] !== 'string') { + throw new Error('Missing Content-Type'); + } + + return getInstance(cfg); +}; diff --git a/server/libs/busboy/types/multipart.js b/server/libs/busboy/types/multipart.js new file mode 100644 index 000000000..b8c04b136 --- /dev/null +++ b/server/libs/busboy/types/multipart.js @@ -0,0 +1,657 @@ +'use strict'; + +const { Readable, Writable } = require('stream'); + +const StreamSearch = require('../../streamsearch'); + +const { + basename, + convertToUTF8, + getDecoder, + parseContentType, + parseDisposition, +} = require('../utils.js'); + +const BUF_CRLF = Buffer.from('\r\n'); +const BUF_CR = Buffer.from('\r'); +const BUF_DASH = Buffer.from('-'); + +function noop() { } + +const MAX_HEADER_PAIRS = 2000; // From node +const MAX_HEADER_SIZE = 16 * 1024; // From node (its default value) + +const HPARSER_NAME = 0; +const HPARSER_PRE_OWS = 1; +const HPARSER_VALUE = 2; +class HeaderParser { + constructor(cb) { + this.header = Object.create(null); + this.pairCount = 0; + this.byteCount = 0; + this.state = HPARSER_NAME; + this.name = ''; + this.value = ''; + this.crlf = 0; + this.cb = cb; + } + + reset() { + this.header = Object.create(null); + this.pairCount = 0; + this.byteCount = 0; + this.state = HPARSER_NAME; + this.name = ''; + this.value = ''; + this.crlf = 0; + } + + push(chunk, pos, end) { + let start = pos; + while (pos < end) { + switch (this.state) { + case HPARSER_NAME: { + let done = false; + for (; pos < end; ++pos) { + if (this.byteCount === MAX_HEADER_SIZE) + return -1; + ++this.byteCount; + const code = chunk[pos]; + if (TOKEN[code] !== 1) { + if (code !== 58/* ':' */) + return -1; + this.name += chunk.latin1Slice(start, pos); + if (this.name.length === 0) + return -1; + ++pos; + done = true; + this.state = HPARSER_PRE_OWS; + break; + } + } + if (!done) { + this.name += chunk.latin1Slice(start, pos); + break; + } + // FALLTHROUGH + } + case HPARSER_PRE_OWS: { + // Skip optional whitespace + let done = false; + for (; pos < end; ++pos) { + if (this.byteCount === MAX_HEADER_SIZE) + return -1; + ++this.byteCount; + const code = chunk[pos]; + if (code !== 32/* ' ' */ && code !== 9/* '\t' */) { + start = pos; + done = true; + this.state = HPARSER_VALUE; + break; + } + } + if (!done) + break; + // FALLTHROUGH + } + case HPARSER_VALUE: + switch (this.crlf) { + case 0: // Nothing yet + for (; pos < end; ++pos) { + if (this.byteCount === MAX_HEADER_SIZE) + return -1; + ++this.byteCount; + const code = chunk[pos]; + if (FIELD_VCHAR[code] !== 1) { + if (code !== 13/* '\r' */) + return -1; + ++this.crlf; + break; + } + } + this.value += chunk.latin1Slice(start, pos++); + break; + case 1: // Received CR + if (this.byteCount === MAX_HEADER_SIZE) + return -1; + ++this.byteCount; + if (chunk[pos++] !== 10/* '\n' */) + return -1; + ++this.crlf; + break; + case 2: { // Received CR LF + if (this.byteCount === MAX_HEADER_SIZE) + return -1; + ++this.byteCount; + const code = chunk[pos]; + if (code === 32/* ' ' */ || code === 9/* '\t' */) { + // Folded value + start = pos; + this.crlf = 0; + } else { + if (++this.pairCount < MAX_HEADER_PAIRS) { + this.name = this.name.toLowerCase(); + if (this.header[this.name] === undefined) + this.header[this.name] = [this.value]; + else + this.header[this.name].push(this.value); + } + if (code === 13/* '\r' */) { + ++this.crlf; + ++pos; + } else { + // Assume start of next header field name + start = pos; + this.crlf = 0; + this.state = HPARSER_NAME; + this.name = ''; + this.value = ''; + } + } + break; + } + case 3: { // Received CR LF CR + if (this.byteCount === MAX_HEADER_SIZE) + return -1; + ++this.byteCount; + if (chunk[pos++] !== 10/* '\n' */) + return -1; + // End of header + const header = this.header; + this.reset(); + this.cb(header); + return pos; + } + } + break; + } + } + + return pos; + } +} + +class FileStream extends Readable { + constructor(opts, owner) { + super(opts); + this.truncated = false; + this._readcb = null; + this.once('end', () => { + // We need to make sure that we call any outstanding _writecb() that is + // associated with this file so that processing of the rest of the form + // can continue. This may not happen if the file stream ends right after + // backpressure kicks in, so we force it here. + this._read(); + if (--owner._fileEndsLeft === 0 && owner._finalcb) { + const cb = owner._finalcb; + owner._finalcb = null; + // Make sure other 'end' event handlers get a chance to be executed + // before busboy's 'finish' event is emitted + process.nextTick(cb); + } + }); + } + _read(n) { + const cb = this._readcb; + if (cb) { + this._readcb = null; + cb(); + } + } +} + +const ignoreData = { + push: (chunk, pos) => { }, + destroy: () => { }, +}; + +function callAndUnsetCb(self, err) { + const cb = self._writecb; + self._writecb = null; + if (err) + self.destroy(err); + else if (cb) + cb(); +} + +function nullDecoder(val, hint) { + return val; +} + +class Multipart extends Writable { + constructor(cfg) { + const streamOpts = { + autoDestroy: true, + emitClose: true, + highWaterMark: (typeof cfg.highWaterMark === 'number' + ? cfg.highWaterMark + : undefined), + }; + super(streamOpts); + + if (!cfg.conType.params || typeof cfg.conType.params.boundary !== 'string') + throw new Error('Multipart: Boundary not found'); + + const boundary = cfg.conType.params.boundary; + const paramDecoder = (typeof cfg.defParamCharset === 'string' + && cfg.defParamCharset + ? getDecoder(cfg.defParamCharset) + : nullDecoder); + const defCharset = (cfg.defCharset || 'utf8'); + const preservePath = cfg.preservePath; + const fileOpts = { + autoDestroy: true, + emitClose: true, + highWaterMark: (typeof cfg.fileHwm === 'number' + ? cfg.fileHwm + : undefined), + }; + + const limits = cfg.limits; + const fieldSizeLimit = (limits && typeof limits.fieldSize === 'number' + ? limits.fieldSize + : 1 * 1024 * 1024); + const fileSizeLimit = (limits && typeof limits.fileSize === 'number' + ? limits.fileSize + : Infinity); + const filesLimit = (limits && typeof limits.files === 'number' + ? limits.files + : Infinity); + const fieldsLimit = (limits && typeof limits.fields === 'number' + ? limits.fields + : Infinity); + const partsLimit = (limits && typeof limits.parts === 'number' + ? limits.parts + : Infinity); + + let parts = -1; // Account for initial boundary + let fields = 0; + let files = 0; + let skipPart = false; + + this._fileEndsLeft = 0; + this._fileStream = undefined; + this._complete = false; + let fileSize = 0; + + let field; + let fieldSize = 0; + let partCharset; + let partEncoding; + let partType; + let partName; + let partTruncated = false; + + let hitFilesLimit = false; + let hitFieldsLimit = false; + + this._hparser = null; + const hparser = new HeaderParser((header) => { + this._hparser = null; + skipPart = false; + + partType = 'text/plain'; + partCharset = defCharset; + partEncoding = '7bit'; + partName = undefined; + partTruncated = false; + + let filename; + if (!header['content-disposition']) { + skipPart = true; + return; + } + + const disp = parseDisposition(header['content-disposition'][0], + paramDecoder); + if (!disp || disp.type !== 'form-data') { + skipPart = true; + return; + } + + if (disp.params) { + if (disp.params.name) + partName = disp.params.name; + + if (disp.params['filename*']) + filename = disp.params['filename*']; + else if (disp.params.filename) + filename = disp.params.filename; + + if (filename !== undefined && !preservePath) + filename = basename(filename); + } + + if (header['content-type']) { + const conType = parseContentType(header['content-type'][0]); + if (conType) { + partType = `${conType.type}/${conType.subtype}`; + if (conType.params && typeof conType.params.charset === 'string') + partCharset = conType.params.charset.toLowerCase(); + } + } + + if (header['content-transfer-encoding']) + partEncoding = header['content-transfer-encoding'][0].toLowerCase(); + + if (partType === 'application/octet-stream' || filename !== undefined) { + // File + + if (files === filesLimit) { + if (!hitFilesLimit) { + hitFilesLimit = true; + this.emit('filesLimit'); + } + skipPart = true; + return; + } + ++files; + + if (this.listenerCount('file') === 0) { + skipPart = true; + return; + } + + fileSize = 0; + this._fileStream = new FileStream(fileOpts, this); + ++this._fileEndsLeft; + this.emit( + 'file', + partName, + this._fileStream, + { + filename, + encoding: partEncoding, + mimeType: partType + } + ); + } else { + // Non-file + + if (fields === fieldsLimit) { + if (!hitFieldsLimit) { + hitFieldsLimit = true; + this.emit('fieldsLimit'); + } + skipPart = true; + return; + } + ++fields; + + if (this.listenerCount('field') === 0) { + skipPart = true; + return; + } + + field = []; + fieldSize = 0; + } + }); + + let matchPostBoundary = 0; + const ssCb = (isMatch, data, start, end, isDataSafe) => { + retrydata: + while (data) { + if (this._hparser !== null) { + const ret = this._hparser.push(data, start, end); + if (ret === -1) { + this._hparser = null; + hparser.reset(); + this.emit('error', new Error('Malformed part header')); + break; + } + start = ret; + } + + if (start === end) + break; + + if (matchPostBoundary !== 0) { + if (matchPostBoundary === 1) { + switch (data[start]) { + case 45: // '-' + // Try matching '--' after boundary + matchPostBoundary = 2; + ++start; + break; + case 13: // '\r' + // Try matching CR LF before header + matchPostBoundary = 3; + ++start; + break; + default: + matchPostBoundary = 0; + } + if (start === end) + return; + } + + if (matchPostBoundary === 2) { + matchPostBoundary = 0; + if (data[start] === 45/* '-' */) { + // End of multipart data + this._complete = true; + this._bparser = ignoreData; + return; + } + // We saw something other than '-', so put the dash we consumed + // "back" + const writecb = this._writecb; + this._writecb = noop; + ssCb(false, BUF_DASH, 0, 1, false); + this._writecb = writecb; + } else if (matchPostBoundary === 3) { + matchPostBoundary = 0; + if (data[start] === 10/* '\n' */) { + ++start; + if (parts >= partsLimit) + break; + // Prepare the header parser + this._hparser = hparser; + if (start === end) + break; + // Process the remaining data as a header + continue retrydata; + } else { + // We saw something other than LF, so put the CR we consumed + // "back" + const writecb = this._writecb; + this._writecb = noop; + ssCb(false, BUF_CR, 0, 1, false); + this._writecb = writecb; + } + } + } + + if (!skipPart) { + if (this._fileStream) { + let chunk; + const actualLen = Math.min(end - start, fileSizeLimit - fileSize); + if (!isDataSafe) { + chunk = Buffer.allocUnsafe(actualLen); + data.copy(chunk, 0, start, start + actualLen); + } else { + chunk = data.slice(start, start + actualLen); + } + + fileSize += chunk.length; + if (fileSize === fileSizeLimit) { + if (chunk.length > 0) + this._fileStream.push(chunk); + this._fileStream.emit('limit'); + this._fileStream.truncated = true; + skipPart = true; + } else if (!this._fileStream.push(chunk)) { + if (this._writecb) + this._fileStream._readcb = this._writecb; + this._writecb = null; + } + } else if (field !== undefined) { + let chunk; + const actualLen = Math.min( + end - start, + fieldSizeLimit - fieldSize + ); + if (!isDataSafe) { + chunk = Buffer.allocUnsafe(actualLen); + data.copy(chunk, 0, start, start + actualLen); + } else { + chunk = data.slice(start, start + actualLen); + } + + fieldSize += actualLen; + field.push(chunk); + if (fieldSize === fieldSizeLimit) { + skipPart = true; + partTruncated = true; + } + } + } + + break; + } + + if (isMatch) { + matchPostBoundary = 1; + + if (this._fileStream) { + // End the active file stream if the previous part was a file + this._fileStream.push(null); + this._fileStream = null; + } else if (field !== undefined) { + let data; + switch (field.length) { + case 0: + data = ''; + break; + case 1: + data = convertToUTF8(field[0], partCharset, 0); + break; + default: + data = convertToUTF8( + Buffer.concat(field, fieldSize), + partCharset, + 0 + ); + } + field = undefined; + fieldSize = 0; + this.emit( + 'field', + partName, + data, + { + nameTruncated: false, + valueTruncated: partTruncated, + encoding: partEncoding, + mimeType: partType + } + ); + } + + if (++parts === partsLimit) + this.emit('partsLimit'); + } + }; + this._bparser = new StreamSearch(`\r\n--${boundary}`, ssCb); + + this._writecb = null; + this._finalcb = null; + + // Just in case there is no preamble + this.write(BUF_CRLF); + } + + static detect(conType) { + return (conType.type === 'multipart' && conType.subtype === 'form-data'); + } + + _write(chunk, enc, cb) { + this._writecb = cb; + this._bparser.push(chunk, 0); + if (this._writecb) + callAndUnsetCb(this); + } + + _destroy(err, cb) { + this._hparser = null; + this._bparser = ignoreData; + if (!err) + err = checkEndState(this); + const fileStream = this._fileStream; + if (fileStream) { + this._fileStream = null; + fileStream.destroy(err); + } + cb(err); + } + + _final(cb) { + this._bparser.destroy(); + if (!this._complete) + return cb(new Error('Unexpected end of form')); + if (this._fileEndsLeft) + this._finalcb = finalcb.bind(null, this, cb); + else + finalcb(this, cb); + } +} + +function finalcb(self, cb, err) { + if (err) + return cb(err); + err = checkEndState(self); + cb(err); +} + +function checkEndState(self) { + if (self._hparser) + return new Error('Malformed part header'); + const fileStream = self._fileStream; + if (fileStream) { + self._fileStream = null; + fileStream.destroy(new Error('Unexpected end of file')); + } + if (!self._complete) + return new Error('Unexpected end of form'); +} + +const TOKEN = [ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +]; + +const FIELD_VCHAR = [ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +]; + +module.exports = Multipart; diff --git a/server/libs/busboy/types/urlencoded.js b/server/libs/busboy/types/urlencoded.js new file mode 100644 index 000000000..5c463a258 --- /dev/null +++ b/server/libs/busboy/types/urlencoded.js @@ -0,0 +1,350 @@ +'use strict'; + +const { Writable } = require('stream'); + +const { getDecoder } = require('../utils.js'); + +class URLEncoded extends Writable { + constructor(cfg) { + const streamOpts = { + autoDestroy: true, + emitClose: true, + highWaterMark: (typeof cfg.highWaterMark === 'number' + ? cfg.highWaterMark + : undefined), + }; + super(streamOpts); + + let charset = (cfg.defCharset || 'utf8'); + if (cfg.conType.params && typeof cfg.conType.params.charset === 'string') + charset = cfg.conType.params.charset; + + this.charset = charset; + + const limits = cfg.limits; + this.fieldSizeLimit = (limits && typeof limits.fieldSize === 'number' + ? limits.fieldSize + : 1 * 1024 * 1024); + this.fieldsLimit = (limits && typeof limits.fields === 'number' + ? limits.fields + : Infinity); + this.fieldNameSizeLimit = ( + limits && typeof limits.fieldNameSize === 'number' + ? limits.fieldNameSize + : 100 + ); + + this._inKey = true; + this._keyTrunc = false; + this._valTrunc = false; + this._bytesKey = 0; + this._bytesVal = 0; + this._fields = 0; + this._key = ''; + this._val = ''; + this._byte = -2; + this._lastPos = 0; + this._encode = 0; + this._decoder = getDecoder(charset); + } + + static detect(conType) { + return (conType.type === 'application' + && conType.subtype === 'x-www-form-urlencoded'); + } + + _write(chunk, enc, cb) { + if (this._fields >= this.fieldsLimit) + return cb(); + + let i = 0; + const len = chunk.length; + this._lastPos = 0; + + // Check if we last ended mid-percent-encoded byte + if (this._byte !== -2) { + i = readPctEnc(this, chunk, i, len); + if (i === -1) + return cb(new Error('Malformed urlencoded form')); + if (i >= len) + return cb(); + if (this._inKey) + ++this._bytesKey; + else + ++this._bytesVal; + } + +main: + while (i < len) { + if (this._inKey) { + // Parsing key + + i = skipKeyBytes(this, chunk, i, len); + + while (i < len) { + switch (chunk[i]) { + case 61: // '=' + if (this._lastPos < i) + this._key += chunk.latin1Slice(this._lastPos, i); + this._lastPos = ++i; + this._key = this._decoder(this._key, this._encode); + this._encode = 0; + this._inKey = false; + continue main; + case 38: // '&' + if (this._lastPos < i) + this._key += chunk.latin1Slice(this._lastPos, i); + this._lastPos = ++i; + this._key = this._decoder(this._key, this._encode); + this._encode = 0; + if (this._bytesKey > 0) { + this.emit( + 'field', + this._key, + '', + { nameTruncated: this._keyTrunc, + valueTruncated: false, + encoding: this.charset, + mimeType: 'text/plain' } + ); + } + this._key = ''; + this._val = ''; + this._keyTrunc = false; + this._valTrunc = false; + this._bytesKey = 0; + this._bytesVal = 0; + if (++this._fields >= this.fieldsLimit) { + this.emit('fieldsLimit'); + return cb(); + } + continue; + case 43: // '+' + if (this._lastPos < i) + this._key += chunk.latin1Slice(this._lastPos, i); + this._key += ' '; + this._lastPos = i + 1; + break; + case 37: // '%' + if (this._encode === 0) + this._encode = 1; + if (this._lastPos < i) + this._key += chunk.latin1Slice(this._lastPos, i); + this._lastPos = i + 1; + this._byte = -1; + i = readPctEnc(this, chunk, i + 1, len); + if (i === -1) + return cb(new Error('Malformed urlencoded form')); + if (i >= len) + return cb(); + ++this._bytesKey; + i = skipKeyBytes(this, chunk, i, len); + continue; + } + ++i; + ++this._bytesKey; + i = skipKeyBytes(this, chunk, i, len); + } + if (this._lastPos < i) + this._key += chunk.latin1Slice(this._lastPos, i); + } else { + // Parsing value + + i = skipValBytes(this, chunk, i, len); + + while (i < len) { + switch (chunk[i]) { + case 38: // '&' + if (this._lastPos < i) + this._val += chunk.latin1Slice(this._lastPos, i); + this._lastPos = ++i; + this._inKey = true; + this._val = this._decoder(this._val, this._encode); + this._encode = 0; + if (this._bytesKey > 0 || this._bytesVal > 0) { + this.emit( + 'field', + this._key, + this._val, + { nameTruncated: this._keyTrunc, + valueTruncated: this._valTrunc, + encoding: this.charset, + mimeType: 'text/plain' } + ); + } + this._key = ''; + this._val = ''; + this._keyTrunc = false; + this._valTrunc = false; + this._bytesKey = 0; + this._bytesVal = 0; + if (++this._fields >= this.fieldsLimit) { + this.emit('fieldsLimit'); + return cb(); + } + continue main; + case 43: // '+' + if (this._lastPos < i) + this._val += chunk.latin1Slice(this._lastPos, i); + this._val += ' '; + this._lastPos = i + 1; + break; + case 37: // '%' + if (this._encode === 0) + this._encode = 1; + if (this._lastPos < i) + this._val += chunk.latin1Slice(this._lastPos, i); + this._lastPos = i + 1; + this._byte = -1; + i = readPctEnc(this, chunk, i + 1, len); + if (i === -1) + return cb(new Error('Malformed urlencoded form')); + if (i >= len) + return cb(); + ++this._bytesVal; + i = skipValBytes(this, chunk, i, len); + continue; + } + ++i; + ++this._bytesVal; + i = skipValBytes(this, chunk, i, len); + } + if (this._lastPos < i) + this._val += chunk.latin1Slice(this._lastPos, i); + } + } + + cb(); + } + + _final(cb) { + if (this._byte !== -2) + return cb(new Error('Malformed urlencoded form')); + if (!this._inKey || this._bytesKey > 0 || this._bytesVal > 0) { + if (this._inKey) + this._key = this._decoder(this._key, this._encode); + else + this._val = this._decoder(this._val, this._encode); + this.emit( + 'field', + this._key, + this._val, + { nameTruncated: this._keyTrunc, + valueTruncated: this._valTrunc, + encoding: this.charset, + mimeType: 'text/plain' } + ); + } + cb(); + } +} + +function readPctEnc(self, chunk, pos, len) { + if (pos >= len) + return len; + + if (self._byte === -1) { + // We saw a '%' but no hex characters yet + const hexUpper = HEX_VALUES[chunk[pos++]]; + if (hexUpper === -1) + return -1; + + if (hexUpper >= 8) + self._encode = 2; // Indicate high bits detected + + if (pos < len) { + // Both hex characters are in this chunk + const hexLower = HEX_VALUES[chunk[pos++]]; + if (hexLower === -1) + return -1; + + if (self._inKey) + self._key += String.fromCharCode((hexUpper << 4) + hexLower); + else + self._val += String.fromCharCode((hexUpper << 4) + hexLower); + + self._byte = -2; + self._lastPos = pos; + } else { + // Only one hex character was available in this chunk + self._byte = hexUpper; + } + } else { + // We saw only one hex character so far + const hexLower = HEX_VALUES[chunk[pos++]]; + if (hexLower === -1) + return -1; + + if (self._inKey) + self._key += String.fromCharCode((self._byte << 4) + hexLower); + else + self._val += String.fromCharCode((self._byte << 4) + hexLower); + + self._byte = -2; + self._lastPos = pos; + } + + return pos; +} + +function skipKeyBytes(self, chunk, pos, len) { + // Skip bytes if we've truncated + if (self._bytesKey > self.fieldNameSizeLimit) { + if (!self._keyTrunc) { + if (self._lastPos < pos) + self._key += chunk.latin1Slice(self._lastPos, pos - 1); + } + self._keyTrunc = true; + for (; pos < len; ++pos) { + const code = chunk[pos]; + if (code === 61/* '=' */ || code === 38/* '&' */) + break; + ++self._bytesKey; + } + self._lastPos = pos; + } + + return pos; +} + +function skipValBytes(self, chunk, pos, len) { + // Skip bytes if we've truncated + if (self._bytesVal > self.fieldSizeLimit) { + if (!self._valTrunc) { + if (self._lastPos < pos) + self._val += chunk.latin1Slice(self._lastPos, pos - 1); + } + self._valTrunc = true; + for (; pos < len; ++pos) { + if (chunk[pos] === 38/* '&' */) + break; + ++self._bytesVal; + } + self._lastPos = pos; + } + + return pos; +} + +/* eslint-disable no-multi-spaces */ +const HEX_VALUES = [ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, + -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, +]; +/* eslint-enable no-multi-spaces */ + +module.exports = URLEncoded; diff --git a/server/libs/busboy/utils.js b/server/libs/busboy/utils.js new file mode 100644 index 000000000..8274f6c3a --- /dev/null +++ b/server/libs/busboy/utils.js @@ -0,0 +1,596 @@ +'use strict'; + +function parseContentType(str) { + if (str.length === 0) + return; + + const params = Object.create(null); + let i = 0; + + // Parse type + for (; i < str.length; ++i) { + const code = str.charCodeAt(i); + if (TOKEN[code] !== 1) { + if (code !== 47/* '/' */ || i === 0) + return; + break; + } + } + // Check for type without subtype + if (i === str.length) + return; + + const type = str.slice(0, i).toLowerCase(); + + // Parse subtype + const subtypeStart = ++i; + for (; i < str.length; ++i) { + const code = str.charCodeAt(i); + if (TOKEN[code] !== 1) { + // Make sure we have a subtype + if (i === subtypeStart) + return; + + if (parseContentTypeParams(str, i, params) === undefined) + return; + break; + } + } + // Make sure we have a subtype + if (i === subtypeStart) + return; + + const subtype = str.slice(subtypeStart, i).toLowerCase(); + + return { type, subtype, params }; +} + +function parseContentTypeParams(str, i, params) { + while (i < str.length) { + // Consume whitespace + for (; i < str.length; ++i) { + const code = str.charCodeAt(i); + if (code !== 32/* ' ' */ && code !== 9/* '\t' */) + break; + } + + // Ended on whitespace + if (i === str.length) + break; + + // Check for malformed parameter + if (str.charCodeAt(i++) !== 59/* ';' */) + return; + + // Consume whitespace + for (; i < str.length; ++i) { + const code = str.charCodeAt(i); + if (code !== 32/* ' ' */ && code !== 9/* '\t' */) + break; + } + + // Ended on whitespace (malformed) + if (i === str.length) + return; + + let name; + const nameStart = i; + // Parse parameter name + for (; i < str.length; ++i) { + const code = str.charCodeAt(i); + if (TOKEN[code] !== 1) { + if (code !== 61/* '=' */) + return; + break; + } + } + + // No value (malformed) + if (i === str.length) + return; + + name = str.slice(nameStart, i); + ++i; // Skip over '=' + + // No value (malformed) + if (i === str.length) + return; + + let value = ''; + let valueStart; + if (str.charCodeAt(i) === 34/* '"' */) { + valueStart = ++i; + let escaping = false; + // Parse quoted value + for (; i < str.length; ++i) { + const code = str.charCodeAt(i); + if (code === 92/* '\\' */) { + if (escaping) { + valueStart = i; + escaping = false; + } else { + value += str.slice(valueStart, i); + escaping = true; + } + continue; + } + if (code === 34/* '"' */) { + if (escaping) { + valueStart = i; + escaping = false; + continue; + } + value += str.slice(valueStart, i); + break; + } + if (escaping) { + valueStart = i - 1; + escaping = false; + } + // Invalid unescaped quoted character (malformed) + if (QDTEXT[code] !== 1) + return; + } + + // No end quote (malformed) + if (i === str.length) + return; + + ++i; // Skip over double quote + } else { + valueStart = i; + // Parse unquoted value + for (; i < str.length; ++i) { + const code = str.charCodeAt(i); + if (TOKEN[code] !== 1) { + // No value (malformed) + if (i === valueStart) + return; + break; + } + } + value = str.slice(valueStart, i); + } + + name = name.toLowerCase(); + if (params[name] === undefined) + params[name] = value; + } + + return params; +} + +function parseDisposition(str, defDecoder) { + if (str.length === 0) + return; + + const params = Object.create(null); + let i = 0; + + for (; i < str.length; ++i) { + const code = str.charCodeAt(i); + if (TOKEN[code] !== 1) { + if (parseDispositionParams(str, i, params, defDecoder) === undefined) + return; + break; + } + } + + const type = str.slice(0, i).toLowerCase(); + + return { type, params }; +} + +function parseDispositionParams(str, i, params, defDecoder) { + while (i < str.length) { + // Consume whitespace + for (; i < str.length; ++i) { + const code = str.charCodeAt(i); + if (code !== 32/* ' ' */ && code !== 9/* '\t' */) + break; + } + + // Ended on whitespace + if (i === str.length) + break; + + // Check for malformed parameter + if (str.charCodeAt(i++) !== 59/* ';' */) + return; + + // Consume whitespace + for (; i < str.length; ++i) { + const code = str.charCodeAt(i); + if (code !== 32/* ' ' */ && code !== 9/* '\t' */) + break; + } + + // Ended on whitespace (malformed) + if (i === str.length) + return; + + let name; + const nameStart = i; + // Parse parameter name + for (; i < str.length; ++i) { + const code = str.charCodeAt(i); + if (TOKEN[code] !== 1) { + if (code === 61/* '=' */) + break; + return; + } + } + + // No value (malformed) + if (i === str.length) + return; + + let value = ''; + let valueStart; + let charset; + //~ let lang; + name = str.slice(nameStart, i); + if (name.charCodeAt(name.length - 1) === 42/* '*' */) { + // Extended value + + const charsetStart = ++i; + // Parse charset name + for (; i < str.length; ++i) { + const code = str.charCodeAt(i); + if (CHARSET[code] !== 1) { + if (code !== 39/* '\'' */) + return; + break; + } + } + + // Incomplete charset (malformed) + if (i === str.length) + return; + + charset = str.slice(charsetStart, i); + ++i; // Skip over the '\'' + + //~ const langStart = ++i; + // Parse language name + for (; i < str.length; ++i) { + const code = str.charCodeAt(i); + if (code === 39/* '\'' */) + break; + } + + // Incomplete language (malformed) + if (i === str.length) + return; + + //~ lang = str.slice(langStart, i); + ++i; // Skip over the '\'' + + // No value (malformed) + if (i === str.length) + return; + + valueStart = i; + + let encode = 0; + // Parse value + for (; i < str.length; ++i) { + const code = str.charCodeAt(i); + if (EXTENDED_VALUE[code] !== 1) { + if (code === 37/* '%' */) { + let hexUpper; + let hexLower; + if (i + 2 < str.length + && (hexUpper = HEX_VALUES[str.charCodeAt(i + 1)]) !== -1 + && (hexLower = HEX_VALUES[str.charCodeAt(i + 2)]) !== -1) { + const byteVal = (hexUpper << 4) + hexLower; + value += str.slice(valueStart, i); + value += String.fromCharCode(byteVal); + i += 2; + valueStart = i + 1; + if (byteVal >= 128) + encode = 2; + else if (encode === 0) + encode = 1; + continue; + } + // '%' disallowed in non-percent encoded contexts (malformed) + return; + } + break; + } + } + + value += str.slice(valueStart, i); + value = convertToUTF8(value, charset, encode); + if (value === undefined) + return; + } else { + // Non-extended value + + ++i; // Skip over '=' + + // No value (malformed) + if (i === str.length) + return; + + if (str.charCodeAt(i) === 34/* '"' */) { + valueStart = ++i; + let escaping = false; + // Parse quoted value + for (; i < str.length; ++i) { + const code = str.charCodeAt(i); + if (code === 92/* '\\' */) { + if (escaping) { + valueStart = i; + escaping = false; + } else { + value += str.slice(valueStart, i); + escaping = true; + } + continue; + } + if (code === 34/* '"' */) { + if (escaping) { + valueStart = i; + escaping = false; + continue; + } + value += str.slice(valueStart, i); + break; + } + if (escaping) { + valueStart = i - 1; + escaping = false; + } + // Invalid unescaped quoted character (malformed) + if (QDTEXT[code] !== 1) + return; + } + + // No end quote (malformed) + if (i === str.length) + return; + + ++i; // Skip over double quote + } else { + valueStart = i; + // Parse unquoted value + for (; i < str.length; ++i) { + const code = str.charCodeAt(i); + if (TOKEN[code] !== 1) { + // No value (malformed) + if (i === valueStart) + return; + break; + } + } + value = str.slice(valueStart, i); + } + + value = defDecoder(value, 2); + if (value === undefined) + return; + } + + name = name.toLowerCase(); + if (params[name] === undefined) + params[name] = value; + } + + return params; +} + +function getDecoder(charset) { + let lc; + while (true) { + switch (charset) { + case 'utf-8': + case 'utf8': + return decoders.utf8; + case 'latin1': + case 'ascii': // TODO: Make these a separate, strict decoder? + case 'us-ascii': + case 'iso-8859-1': + case 'iso8859-1': + case 'iso88591': + case 'iso_8859-1': + case 'windows-1252': + case 'iso_8859-1:1987': + case 'cp1252': + case 'x-cp1252': + return decoders.latin1; + case 'utf16le': + case 'utf-16le': + case 'ucs2': + case 'ucs-2': + return decoders.utf16le; + case 'base64': + return decoders.base64; + default: + if (lc === undefined) { + lc = true; + charset = charset.toLowerCase(); + continue; + } + return decoders.other.bind(charset); + } + } +} + +const decoders = { + utf8: (data, hint) => { + if (data.length === 0) + return ''; + if (typeof data === 'string') { + // If `data` never had any percent-encoded bytes or never had any that + // were outside of the ASCII range, then we can safely just return the + // input since UTF-8 is ASCII compatible + if (hint < 2) + return data; + + data = Buffer.from(data, 'latin1'); + } + return data.utf8Slice(0, data.length); + }, + + latin1: (data, hint) => { + if (data.length === 0) + return ''; + if (typeof data === 'string') + return data; + return data.latin1Slice(0, data.length); + }, + + utf16le: (data, hint) => { + if (data.length === 0) + return ''; + if (typeof data === 'string') + data = Buffer.from(data, 'latin1'); + return data.ucs2Slice(0, data.length); + }, + + base64: (data, hint) => { + if (data.length === 0) + return ''; + if (typeof data === 'string') + data = Buffer.from(data, 'latin1'); + return data.base64Slice(0, data.length); + }, + + other: (data, hint) => { + if (data.length === 0) + return ''; + if (typeof data === 'string') + data = Buffer.from(data, 'latin1'); + try { + const decoder = new TextDecoder(this); + return decoder.decode(data); + } catch {} + }, +}; + +function convertToUTF8(data, charset, hint) { + const decode = getDecoder(charset); + if (decode) + return decode(data, hint); +} + +function basename(path) { + if (typeof path !== 'string') + return ''; + for (let i = path.length - 1; i >= 0; --i) { + switch (path.charCodeAt(i)) { + case 0x2F: // '/' + case 0x5C: // '\' + path = path.slice(i + 1); + return (path === '..' || path === '.' ? '' : path); + } + } + return (path === '..' || path === '.' ? '' : path); +} + +const TOKEN = [ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +]; + +const QDTEXT = [ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +]; + +const CHARSET = [ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +]; + +const EXTENDED_VALUE = [ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +]; + +/* eslint-disable no-multi-spaces */ +const HEX_VALUES = [ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, + -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, +]; +/* eslint-enable no-multi-spaces */ + +module.exports = { + basename, + convertToUTF8, + getDecoder, + parseContentType, + parseDisposition, +}; diff --git a/server/libs/expressFileupload/LICENSE b/server/libs/expressFileupload/LICENSE new file mode 100644 index 000000000..7f6df6aa2 --- /dev/null +++ b/server/libs/expressFileupload/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2015 Richard Girges + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/server/libs/expressFileupload/fileFactory.js b/server/libs/expressFileupload/fileFactory.js new file mode 100644 index 000000000..02b82df2f --- /dev/null +++ b/server/libs/expressFileupload/fileFactory.js @@ -0,0 +1,65 @@ +'use strict'; + +const { + isFunc, + debugLog, + moveFile, + promiseCallback, + checkAndMakeDir, + saveBufferToFile +} = require('./utilities'); + +/** + * Returns Local function that moves the file to a different location on the filesystem + * which takes two function arguments to make it compatible w/ Promise or Callback APIs + * @param {String} filePath - destination file path. + * @param {Object} options - file factory options. + * @param {Object} fileUploadOptions - middleware options. + * @returns {Function} + */ +const moveFromTemp = (filePath, options, fileUploadOptions) => (resolve, reject) => { + debugLog(fileUploadOptions, `Moving temporary file ${options.tempFilePath} to ${filePath}`); + moveFile(options.tempFilePath, filePath, promiseCallback(resolve, reject)); +}; + +/** + * Returns Local function that moves the file from buffer to a different location on the filesystem + * which takes two function arguments to make it compatible w/ Promise or Callback APIs + * @param {String} filePath - destination file path. + * @param {Object} options - file factory options. + * @param {Object} fileUploadOptions - middleware options. + * @returns {Function} + */ +const moveFromBuffer = (filePath, options, fileUploadOptions) => (resolve, reject) => { + debugLog(fileUploadOptions, `Moving uploaded buffer to ${filePath}`); + saveBufferToFile(options.buffer, filePath, promiseCallback(resolve, reject)); +}; + +module.exports = (options, fileUploadOptions = {}) => { + // see: https://github.com/richardgirges/express-fileupload/issues/14 + // firefox uploads empty file in case of cache miss when f5ing page. + // resulting in unexpected behavior. if there is no file data, the file is invalid. + // if (!fileUploadOptions.useTempFiles && !options.buffer.length) return; + + // Create and return file object. + return { + name: options.name, + data: options.buffer, + size: options.size, + encoding: options.encoding, + tempFilePath: options.tempFilePath, + truncated: options.truncated, + mimetype: options.mimetype, + md5: options.hash, + mv: (filePath, callback) => { + // Define a propper move function. + const moveFunc = fileUploadOptions.useTempFiles + ? moveFromTemp(filePath, options, fileUploadOptions) + : moveFromBuffer(filePath, options, fileUploadOptions); + // Create a folder for a file. + checkAndMakeDir(fileUploadOptions, filePath); + // If callback is passed in, use the callback API, otherwise return a promise. + return isFunc(callback) ? moveFunc(callback) : new Promise(moveFunc); + } + }; +}; diff --git a/server/libs/expressFileupload/index.js b/server/libs/expressFileupload/index.js new file mode 100644 index 000000000..95b39ba23 --- /dev/null +++ b/server/libs/expressFileupload/index.js @@ -0,0 +1,39 @@ +'use strict'; + +const path = require('path'); +const processMultipart = require('./processMultipart'); +const isEligibleRequest = require('./isEligibleRequest'); +const { buildOptions, debugLog } = require('./utilities'); +const busboy = require('../busboy'); // eslint-disable-line no-unused-vars + +const DEFAULT_OPTIONS = { + debug: false, + uploadTimeout: 60000, + fileHandler: false, + uriDecodeFileNames: false, + safeFileNames: false, + preserveExtension: false, + abortOnLimit: false, + responseOnLimit: 'File size limit has been reached', + limitHandler: false, + createParentPath: false, + parseNested: false, + useTempFiles: false, + tempFileDir: path.join(process.cwd(), 'tmp') +}; + +/** + * Expose the file upload middleware + * @param {DEFAULT_OPTIONS & busboy.BusboyConfig} options - Middleware options. + * @returns {Function} - express-fileupload middleware. + */ +module.exports = (options) => { + const uploadOptions = buildOptions(DEFAULT_OPTIONS, options); + return (req, res, next) => { + if (!isEligibleRequest(req)) { + debugLog(uploadOptions, 'Request is not eligible for file upload!'); + return next(); + } + processMultipart(uploadOptions, req, res, next); + }; +}; diff --git a/server/libs/expressFileupload/isEligibleRequest.js b/server/libs/expressFileupload/isEligibleRequest.js new file mode 100644 index 000000000..0c252833f --- /dev/null +++ b/server/libs/expressFileupload/isEligibleRequest.js @@ -0,0 +1,34 @@ +const ACCEPTABLE_CONTENT_TYPE = /^(multipart\/.+);(.*)$/i; +const UNACCEPTABLE_METHODS = ['GET', 'HEAD']; + +/** + * Ensures the request contains a content body + * @param {Object} req Express req object + * @returns {Boolean} + */ +const hasBody = (req) => { + return ('transfer-encoding' in req.headers) || + ('content-length' in req.headers && req.headers['content-length'] !== '0'); +}; + +/** + * Ensures the request is not using a non-compliant multipart method + * such as GET or HEAD + * @param {Object} req Express req object + * @returns {Boolean} + */ +const hasAcceptableMethod = req => !UNACCEPTABLE_METHODS.includes(req.method); + +/** + * Ensures that only multipart requests are processed by express-fileupload + * @param {Object} req Express req object + * @returns {Boolean} + */ +const hasAcceptableContentType = req => ACCEPTABLE_CONTENT_TYPE.test(req.headers['content-type']); + +/** + * Ensures that the request in question is eligible for file uploads + * @param {Object} req Express req object + * @returns {Boolean} + */ +module.exports = req => hasBody(req) && hasAcceptableMethod(req) && hasAcceptableContentType(req); diff --git a/server/libs/expressFileupload/memHandler.js b/server/libs/expressFileupload/memHandler.js new file mode 100644 index 000000000..09accfe09 --- /dev/null +++ b/server/libs/expressFileupload/memHandler.js @@ -0,0 +1,42 @@ +const crypto = require('crypto'); +const { debugLog } = require('./utilities'); + +/** + * memHandler - In memory upload handler + * @param {Object} options + * @param {String} fieldname + * @param {String} filename + * @returns {Object} + */ +module.exports = (options, fieldname, filename) => { + const buffers = []; + const hash = crypto.createHash('md5'); + let fileSize = 0; + let completed = false; + + const getBuffer = () => Buffer.concat(buffers, fileSize); + + return { + dataHandler: (data) => { + if (completed === true) { + debugLog(options, `Error: got ${fieldname}->${filename} data chunk for completed upload!`); + return; + } + buffers.push(data); + hash.update(data); + fileSize += data.length; + debugLog(options, `Uploading ${fieldname}->${filename}, bytes:${fileSize}...`); + }, + getBuffer: getBuffer, + getFilePath: () => '', + getFileSize: () => fileSize, + getHash: () => hash.digest('hex'), + complete: () => { + debugLog(options, `Upload ${fieldname}->${filename} completed, bytes:${fileSize}.`); + completed = true; + return getBuffer(); + }, + cleanup: () => { completed = true; }, + getWritePromise: () => Promise.resolve() + }; +}; diff --git a/server/libs/expressFileupload/processMultipart.js b/server/libs/expressFileupload/processMultipart.js new file mode 100644 index 000000000..32fb690a7 --- /dev/null +++ b/server/libs/expressFileupload/processMultipart.js @@ -0,0 +1,168 @@ +const Busboy = require('../busboy'); +const UploadTimer = require('./uploadtimer'); +const fileFactory = require('./fileFactory'); +const memHandler = require('./memHandler'); +const tempFileHandler = require('./tempFileHandler'); +const processNested = require('./processNested'); +const { + isFunc, + debugLog, + buildFields, + buildOptions, + parseFileName +} = require('./utilities'); + +const waitFlushProperty = Symbol('wait flush property symbol'); + +/** + * Processes multipart request + * Builds a req.body object for fields + * Builds a req.files object for files + * @param {Object} options expressFileupload and Busboy options + * @param {Object} req Express request object + * @param {Object} res Express response object + * @param {Function} next Express next method + * @return {void} + */ +module.exports = (options, req, res, next) => { + req.files = null; + + // Build busboy options and init busboy instance. + const busboyOptions = buildOptions(options, { headers: req.headers }); + const busboy = Busboy(busboyOptions); + + // Close connection with specified reason and http code, default: 400 Bad Request. + const closeConnection = (code, reason) => { + req.unpipe(busboy); + res.writeHead(code || 400, { Connection: 'close' }); + res.end(reason || 'Bad Request'); + }; + + // Express proxies sometimes attach multipart data to a buffer + if (req.body instanceof Buffer) { + req.body = Object.create(null); + } + // Build multipart req.body fields + busboy.on('field', (field, val) => req.body = buildFields(req.body, field, val)); + + // Build req.files fields + busboy.on('file', (field, file, info) => { + // Parse file name(cutting huge names, decoding, etc..). + const { filename: name, encoding, mimeType: mime } = info; + const filename = parseFileName(options, name); + // Define methods and handlers for upload process. + const { + dataHandler, + getFilePath, + getFileSize, + getHash, + complete, + cleanup, + getWritePromise + } = options.useTempFiles + ? tempFileHandler(options, field, filename) // Upload into temporary file. + : memHandler(options, field, filename); // Upload into RAM. + + const writePromise = options.useTempFiles + ? getWritePromise().catch(err => { + req.unpipe(busboy); + req.resume(); + cleanup(); + next(err); + }) : getWritePromise(); + + // Define upload timer. + const uploadTimer = new UploadTimer(options.uploadTimeout, () => { + file.removeAllListeners('data'); + file.resume(); + // After destroy an error event will be emitted and file clean up will be done. + file.destroy(new Error(`Upload timeout ${field}->${filename}, bytes:${getFileSize()}`)); + }); + + file.on('limit', () => { + debugLog(options, `Size limit reached for ${field}->${filename}, bytes:${getFileSize()}`); + // Reset upload timer in case of file limit reached. + uploadTimer.clear(); + // Run a user defined limit handler if it has been set. + if (isFunc(options.limitHandler)) return options.limitHandler(req, res, next); + // Close connection with 413 code and do cleanup if abortOnLimit set(default: false). + if (options.abortOnLimit) { + debugLog(options, `Aborting upload because of size limit ${field}->${filename}.`); + !isFunc(options.limitHandler) ? closeConnection(413, options.responseOnLimit) : ''; + cleanup(); + } + }); + + file.on('data', (data) => { + uploadTimer.set(); // Refresh upload timer each time new data chunk came. + dataHandler(data); // Handle new piece of data. + }); + + file.on('end', () => { + const size = getFileSize(); + // Debug logging for file upload ending. + debugLog(options, `Upload finished ${field}->${filename}, bytes:${size}`); + // Reset upload timer in case of end event. + uploadTimer.clear(); + // See https://github.com/richardgirges/express-fileupload/issues/191 + // Do not add file instance to the req.files if original name and size are empty. + // Empty name and zero size indicates empty file field in the posted form. + if (!name && size === 0) { + if (options.useTempFiles) { + cleanup(); + debugLog(options, `Removing the empty file ${field}->${filename}`); + } + return debugLog(options, `Don't add file instance if original name and size are empty`); + } + req.files = buildFields(req.files, field, fileFactory({ + buffer: complete(), + name: filename, + tempFilePath: getFilePath(), + hash: getHash(), + size, + encoding, + truncated: file.truncated, + mimetype: mime + }, options)); + + if (!req[waitFlushProperty]) { + req[waitFlushProperty] = []; + } + req[waitFlushProperty].push(writePromise); + }); + + file.on('error', (err) => { + uploadTimer.clear(); // Reset upload timer in case of errors. + debugLog(options, err); + cleanup(); + next(); + }); + + // Debug logging for a new file upload. + debugLog(options, `New upload started ${field}->${filename}, bytes:${getFileSize()}`); + // Set new upload timeout for a new file. + uploadTimer.set(); + }); + + busboy.on('finish', () => { + debugLog(options, `Busboy finished parsing request.`); + if (options.parseNested) { + req.body = processNested(req.body); + req.files = processNested(req.files); + } + + if (!req[waitFlushProperty]) return next(); + Promise.all(req[waitFlushProperty]) + .then(() => { + delete req[waitFlushProperty]; + next(); + }); + }); + + busboy.on('error', (err) => { + debugLog(options, `Busboy error`); + next(err); + }); + + req.pipe(busboy); +}; diff --git a/server/libs/expressFileupload/processNested.js b/server/libs/expressFileupload/processNested.js new file mode 100644 index 000000000..9c8b648ed --- /dev/null +++ b/server/libs/expressFileupload/processNested.js @@ -0,0 +1,35 @@ +const { isSafeFromPollution } = require("./utilities"); + +module.exports = function(data){ + if (!data || data.length < 1) return Object.create(null); + + let d = Object.create(null), + keys = Object.keys(data); + + for (let i = 0; i < keys.length; i++) { + let key = keys[i], + value = data[key], + current = d, + keyParts = key + .replace(new RegExp(/\[/g), '.') + .replace(new RegExp(/\]/g), '') + .split('.'); + + for (let index = 0; index < keyParts.length; index++){ + let k = keyParts[index]; + + // Ensure we don't allow prototype pollution + if (!isSafeFromPollution(current, k)) { + continue; + } + + if (index >= keyParts.length - 1){ + current[k] = value; + } else { + if (!current[k]) current[k] = !isNaN(keyParts[index + 1]) ? [] : Object.create(null); + current = current[k]; + } + } + } + return d; +}; diff --git a/server/libs/expressFileupload/tempFileHandler.js b/server/libs/expressFileupload/tempFileHandler.js new file mode 100644 index 000000000..bfaca8b4f --- /dev/null +++ b/server/libs/expressFileupload/tempFileHandler.js @@ -0,0 +1,64 @@ +const fs = require('fs'); +const path = require('path'); +const crypto = require('crypto'); +const { + debugLog, + checkAndMakeDir, + getTempFilename, + deleteFile +} = require('./utilities'); + +module.exports = (options, fieldname, filename) => { + const dir = path.normalize(options.tempFileDir); + const tempFilePath = path.join(dir, getTempFilename()); + checkAndMakeDir({ createParentPath: true }, tempFilePath); + + debugLog(options, `Temporary file path is ${tempFilePath}`); + + const hash = crypto.createHash('md5'); + let fileSize = 0; + let completed = false; + + debugLog(options, `Opening write stream for ${fieldname}->${filename}...`); + const writeStream = fs.createWriteStream(tempFilePath); + const writePromise = new Promise((resolve, reject) => { + writeStream.on('finish', () => resolve()); + writeStream.on('error', (err) => { + debugLog(options, `Error write temp file: ${err}`); + reject(err); + }); + }); + + return { + dataHandler: (data) => { + if (completed === true) { + debugLog(options, `Error: got ${fieldname}->${filename} data chunk for completed upload!`); + return; + } + writeStream.write(data); + hash.update(data); + fileSize += data.length; + debugLog(options, `Uploading ${fieldname}->${filename}, bytes:${fileSize}...`); + }, + getFilePath: () => tempFilePath, + getFileSize: () => fileSize, + getHash: () => hash.digest('hex'), + complete: () => { + completed = true; + debugLog(options, `Upload ${fieldname}->${filename} completed, bytes:${fileSize}.`); + if (writeStream !== false) writeStream.end(); + // Return empty buff since data was uploaded into a temp file. + return Buffer.concat([]); + }, + cleanup: () => { + completed = true; + debugLog(options, `Cleaning up temporary file ${tempFilePath}...`); + writeStream.end(); + deleteFile(tempFilePath, err => (err + ? debugLog(options, `Cleaning up temporary file ${tempFilePath} failed: ${err}`) + : debugLog(options, `Cleaning up temporary file ${tempFilePath} done.`) + )); + }, + getWritePromise: () => writePromise + }; +}; diff --git a/server/libs/expressFileupload/uploadtimer.js b/server/libs/expressFileupload/uploadtimer.js new file mode 100644 index 000000000..d29ab46a7 --- /dev/null +++ b/server/libs/expressFileupload/uploadtimer.js @@ -0,0 +1,26 @@ +class UploadTimer { + /** + * @constructor + * @param {number} timeout - timer timeout in msecs. + * @param {Function} callback - callback to run when timeout reached. + */ + constructor(timeout = 0, callback = () => {}) { + this.timeout = timeout; + this.callback = callback; + this.timer = null; + } + + clear() { + clearTimeout(this.timer); + } + + set() { + // Do not start a timer if zero timeout or it hasn't been set. + if (!this.timeout) return false; + this.clear(); + this.timer = setTimeout(this.callback, this.timeout); + return true; + } +} + +module.exports = UploadTimer; diff --git a/server/libs/expressFileupload/utilities.js b/server/libs/expressFileupload/utilities.js new file mode 100644 index 000000000..b6bad01be --- /dev/null +++ b/server/libs/expressFileupload/utilities.js @@ -0,0 +1,311 @@ +'use strict'; + +const fs = require('fs'); +const path = require('path'); +const { Readable } = require('stream'); + +// Parameters for safe file name parsing. +const SAFE_FILE_NAME_REGEX = /[^\w-]/g; +const MAX_EXTENSION_LENGTH = 3; + +// Parameters to generate unique temporary file names: +const TEMP_COUNTER_MAX = 65536; +const TEMP_PREFIX = 'tmp'; +let tempCounter = 0; + +/** + * Logs message to console if debug option set to true. + * @param {Object} options - options object. + * @param {string} msg - message to log. + * @returns {boolean} - false if debug is off. + */ +const debugLog = (options, msg) => { + const opts = options || {}; + if (!opts.debug) return false; + console.log(`Express-file-upload: ${msg}`); // eslint-disable-line + return true; +}; + +/** + * Generates unique temporary file name. e.g. tmp-5000-156788789789. + * @param {string} prefix - a prefix for generated unique file name. + * @returns {string} + */ +const getTempFilename = (prefix = TEMP_PREFIX) => { + tempCounter = tempCounter >= TEMP_COUNTER_MAX ? 1 : tempCounter + 1; + return `${prefix}-${tempCounter}-${Date.now()}`; +}; + +/** + * isFunc: Checks if argument is a function. + * @returns {boolean} - Returns true if argument is a function. + */ +const isFunc = func => func && func.constructor && func.call && func.apply ? true: false; + +/** + * Set errorFunc to the same value as successFunc for callback mode. + * @returns {Function} + */ +const errorFunc = (resolve, reject) => isFunc(reject) ? reject : resolve; + +/** + * Return a callback function for promise resole/reject args. + * Ensures that callback is called only once. + * @returns {Function} + */ +const promiseCallback = (resolve, reject) => { + let hasFired = false; + return (err) => { + if (hasFired) { + return; + } + + hasFired = true; + return err ? errorFunc(resolve, reject)(err) : resolve(); + }; +}; + +/** + * Builds instance options from arguments objects(can't be arrow function). + * @returns {Object} - result options. + */ +const buildOptions = function() { + const result = {}; + [...arguments].forEach(options => { + if (!options || typeof options !== 'object') return; + Object.keys(options).forEach(i => result[i] = options[i]); + }); + return result; +}; + +// The default prototypes for both objects and arrays. +// Used by isSafeFromPollution +const OBJECT_PROTOTYPE_KEYS = Object.getOwnPropertyNames(Object.prototype); +const ARRAY_PROTOTYPE_KEYS = Object.getOwnPropertyNames(Array.prototype); + +/** + * Determines whether a key insertion into an object could result in a prototype pollution + * @param {Object} base - The object whose insertion we are checking + * @param {string} key - The key that will be inserted + */ +const isSafeFromPollution = (base, key) => { + // We perform an instanceof check instead of Array.isArray as the former is more + // permissive for cases in which the object as an Array prototype but was not constructed + // via an Array constructor or literal. + const TOUCHES_ARRAY_PROTOTYPE = (base instanceof Array) && ARRAY_PROTOTYPE_KEYS.includes(key); + const TOUCHES_OBJECT_PROTOTYPE = OBJECT_PROTOTYPE_KEYS.includes(key); + + return !TOUCHES_ARRAY_PROTOTYPE && !TOUCHES_OBJECT_PROTOTYPE; +}; + +/** + * Builds request fields (using to build req.body and req.files) + * @param {Object} instance - request object. + * @param {string} field - field name. + * @param {any} value - field value. + * @returns {Object} + */ +const buildFields = (instance, field, value) => { + // Do nothing if value is not set. + if (value === null || value === undefined) return instance; + instance = instance || Object.create(null); + + if (!isSafeFromPollution(instance, field)) { + return instance; + } + // Non-array fields + if (!instance[field]) { + instance[field] = value; + return instance; + } + // Array fields + if (instance[field] instanceof Array) { + instance[field].push(value); + } else { + instance[field] = [instance[field], value]; + } + return instance; +}; + +/** + * Creates a folder for file specified in the path variable + * @param {Object} fileUploadOptions + * @param {string} filePath + * @returns {boolean} + */ +const checkAndMakeDir = (fileUploadOptions, filePath) => { + // Check upload options were set. + if (!fileUploadOptions) return false; + if (!fileUploadOptions.createParentPath) return false; + // Check whether folder for the file exists. + if (!filePath) return false; + const parentPath = path.dirname(filePath); + // Create folder if it doesn't exist. + if (!fs.existsSync(parentPath)) fs.mkdirSync(parentPath, { recursive: true }); + // Checks folder again and return a results. + return fs.existsSync(parentPath); +}; + +/** + * Deletes a file. + * @param {string} file - Path to the file to delete. + * @param {Function} callback + */ +const deleteFile = (file, callback) => fs.unlink(file, callback); + +/** + * Copy file via streams + * @param {string} src - Path to the source file + * @param {string} dst - Path to the destination file. + */ +const copyFile = (src, dst, callback) => { + // cbCalled flag and runCb helps to run cb only once. + let cbCalled = false; + let runCb = (err) => { + if (cbCalled) return; + cbCalled = true; + callback(err); + }; + // Create read stream + let readable = fs.createReadStream(src); + readable.on('error', runCb); + // Create write stream + let writable = fs.createWriteStream(dst); + writable.on('error', (err)=>{ + readable.destroy(); + runCb(err); + }); + writable.on('close', () => runCb()); + // Copy file via piping streams. + readable.pipe(writable); +}; + +/** + * moveFile: moves the file from src to dst. + * Firstly trying to rename the file if no luck copying it to dst and then deleteing src. + * @param {string} src - Path to the source file + * @param {string} dst - Path to the destination file. + * @param {Function} callback - A callback function. + */ +const moveFile = (src, dst, callback) => fs.rename(src, dst, err => (err + ? copyFile(src, dst, err => err ? callback(err) : deleteFile(src, callback)) + : callback() +)); + +/** + * Save buffer data to a file. + * @param {Buffer} buffer - buffer to save to a file. + * @param {string} filePath - path to a file. + */ +const saveBufferToFile = (buffer, filePath, callback) => { + if (!Buffer.isBuffer(buffer)) { + return callback(new Error('buffer variable should be type of Buffer!')); + } + // Setup readable stream from buffer. + let streamData = buffer; + let readStream = Readable(); + readStream._read = () => { + readStream.push(streamData); + streamData = null; + }; + // Setup file system writable stream. + let fstream = fs.createWriteStream(filePath); + // console.log("Calling saveBuffer"); + fstream.on('error', err => { + // console.log("err cb") + callback(err); + }); + fstream.on('close', () => { + // console.log("close cb"); + callback(); + }); + // Copy file via piping streams. + readStream.pipe(fstream); +}; + +/** + * Decodes uriEncoded file names. + * @param fileName {String} - file name to decode. + * @returns {String} + */ +const uriDecodeFileName = (opts, fileName) => { + return opts.uriDecodeFileNames ? decodeURIComponent(fileName) : fileName; +}; + +/** + * Parses filename and extension and returns object {name, extension}. + * @param {boolean|integer} preserveExtension - true/false or number of characters for extension. + * @param {string} fileName - file name to parse. + * @returns {Object} - { name, extension }. + */ +const parseFileNameExtension = (preserveExtension, fileName) => { + const preserveExtensionLength = parseInt(preserveExtension); + const result = {name: fileName, extension: ''}; + if (!preserveExtension && preserveExtensionLength !== 0) return result; + // Define maximum extension length + const maxExtLength = isNaN(preserveExtensionLength) + ? MAX_EXTENSION_LENGTH + : Math.abs(preserveExtensionLength); + + const nameParts = fileName.split('.'); + if (nameParts.length < 2) return result; + + let extension = nameParts.pop(); + if ( + extension.length > maxExtLength && + maxExtLength > 0 + ) { + nameParts[nameParts.length - 1] += + '.' + + extension.substr(0, extension.length - maxExtLength); + extension = extension.substr(-maxExtLength); + } + + result.extension = maxExtLength ? extension : ''; + result.name = nameParts.join('.'); + return result; +}; + +/** + * Parse file name and extension. + * @param {Object} opts - middleware options. + * @param {string} fileName - Uploaded file name. + * @returns {string} + */ +const parseFileName = (opts, fileName) => { + // Check fileName argument + if (!fileName || typeof fileName !== 'string') return getTempFilename(); + // Cut off file name if it's lenght more then 255. + let parsedName = fileName.length <= 255 ? fileName : fileName.substr(0, 255); + // Decode file name if uriDecodeFileNames option set true. + parsedName = uriDecodeFileName(opts, parsedName); + // Stop parsing file name if safeFileNames options hasn't been set. + if (!opts.safeFileNames) return parsedName; + // Set regular expression for the file name. + const nameRegex = typeof opts.safeFileNames === 'object' && opts.safeFileNames instanceof RegExp + ? opts.safeFileNames + : SAFE_FILE_NAME_REGEX; + // Parse file name extension. + let {name, extension} = parseFileNameExtension(opts.preserveExtension, parsedName); + if (extension.length) extension = '.' + extension.replace(nameRegex, ''); + + return name.replace(nameRegex, '').concat(extension); +}; + +module.exports = { + isFunc, + debugLog, + copyFile, // For testing purpose. + moveFile, + errorFunc, + deleteFile, // For testing purpose. + buildFields, + buildOptions, + parseFileName, + getTempFilename, + promiseCallback, + checkAndMakeDir, + saveBufferToFile, + uriDecodeFileName, + isSafeFromPollution +}; diff --git a/server/libs/streamsearch/LICENSE b/server/libs/streamsearch/LICENSE new file mode 100644 index 000000000..290762e94 --- /dev/null +++ b/server/libs/streamsearch/LICENSE @@ -0,0 +1,19 @@ +Copyright Brian White. All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to +deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +sell copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +IN THE SOFTWARE. \ No newline at end of file diff --git a/server/libs/streamsearch/index.js b/server/libs/streamsearch/index.js new file mode 100644 index 000000000..8683b58e0 --- /dev/null +++ b/server/libs/streamsearch/index.js @@ -0,0 +1,273 @@ +'use strict'; + +// +// used by busboy +// Source: https://github.com/mscdex/streamsearch +// + +/* + Based heavily on the Streaming Boyer-Moore-Horspool C++ implementation + by Hongli Lai at: https://github.com/FooBarWidget/boyer-moore-horspool +*/ +function memcmp(buf1, pos1, buf2, pos2, num) { + for (let i = 0; i < num; ++i) { + if (buf1[pos1 + i] !== buf2[pos2 + i]) + return false; + } + return true; +} + +class SBMH { + constructor(needle, cb) { + if (typeof cb !== 'function') + throw new Error('Missing match callback'); + + if (typeof needle === 'string') + needle = Buffer.from(needle); + else if (!Buffer.isBuffer(needle)) + throw new Error(`Expected Buffer for needle, got ${typeof needle}`); + + const needleLen = needle.length; + + this.maxMatches = Infinity; + this.matches = 0; + + this._cb = cb; + this._lookbehindSize = 0; + this._needle = needle; + this._bufPos = 0; + + this._lookbehind = Buffer.allocUnsafe(needleLen); + + // Initialize occurrence table. + this._occ = [ + needleLen, needleLen, needleLen, needleLen, needleLen, needleLen, + needleLen, needleLen, needleLen, needleLen, needleLen, needleLen, + needleLen, needleLen, needleLen, needleLen, needleLen, needleLen, + needleLen, needleLen, needleLen, needleLen, needleLen, needleLen, + needleLen, needleLen, needleLen, needleLen, needleLen, needleLen, + needleLen, needleLen, needleLen, needleLen, needleLen, needleLen, + needleLen, needleLen, needleLen, needleLen, needleLen, needleLen, + needleLen, needleLen, needleLen, needleLen, needleLen, needleLen, + needleLen, needleLen, needleLen, needleLen, needleLen, needleLen, + needleLen, needleLen, needleLen, needleLen, needleLen, needleLen, + needleLen, needleLen, needleLen, needleLen, needleLen, needleLen, + needleLen, needleLen, needleLen, needleLen, needleLen, needleLen, + needleLen, needleLen, needleLen, needleLen, needleLen, needleLen, + needleLen, needleLen, needleLen, needleLen, needleLen, needleLen, + needleLen, needleLen, needleLen, needleLen, needleLen, needleLen, + needleLen, needleLen, needleLen, needleLen, needleLen, needleLen, + needleLen, needleLen, needleLen, needleLen, needleLen, needleLen, + needleLen, needleLen, needleLen, needleLen, needleLen, needleLen, + needleLen, needleLen, needleLen, needleLen, needleLen, needleLen, + needleLen, needleLen, needleLen, needleLen, needleLen, needleLen, + needleLen, needleLen, needleLen, needleLen, needleLen, needleLen, + needleLen, needleLen, needleLen, needleLen, needleLen, needleLen, + needleLen, needleLen, needleLen, needleLen, needleLen, needleLen, + needleLen, needleLen, needleLen, needleLen, needleLen, needleLen, + needleLen, needleLen, needleLen, needleLen, needleLen, needleLen, + needleLen, needleLen, needleLen, needleLen, needleLen, needleLen, + needleLen, needleLen, needleLen, needleLen, needleLen, needleLen, + needleLen, needleLen, needleLen, needleLen, needleLen, needleLen, + needleLen, needleLen, needleLen, needleLen, needleLen, needleLen, + needleLen, needleLen, needleLen, needleLen, needleLen, needleLen, + needleLen, needleLen, needleLen, needleLen, needleLen, needleLen, + needleLen, needleLen, needleLen, needleLen, needleLen, needleLen, + needleLen, needleLen, needleLen, needleLen, needleLen, needleLen, + needleLen, needleLen, needleLen, needleLen, needleLen, needleLen, + needleLen, needleLen, needleLen, needleLen, needleLen, needleLen, + needleLen, needleLen, needleLen, needleLen, needleLen, needleLen, + needleLen, needleLen, needleLen, needleLen, needleLen, needleLen, + needleLen, needleLen, needleLen, needleLen, needleLen, needleLen, + needleLen, needleLen, needleLen, needleLen, needleLen, needleLen, + needleLen, needleLen, needleLen, needleLen, needleLen, needleLen, + needleLen, needleLen, needleLen, needleLen, needleLen, needleLen, + needleLen, needleLen, needleLen, needleLen, needleLen, needleLen, + needleLen, needleLen, needleLen, needleLen + ]; + + // Populate occurrence table with analysis of the needle, ignoring the last + // letter. + if (needleLen > 1) { + for (let i = 0; i < needleLen - 1; ++i) + this._occ[needle[i]] = needleLen - 1 - i; + } + } + + reset() { + this.matches = 0; + this._lookbehindSize = 0; + this._bufPos = 0; + } + + push(chunk, pos) { + let result; + if (!Buffer.isBuffer(chunk)) + chunk = Buffer.from(chunk, 'latin1'); + const chunkLen = chunk.length; + this._bufPos = pos || 0; + while (result !== chunkLen && this.matches < this.maxMatches) + result = feed(this, chunk); + return result; + } + + destroy() { + const lbSize = this._lookbehindSize; + if (lbSize) + this._cb(false, this._lookbehind, 0, lbSize, false); + this.reset(); + } +} + +function feed(self, data) { + const len = data.length; + const needle = self._needle; + const needleLen = needle.length; + + // Positive: points to a position in `data` + // pos == 3 points to data[3] + // Negative: points to a position in the lookbehind buffer + // pos == -2 points to lookbehind[lookbehindSize - 2] + let pos = -self._lookbehindSize; + const lastNeedleCharPos = needleLen - 1; + const lastNeedleChar = needle[lastNeedleCharPos]; + const end = len - needleLen; + const occ = self._occ; + const lookbehind = self._lookbehind; + + if (pos < 0) { + // Lookbehind buffer is not empty. Perform Boyer-Moore-Horspool + // search with character lookup code that considers both the + // lookbehind buffer and the current round's haystack data. + // + // Loop until + // there is a match. + // or until + // we've moved past the position that requires the + // lookbehind buffer. In this case we switch to the + // optimized loop. + // or until + // the character to look at lies outside the haystack. + while (pos < 0 && pos <= end) { + const nextPos = pos + lastNeedleCharPos; + const ch = (nextPos < 0 + ? lookbehind[self._lookbehindSize + nextPos] + : data[nextPos]); + + if (ch === lastNeedleChar + && matchNeedle(self, data, pos, lastNeedleCharPos)) { + self._lookbehindSize = 0; + ++self.matches; + if (pos > -self._lookbehindSize) + self._cb(true, lookbehind, 0, self._lookbehindSize + pos, false); + else + self._cb(true, undefined, 0, 0, true); + + return (self._bufPos = pos + needleLen); + } + + pos += occ[ch]; + } + + // No match. + + // There's too few data for Boyer-Moore-Horspool to run, + // so let's use a different algorithm to skip as much as + // we can. + // Forward pos until + // the trailing part of lookbehind + data + // looks like the beginning of the needle + // or until + // pos == 0 + while (pos < 0 && !matchNeedle(self, data, pos, len - pos)) + ++pos; + + if (pos < 0) { + // Cut off part of the lookbehind buffer that has + // been processed and append the entire haystack + // into it. + const bytesToCutOff = self._lookbehindSize + pos; + + if (bytesToCutOff > 0) { + // The cut off data is guaranteed not to contain the needle. + self._cb(false, lookbehind, 0, bytesToCutOff, false); + } + + self._lookbehindSize -= bytesToCutOff; + lookbehind.copy(lookbehind, 0, bytesToCutOff, self._lookbehindSize); + lookbehind.set(data, self._lookbehindSize); + self._lookbehindSize += len; + + self._bufPos = len; + return len; + } + + // Discard lookbehind buffer. + self._cb(false, lookbehind, 0, self._lookbehindSize, false); + self._lookbehindSize = 0; + } + + pos += self._bufPos; + + const firstNeedleChar = needle[0]; + + // Lookbehind buffer is now empty. Perform Boyer-Moore-Horspool + // search with optimized character lookup code that only considers + // the current round's haystack data. + while (pos <= end) { + const ch = data[pos + lastNeedleCharPos]; + + if (ch === lastNeedleChar + && data[pos] === firstNeedleChar + && memcmp(needle, 0, data, pos, lastNeedleCharPos)) { + ++self.matches; + if (pos > 0) + self._cb(true, data, self._bufPos, pos, true); + else + self._cb(true, undefined, 0, 0, true); + + return (self._bufPos = pos + needleLen); + } + + pos += occ[ch]; + } + + // There was no match. If there's trailing haystack data that we cannot + // match yet using the Boyer-Moore-Horspool algorithm (because the trailing + // data is less than the needle size) then match using a modified + // algorithm that starts matching from the beginning instead of the end. + // Whatever trailing data is left after running this algorithm is added to + // the lookbehind buffer. + while (pos < len) { + if (data[pos] !== firstNeedleChar + || !memcmp(data, pos, needle, 0, len - pos)) { + ++pos; + continue; + } + data.copy(lookbehind, 0, pos, len); + self._lookbehindSize = len - pos; + break; + } + + // Everything until `pos` is guaranteed not to contain needle data. + if (pos > 0) + self._cb(false, data, self._bufPos, pos < len ? pos : len, true); + + self._bufPos = len; + return len; +} + +function matchNeedle(self, data, pos, len) { + const lb = self._lookbehind; + const lbSize = self._lookbehindSize; + const needle = self._needle; + + for (let i = 0; i < len; ++i, ++pos) { + const ch = (pos < 0 ? lb[lbSize + pos] : data[pos]); + if (ch !== needle[i]) + return false; + } + return true; +} + +module.exports = SBMH; \ No newline at end of file From d301c12acd4f10e202a06241d997d46c55620833 Mon Sep 17 00:00:00 2001 From: advplyr Date: Wed, 6 Jul 2022 19:14:47 -0500 Subject: [PATCH 007/100] Remove dependency express-rate-limit --- package-lock.json | 5 - package.json | 1 - server/Server.js | 2 +- server/libs/expressRateLimit/LICENSE | 20 ++ server/libs/expressRateLimit/index.js | 196 +++++++++++++++++++ server/libs/expressRateLimit/memory-store.js | 47 +++++ 6 files changed, 264 insertions(+), 7 deletions(-) create mode 100644 server/libs/expressRateLimit/LICENSE create mode 100644 server/libs/expressRateLimit/index.js create mode 100644 server/libs/expressRateLimit/memory-store.js diff --git a/package-lock.json b/package-lock.json index 01052b96b..d3d3e5fc3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -433,11 +433,6 @@ "vary": "~1.1.2" } }, - "express-rate-limit": { - "version": "5.5.1", - "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-5.5.1.tgz", - "integrity": "sha512-MTjE2eIbHv5DyfuFz4zLYWxpqVhEhkTiwFGuB74Q9CSou2WHO52nlE5y3Zlg6SIsiYUIPj6ifFxnkPz6O3sIUg==" - }, "finalhandler": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", diff --git a/package.json b/package.json index 61d31ef56..4f72599f5 100644 --- a/package.json +++ b/package.json @@ -34,7 +34,6 @@ "axios": "^0.26.1", "date-and-time": "^2.3.1", "express": "^4.17.1", - "express-rate-limit": "^5.3.0", "htmlparser2": "^8.0.1", "socket.io": "^4.4.1", "xml2js": "^0.4.23" diff --git a/server/Server.js b/server/Server.js index f43d46c72..c2895de96 100644 --- a/server/Server.js +++ b/server/Server.js @@ -4,7 +4,7 @@ const http = require('http') const SocketIO = require('socket.io') const fs = require('./libs/fsExtra') const fileUpload = require('./libs/expressFileupload') -const rateLimit = require('express-rate-limit') +const rateLimit = require('./libs/expressRateLimit') const { version } = require('../package.json') diff --git a/server/libs/expressRateLimit/LICENSE b/server/libs/expressRateLimit/LICENSE new file mode 100644 index 000000000..f4bb9cc36 --- /dev/null +++ b/server/libs/expressRateLimit/LICENSE @@ -0,0 +1,20 @@ +# MIT License + +Copyright 2021 Nathan Friedly + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/server/libs/expressRateLimit/index.js b/server/libs/expressRateLimit/index.js new file mode 100644 index 000000000..6df27ff5e --- /dev/null +++ b/server/libs/expressRateLimit/index.js @@ -0,0 +1,196 @@ +"use strict"; + +// +// modified for use in audiobookshelf +// Source: https://github.com/nfriedly/express-rate-limit +// + +const MemoryStore = require("./memory-store"); + +function RateLimit(options) { + options = Object.assign( + { + windowMs: 60 * 1000, // milliseconds - how long to keep records of requests in memory + max: 5, // max number of recent connections during `window` milliseconds before sending a 429 response + message: "Too many requests, please try again later.", + statusCode: 429, // 429 status = Too Many Requests (RFC 6585) + headers: true, //Send custom rate limit header with limit and remaining + draft_polli_ratelimit_headers: false, //Support for the new RateLimit standardization headers + // ability to manually decide if request was successful. Used when `skipSuccessfulRequests` and/or `skipFailedRequests` are set to `true` + requestWasSuccessful: function (req, res) { + return res.statusCode < 400; + }, + skipFailedRequests: false, // Do not count failed requests + skipSuccessfulRequests: false, // Do not count successful requests + // allows to create custom keys (by default user IP is used) + keyGenerator: function (req /*, res*/) { + if (!req.ip) { + console.error( + "express-rate-limit: req.ip is undefined - you can avoid this by providing a custom keyGenerator function, but it may be indicative of a larger issue." + ); + } + return req.ip; + }, + skip: function (/*req, res*/) { + return false; + }, + handler: function (req, res /*, next, optionsUsed*/) { + res.status(options.statusCode).send(options.message); + }, + onLimitReached: function (/*req, res, optionsUsed*/) { }, + requestPropertyName: "rateLimit", // Parameter name appended to req object + }, + options + ); + + // store to use for persisting rate limit data + options.store = options.store || new MemoryStore(options.windowMs); + + // ensure that the store has the incr method + if ( + typeof options.store.incr !== "function" || + typeof options.store.resetKey !== "function" || + (options.skipFailedRequests && + typeof options.store.decrement !== "function") + ) { + throw new Error("The store is not valid."); + } + + ["global", "delayMs", "delayAfter"].forEach((key) => { + // note: this doesn't trigger if delayMs or delayAfter are set to 0, because that essentially disables them + if (options[key]) { + throw new Error( + `The ${key} option was removed from express-rate-limit v3.` + ); + } + }); + + function rateLimit(req, res, next) { + Promise.resolve(options.skip(req, res)) + .then((skip) => { + if (skip) { + return next(); + } + + const key = options.keyGenerator(req, res); + + options.store.incr(key, function (err, current, resetTime) { + if (err) { + return next(err); + } + + const maxResult = + typeof options.max === "function" + ? options.max(req, res) + : options.max; + + Promise.resolve(maxResult) + .then((max) => { + req[options.requestPropertyName] = { + limit: max, + current: current, + remaining: Math.max(max - current, 0), + resetTime: resetTime, + }; + + if (options.headers && !res.headersSent) { + res.setHeader("X-RateLimit-Limit", max); + res.setHeader( + "X-RateLimit-Remaining", + req[options.requestPropertyName].remaining + ); + if (resetTime instanceof Date) { + // if we have a resetTime, also provide the current date to help avoid issues with incorrect clocks + res.setHeader("Date", new Date().toUTCString()); + res.setHeader( + "X-RateLimit-Reset", + Math.ceil(resetTime.getTime() / 1000) + ); + } + } + if (options.draft_polli_ratelimit_headers && !res.headersSent) { + res.setHeader("RateLimit-Limit", max); + res.setHeader( + "RateLimit-Remaining", + req[options.requestPropertyName].remaining + ); + if (resetTime) { + const deltaSeconds = Math.ceil( + (resetTime.getTime() - Date.now()) / 1000 + ); + res.setHeader("RateLimit-Reset", Math.max(0, deltaSeconds)); + } + } + + if ( + options.skipFailedRequests || + options.skipSuccessfulRequests + ) { + let decremented = false; + const decrementKey = () => { + if (!decremented) { + options.store.decrement(key); + decremented = true; + } + }; + + if (options.skipFailedRequests) { + res.on("finish", function () { + if (!options.requestWasSuccessful(req, res)) { + decrementKey(); + } + }); + + res.on("close", () => { + if (!res.finished) { + decrementKey(); + } + }); + + res.on("error", () => decrementKey()); + } + + if (options.skipSuccessfulRequests) { + res.on("finish", function () { + if (options.requestWasSuccessful(req, res)) { + options.store.decrement(key); + } + }); + } + } + + if (max && current === max + 1) { + options.onLimitReached(req, res, options); + } + + if (max && current > max) { + if (options.headers && !res.headersSent) { + res.setHeader( + "Retry-After", + Math.ceil(options.windowMs / 1000) + ); + } + return options.handler(req, res, next, options); + } + + next(); + + return null; + }) + .catch(next); + }); + + return null; + }) + .catch(next); + } + + rateLimit.resetKey = options.store.resetKey.bind(options.store); + + // Backward compatibility function + rateLimit.resetIp = rateLimit.resetKey; + + return rateLimit; +} + +module.exports = RateLimit; diff --git a/server/libs/expressRateLimit/memory-store.js b/server/libs/expressRateLimit/memory-store.js new file mode 100644 index 000000000..60938dbcd --- /dev/null +++ b/server/libs/expressRateLimit/memory-store.js @@ -0,0 +1,47 @@ +"use strict"; + +function calculateNextResetTime(windowMs) { + const d = new Date(); + d.setMilliseconds(d.getMilliseconds() + windowMs); + return d; +} + +function MemoryStore(windowMs) { + let hits = {}; + let resetTime = calculateNextResetTime(windowMs); + + this.incr = function (key, cb) { + if (hits[key]) { + hits[key]++; + } else { + hits[key] = 1; + } + + cb(null, hits[key], resetTime); + }; + + this.decrement = function (key) { + if (hits[key]) { + hits[key]--; + } + }; + + // export an API to allow hits all IPs to be reset + this.resetAll = function () { + hits = {}; + resetTime = calculateNextResetTime(windowMs); + }; + + // export an API to allow hits from one IP to be reset + this.resetKey = function (key) { + delete hits[key]; + }; + + // simply reset ALL hits every windowMs + const interval = setInterval(this.resetAll, windowMs); + if (interval.unref) { + interval.unref(); + } +} + +module.exports = MemoryStore; From 415e0a7b5a91503a54c79909c361eddf370afeb6 Mon Sep 17 00:00:00 2001 From: advplyr Date: Wed, 6 Jul 2022 19:18:27 -0500 Subject: [PATCH 008/100] Remove dependency date-and-time --- package-lock.json | 5 ----- package.json | 1 - server/Logger.js | 2 +- server/libs/dateAndTime/LICENSE | 21 +++++++++++++++++++++ server/libs/dateAndTime/index.js | 17 +++++++++++++++++ server/managers/PlaybackSessionManager.js | 2 +- server/objects/Backup.js | 2 +- server/objects/DailyLog.js | 2 +- server/objects/FeedEpisode.js | 2 +- server/objects/PlaybackSession.js | 2 +- server/routers/ApiRouter.js | 2 +- server/scanner/LibraryScan.js | 2 +- 12 files changed, 46 insertions(+), 14 deletions(-) create mode 100644 server/libs/dateAndTime/LICENSE create mode 100644 server/libs/dateAndTime/index.js diff --git a/package-lock.json b/package-lock.json index d3d3e5fc3..91043d26c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -264,11 +264,6 @@ "readable-stream": "^3.4.0" } }, - "date-and-time": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/date-and-time/-/date-and-time-2.3.1.tgz", - "integrity": "sha512-OaIRmSJXifwEN21rMVVDs0Kz8uhJ3wWPYd86atkRiqN54liaMQYEbbrgjZQea75YXOBWL4ZFb3rG/waenw1TEg==" - }, "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", diff --git a/package.json b/package.json index 4f72599f5..9fdcbb999 100644 --- a/package.json +++ b/package.json @@ -32,7 +32,6 @@ "dependencies": { "archiver": "^5.3.0", "axios": "^0.26.1", - "date-and-time": "^2.3.1", "express": "^4.17.1", "htmlparser2": "^8.0.1", "socket.io": "^4.4.1", diff --git a/server/Logger.js b/server/Logger.js index 376e08c8d..2bdce9ac4 100644 --- a/server/Logger.js +++ b/server/Logger.js @@ -1,4 +1,4 @@ -const date = require('date-and-time') +const date = require('./libs/dateAndTime') const { LogLevel } = require('./utils/constants') class Logger { diff --git a/server/libs/dateAndTime/LICENSE b/server/libs/dateAndTime/LICENSE new file mode 100644 index 000000000..08dc7cf26 --- /dev/null +++ b/server/libs/dateAndTime/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2015 KNOWLEDGECODE + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/server/libs/dateAndTime/index.js b/server/libs/dateAndTime/index.js new file mode 100644 index 000000000..32249afb2 --- /dev/null +++ b/server/libs/dateAndTime/index.js @@ -0,0 +1,17 @@ +/* + date-and-time (c) KNOWLEDGECODE | MIT +*/ +'use strict';(function(p,m){"object"===typeof exports&&"undefined"!==typeof module?module.exports=m():"function"===typeof define&&define.amd?define(m):(p="undefined"!==typeof globalThis?globalThis:p||self,p.date=m())})(this,function(){var p={},m={},r="en",t={MMMM:"January February March April May June July August September October November December".split(" "),MMM:"Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec".split(" "),dddd:"Sunday Monday Tuesday Wednesday Thursday Friday Saturday".split(" "), +ddd:"Sun Mon Tue Wed Thu Fri Sat".split(" "),dd:"Su Mo Tu We Th Fr Sa".split(" "),A:["AM","PM"]},w={YYYY:function(a){return("000"+a.getFullYear()).slice(-4)},YY:function(a){return("0"+a.getFullYear()).slice(-2)},Y:function(a){return""+a.getFullYear()},MMMM:function(a){return this.res.MMMM[a.getMonth()]},MMM:function(a){return this.res.MMM[a.getMonth()]},MM:function(a){return("0"+(a.getMonth()+1)).slice(-2)},M:function(a){return""+(a.getMonth()+1)},DD:function(a){return("0"+a.getDate()).slice(-2)}, +D:function(a){return""+a.getDate()},HH:function(a){return("0"+a.getHours()).slice(-2)},H:function(a){return""+a.getHours()},A:function(a){return this.res.A[11c&&(d=h,c=l.length);return{value:d,length:c}},pre:function(a){return a},res:t},n=function(a,b,d,c){var h={},g;for(g in a)h[g]= +a[g];for(g in b||{})!!d^!!h[g]||(h[g]=b[g]);c&&(h.res=c);return h},f={_formatter:w,_parser:x};f.compile=function(a){for(var b=/\[([^\[\]]|\[[^\[\]]*])*]|([A-Za-z])\2+|\.{3}|./g,d,c=[a];d=b.exec(a);)c[c.length]=d[0];return c};f.format=function(a,b,d){var c=this||e;b="string"===typeof b?c.compile(b):b;var h=a.getTimezoneOffset();a=c.addMinutes(a,d?h:0);c=c._formatter;var g="";a.getTimezoneOffset=function(){return d?0:h};for(var l=1,u=b.length,k;la.Y?22801:1,d||~c._parser.find(b,"ZZ").value?new Date(Date.UTC(a.Y,a.M,a.D,a.H,a.m+a.Z,a.s,a.S)):new Date(a.Y,a.M,a.D,a.H,a.m,a.s,a.S)):new Date(NaN)};f.isValid=function(a,b){var d=this||e;a="string"===typeof a?d.preparse(a,b):a;d=[31,28+d.isLeapYear(a.Y)|0,31,30,31,30,31,31,30,31,30,31][a.M-1];return!(1>a._index||1> +a._length||a._index-a._length||1>a._match||1>a.Y||9999a.M||12a.D||a.D>d||0>a.H||23a.m||59a.s||59a.S||999a.Z||720 Date: Wed, 6 Jul 2022 20:12:14 -0500 Subject: [PATCH 009/100] Remove archiver dependency --- package-lock.json | 221 +--- package.json | 2 +- server/libs/archiver/LICENSE | 22 + server/libs/archiver/buffer-crc32/LICENSE | 19 + server/libs/archiver/buffer-crc32/index.js | 122 +++ server/libs/archiver/compress-commons/LICENSE | 22 + .../archivers/archive-entry.js | 16 + .../archivers/archive-output-stream.js | 117 +++ .../archivers/zip/constants.js | 71 ++ .../archivers/zip/general-purpose-bit.js | 101 ++ .../archivers/zip/unix-stat.js | 53 + .../compress-commons/archivers/zip/util.js | 74 ++ .../archivers/zip/zip-archive-entry.js | 413 ++++++++ .../zip/zip-archive-output-stream.js | 437 ++++++++ .../libs/archiver/compress-commons/index.js | 13 + .../archiver/compress-commons/util/index.js | 30 + server/libs/archiver/crc32-stream/LICENSE | 22 + .../archiver/crc32-stream/crc32-stream.js | 48 + .../crc32-stream/deflate-crc32-stream.js | 62 ++ server/libs/archiver/crc32-stream/index.js | 14 + server/libs/archiver/crc32/LICENSE | 201 ++++ server/libs/archiver/crc32/index.js | 115 +++ server/libs/archiver/index.js | 83 ++ server/libs/archiver/lib/core.js | 974 ++++++++++++++++++ server/libs/archiver/lib/error.js | 40 + server/libs/archiver/lib/plugins/json.js | 110 ++ server/libs/archiver/lib/plugins/zip.js | 120 +++ server/libs/archiver/normalize-path/LICENSE | 21 + server/libs/archiver/normalize-path/index.js | 35 + server/libs/archiver/readdir-glob/LICENSE | 201 ++++ server/libs/archiver/readdir-glob/index.js | 248 +++++ server/libs/archiver/zip-stream/LICENSE | 22 + server/libs/archiver/zip-stream/index.js | 187 ++++ server/managers/BackupManager.js | 2 +- server/managers/DownloadManager.js | 2 +- 35 files changed, 4046 insertions(+), 194 deletions(-) create mode 100644 server/libs/archiver/LICENSE create mode 100644 server/libs/archiver/buffer-crc32/LICENSE create mode 100644 server/libs/archiver/buffer-crc32/index.js create mode 100644 server/libs/archiver/compress-commons/LICENSE create mode 100644 server/libs/archiver/compress-commons/archivers/archive-entry.js create mode 100644 server/libs/archiver/compress-commons/archivers/archive-output-stream.js create mode 100644 server/libs/archiver/compress-commons/archivers/zip/constants.js create mode 100644 server/libs/archiver/compress-commons/archivers/zip/general-purpose-bit.js create mode 100644 server/libs/archiver/compress-commons/archivers/zip/unix-stat.js create mode 100644 server/libs/archiver/compress-commons/archivers/zip/util.js create mode 100644 server/libs/archiver/compress-commons/archivers/zip/zip-archive-entry.js create mode 100644 server/libs/archiver/compress-commons/archivers/zip/zip-archive-output-stream.js create mode 100644 server/libs/archiver/compress-commons/index.js create mode 100644 server/libs/archiver/compress-commons/util/index.js create mode 100644 server/libs/archiver/crc32-stream/LICENSE create mode 100644 server/libs/archiver/crc32-stream/crc32-stream.js create mode 100644 server/libs/archiver/crc32-stream/deflate-crc32-stream.js create mode 100644 server/libs/archiver/crc32-stream/index.js create mode 100644 server/libs/archiver/crc32/LICENSE create mode 100644 server/libs/archiver/crc32/index.js create mode 100644 server/libs/archiver/index.js create mode 100644 server/libs/archiver/lib/core.js create mode 100644 server/libs/archiver/lib/error.js create mode 100644 server/libs/archiver/lib/plugins/json.js create mode 100644 server/libs/archiver/lib/plugins/zip.js create mode 100644 server/libs/archiver/normalize-path/LICENSE create mode 100644 server/libs/archiver/normalize-path/index.js create mode 100644 server/libs/archiver/readdir-glob/LICENSE create mode 100644 server/libs/archiver/readdir-glob/index.js create mode 100644 server/libs/archiver/zip-stream/LICENSE create mode 100644 server/libs/archiver/zip-stream/index.js diff --git a/package-lock.json b/package-lock.json index 91043d26c..b07681898 100644 --- a/package-lock.json +++ b/package-lock.json @@ -33,20 +33,6 @@ "negotiator": "0.6.3" } }, - "archiver": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/archiver/-/archiver-5.3.1.tgz", - "integrity": "sha512-8KyabkmbYrH+9ibcTScQ1xCJC/CGcugdVIwB+53f5sZziXgwUh3iXlAlANMxcZyDEfTHMe6+Z5FofV8nopXP7w==", - "requires": { - "archiver-utils": "^2.1.0", - "async": "^3.2.3", - "buffer-crc32": "^0.2.1", - "readable-stream": "^3.6.0", - "readdir-glob": "^1.0.0", - "tar-stream": "^2.2.0", - "zip-stream": "^4.1.0" - } - }, "archiver-utils": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-2.1.0.tgz", @@ -62,35 +48,6 @@ "lodash.union": "^4.6.0", "normalize-path": "^3.0.0", "readable-stream": "^2.0.0" - }, - "dependencies": { - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - } - } } }, "array-flatten": { @@ -98,11 +55,6 @@ "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" }, - "async": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", - "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==" - }, "axios": { "version": "0.26.1", "resolved": "https://registry.npmjs.org/axios/-/axios-0.26.1.tgz", @@ -116,26 +68,11 @@ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, - "base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" - }, "base64id": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz", "integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==" }, - "bl": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", - "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", - "requires": { - "buffer": "^5.5.0", - "inherits": "^2.0.4", - "readable-stream": "^3.4.0" - } - }, "body-parser": { "version": "1.20.0", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.0.tgz", @@ -164,20 +101,6 @@ "concat-map": "0.0.1" } }, - "buffer": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", - "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", - "requires": { - "base64-js": "^1.3.1", - "ieee754": "^1.1.13" - } - }, - "buffer-crc32": { - "version": "0.2.13", - "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", - "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==" - }, "bytes": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", @@ -197,17 +120,6 @@ "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==" }, - "compress-commons": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-4.1.1.tgz", - "integrity": "sha512-QLdDLCKNV2dtoTorqgxngQCMA+gWXkM/Nwu7FpeBhk/RdkzimqC3jueb/FDmaZeXh+uby1jkBqE3xArsLBE5wQ==", - "requires": { - "buffer-crc32": "^0.2.13", - "crc32-stream": "^4.0.2", - "normalize-path": "^3.0.0", - "readable-stream": "^3.6.0" - } - }, "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -250,20 +162,6 @@ "vary": "^1" } }, - "crc-32": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz", - "integrity": "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==" - }, - "crc32-stream": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-4.0.2.tgz", - "integrity": "sha512-DxFZ/Hk473b/muq1VJ///PMNLj0ZMnzye9thBpmjpJKCc5eMgB95aK8zCGrGfQ90cWo561Te6HK9D+j4KPdM6w==", - "requires": { - "crc-32": "^1.2.0", - "readable-stream": "^3.4.0" - } - }, "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", @@ -325,14 +223,6 @@ "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==" }, - "end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "requires": { - "once": "^1.4.0" - } - }, "engine.io": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.2.0.tgz", @@ -457,11 +347,6 @@ "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==" }, - "fs-constants": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", - "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" - }, "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -544,11 +429,6 @@ "safer-buffer": ">= 2.1.2 < 3" } }, - "ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==" - }, "inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", @@ -579,35 +459,6 @@ "integrity": "sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw==", "requires": { "readable-stream": "^2.0.5" - }, - "dependencies": { - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - } - } } }, "lodash.defaults": { @@ -771,21 +622,24 @@ } }, "readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - }, - "readdir-glob": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/readdir-glob/-/readdir-glob-1.1.1.tgz", - "integrity": "sha512-91/k1EzZwDx6HbERR+zucygRFfiPl2zkIYZtv3Jjr6Mn7SkKcVct8aVO+sSRiGMc6fLf72du3d92/uY63YPdEA==", - "requires": { - "minimatch": "^3.0.4" + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + }, + "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==" + } } }, "safe-buffer": { @@ -920,23 +774,18 @@ "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==" }, "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==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "requires": { - "safe-buffer": "~5.2.0" - } - }, - "tar-stream": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", - "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", - "requires": { - "bl": "^4.0.3", - "end-of-stream": "^1.4.1", - "fs-constants": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^3.1.1" + "safe-buffer": "~5.1.0" + }, + "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==" + } } }, "toidentifier": { @@ -961,7 +810,7 @@ "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" }, "utils-merge": { "version": "1.0.1", @@ -976,7 +825,7 @@ "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" }, "ws": { "version": "8.2.3", @@ -996,16 +845,6 @@ "version": "11.0.1", "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==" - }, - "zip-stream": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-4.1.0.tgz", - "integrity": "sha512-zshzwQW7gG7hjpBlgeQP9RuyPGNxvJdzR8SUM3QhxCnLjWN2E7j3dOvpeDcQoETfHx0urRS7EtmVToql7YpU4A==", - "requires": { - "archiver-utils": "^2.1.0", - "compress-commons": "^4.1.0", - "readable-stream": "^3.6.0" - } } } } diff --git a/package.json b/package.json index 9fdcbb999..6ab44fd8a 100644 --- a/package.json +++ b/package.json @@ -30,7 +30,7 @@ "author": "advplyr", "license": "GPL-3.0", "dependencies": { - "archiver": "^5.3.0", + "archiver-utils": "^2.1.0", "axios": "^0.26.1", "express": "^4.17.1", "htmlparser2": "^8.0.1", diff --git a/server/libs/archiver/LICENSE b/server/libs/archiver/LICENSE new file mode 100644 index 000000000..88caf8710 --- /dev/null +++ b/server/libs/archiver/LICENSE @@ -0,0 +1,22 @@ +Copyright (c) 2012-2014 Chris Talkington, contributors. + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/server/libs/archiver/buffer-crc32/LICENSE b/server/libs/archiver/buffer-crc32/LICENSE new file mode 100644 index 000000000..0fec45a0e --- /dev/null +++ b/server/libs/archiver/buffer-crc32/LICENSE @@ -0,0 +1,19 @@ +The MIT License + +Copyright (c) 2013 Brian J. Brennan + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the +Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/server/libs/archiver/buffer-crc32/index.js b/server/libs/archiver/buffer-crc32/index.js new file mode 100644 index 000000000..945d007c6 --- /dev/null +++ b/server/libs/archiver/buffer-crc32/index.js @@ -0,0 +1,122 @@ +// +// used in archiver +// Source: https://github.com/brianloveswords/buffer-crc32 +// + +var Buffer = require('buffer').Buffer; + +var CRC_TABLE = [ + 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, + 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, + 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, + 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, + 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856, + 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, + 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, + 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, + 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, + 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a, + 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, + 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, + 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, + 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, + 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e, + 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, + 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, + 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, + 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, + 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, + 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, + 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, + 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010, + 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, + 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, + 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, + 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, + 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, + 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344, + 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, + 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, + 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, + 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, + 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c, + 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, + 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, + 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, + 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, + 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c, + 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, + 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, + 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, + 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, + 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, + 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278, + 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, + 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66, + 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, + 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, + 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, + 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, + 0x2d02ef8d +]; + +if (typeof Int32Array !== 'undefined') { + CRC_TABLE = new Int32Array(CRC_TABLE); +} + +function newEmptyBuffer(length) { + var buffer = new Buffer(length); + buffer.fill(0x00); + return buffer; +} + +function ensureBuffer(input) { + if (Buffer.isBuffer(input)) { + return input; + } + + var hasNewBufferAPI = + typeof Buffer.alloc === "function" && + typeof Buffer.from === "function"; + + if (typeof input === "number") { + return hasNewBufferAPI ? Buffer.alloc(input) : newEmptyBuffer(input); + } + else if (typeof input === "string") { + return hasNewBufferAPI ? Buffer.from(input) : new Buffer(input); + } + else { + throw new Error("input must be buffer, number, or string, received " + + typeof input); + } +} + +function bufferizeInt(num) { + var tmp = ensureBuffer(4); + tmp.writeInt32BE(num, 0); + return tmp; +} + +function _crc32(buf, previous) { + buf = ensureBuffer(buf); + if (Buffer.isBuffer(previous)) { + previous = previous.readUInt32BE(0); + } + var crc = ~~previous ^ -1; + for (var n = 0; n < buf.length; n++) { + crc = CRC_TABLE[(crc ^ buf[n]) & 0xff] ^ (crc >>> 8); + } + return (crc ^ -1); +} + +function crc32() { + return bufferizeInt(_crc32.apply(null, arguments)); +} +crc32.signed = function () { + return _crc32.apply(null, arguments); +}; +crc32.unsigned = function () { + return _crc32.apply(null, arguments) >>> 0; +}; + +module.exports = crc32; \ No newline at end of file diff --git a/server/libs/archiver/compress-commons/LICENSE b/server/libs/archiver/compress-commons/LICENSE new file mode 100644 index 000000000..56420a6a0 --- /dev/null +++ b/server/libs/archiver/compress-commons/LICENSE @@ -0,0 +1,22 @@ +Copyright (c) 2014 Chris Talkington, contributors. + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/server/libs/archiver/compress-commons/archivers/archive-entry.js b/server/libs/archiver/compress-commons/archivers/archive-entry.js new file mode 100644 index 000000000..86bc59886 --- /dev/null +++ b/server/libs/archiver/compress-commons/archivers/archive-entry.js @@ -0,0 +1,16 @@ +/** + * node-compress-commons + * + * Copyright (c) 2014 Chris Talkington, contributors. + * Licensed under the MIT license. + * https://github.com/archiverjs/node-compress-commons/blob/master/LICENSE-MIT + */ +var ArchiveEntry = module.exports = function() {}; + +ArchiveEntry.prototype.getName = function() {}; + +ArchiveEntry.prototype.getSize = function() {}; + +ArchiveEntry.prototype.getLastModifiedDate = function() {}; + +ArchiveEntry.prototype.isDirectory = function() {}; \ No newline at end of file diff --git a/server/libs/archiver/compress-commons/archivers/archive-output-stream.js b/server/libs/archiver/compress-commons/archivers/archive-output-stream.js new file mode 100644 index 000000000..b5fa4939c --- /dev/null +++ b/server/libs/archiver/compress-commons/archivers/archive-output-stream.js @@ -0,0 +1,117 @@ +/** + * node-compress-commons + * + * Copyright (c) 2014 Chris Talkington, contributors. + * Licensed under the MIT license. + * https://github.com/archiverjs/node-compress-commons/blob/master/LICENSE-MIT + */ +var inherits = require('util').inherits; +var Transform = require('readable-stream').Transform; + +var ArchiveEntry = require('./archive-entry'); +var util = require('../util'); + +var ArchiveOutputStream = module.exports = function(options) { + if (!(this instanceof ArchiveOutputStream)) { + return new ArchiveOutputStream(options); + } + + Transform.call(this, options); + + this.offset = 0; + this._archive = { + finish: false, + finished: false, + processing: false + }; +}; + +inherits(ArchiveOutputStream, Transform); + +ArchiveOutputStream.prototype._appendBuffer = function(zae, source, callback) { + // scaffold only +}; + +ArchiveOutputStream.prototype._appendStream = function(zae, source, callback) { + // scaffold only +}; + +ArchiveOutputStream.prototype._emitErrorCallback = function(err) { + if (err) { + this.emit('error', err); + } +}; + +ArchiveOutputStream.prototype._finish = function(ae) { + // scaffold only +}; + +ArchiveOutputStream.prototype._normalizeEntry = function(ae) { + // scaffold only +}; + +ArchiveOutputStream.prototype._transform = function(chunk, encoding, callback) { + callback(null, chunk); +}; + +ArchiveOutputStream.prototype.entry = function(ae, source, callback) { + source = source || null; + + if (typeof callback !== 'function') { + callback = this._emitErrorCallback.bind(this); + } + + if (!(ae instanceof ArchiveEntry)) { + callback(new Error('not a valid instance of ArchiveEntry')); + return; + } + + if (this._archive.finish || this._archive.finished) { + callback(new Error('unacceptable entry after finish')); + return; + } + + if (this._archive.processing) { + callback(new Error('already processing an entry')); + return; + } + + this._archive.processing = true; + this._normalizeEntry(ae); + this._entry = ae; + + source = util.normalizeInputSource(source); + + if (Buffer.isBuffer(source)) { + this._appendBuffer(ae, source, callback); + } else if (util.isStream(source)) { + this._appendStream(ae, source, callback); + } else { + this._archive.processing = false; + callback(new Error('input source must be valid Stream or Buffer instance')); + return; + } + + return this; +}; + +ArchiveOutputStream.prototype.finish = function() { + if (this._archive.processing) { + this._archive.finish = true; + return; + } + + this._finish(); +}; + +ArchiveOutputStream.prototype.getBytesWritten = function() { + return this.offset; +}; + +ArchiveOutputStream.prototype.write = function(chunk, cb) { + if (chunk) { + this.offset += chunk.length; + } + + return Transform.prototype.write.call(this, chunk, cb); +}; \ No newline at end of file diff --git a/server/libs/archiver/compress-commons/archivers/zip/constants.js b/server/libs/archiver/compress-commons/archivers/zip/constants.js new file mode 100644 index 000000000..c30b3250b --- /dev/null +++ b/server/libs/archiver/compress-commons/archivers/zip/constants.js @@ -0,0 +1,71 @@ +/** + * node-compress-commons + * + * Copyright (c) 2014 Chris Talkington, contributors. + * Licensed under the MIT license. + * https://github.com/archiverjs/node-compress-commons/blob/master/LICENSE-MIT + */ +module.exports = { + WORD: 4, + DWORD: 8, + EMPTY: Buffer.alloc(0), + + SHORT: 2, + SHORT_MASK: 0xffff, + SHORT_SHIFT: 16, + SHORT_ZERO: Buffer.from(Array(2)), + LONG: 4, + LONG_ZERO: Buffer.from(Array(4)), + + MIN_VERSION_INITIAL: 10, + MIN_VERSION_DATA_DESCRIPTOR: 20, + MIN_VERSION_ZIP64: 45, + VERSION_MADEBY: 45, + + METHOD_STORED: 0, + METHOD_DEFLATED: 8, + + PLATFORM_UNIX: 3, + PLATFORM_FAT: 0, + + SIG_LFH: 0x04034b50, + SIG_DD: 0x08074b50, + SIG_CFH: 0x02014b50, + SIG_EOCD: 0x06054b50, + SIG_ZIP64_EOCD: 0x06064B50, + SIG_ZIP64_EOCD_LOC: 0x07064B50, + + ZIP64_MAGIC_SHORT: 0xffff, + ZIP64_MAGIC: 0xffffffff, + ZIP64_EXTRA_ID: 0x0001, + + ZLIB_NO_COMPRESSION: 0, + ZLIB_BEST_SPEED: 1, + ZLIB_BEST_COMPRESSION: 9, + ZLIB_DEFAULT_COMPRESSION: -1, + + MODE_MASK: 0xFFF, + DEFAULT_FILE_MODE: 33188, // 010644 = -rw-r--r-- = S_IFREG | S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH + DEFAULT_DIR_MODE: 16877, // 040755 = drwxr-xr-x = S_IFDIR | S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH + + EXT_FILE_ATTR_DIR: 1106051088, // 010173200020 = drwxr-xr-x = (((S_IFDIR | 0755) << 16) | S_DOS_D) + EXT_FILE_ATTR_FILE: 2175008800, // 020151000040 = -rw-r--r-- = (((S_IFREG | 0644) << 16) | S_DOS_A) >>> 0 + + // Unix file types + S_IFMT: 61440, // 0170000 type of file mask + S_IFIFO: 4096, // 010000 named pipe (fifo) + S_IFCHR: 8192, // 020000 character special + S_IFDIR: 16384, // 040000 directory + S_IFBLK: 24576, // 060000 block special + S_IFREG: 32768, // 0100000 regular + S_IFLNK: 40960, // 0120000 symbolic link + S_IFSOCK: 49152, // 0140000 socket + + // DOS file type flags + S_DOS_A: 32, // 040 Archive + S_DOS_D: 16, // 020 Directory + S_DOS_V: 8, // 010 Volume + S_DOS_S: 4, // 04 System + S_DOS_H: 2, // 02 Hidden + S_DOS_R: 1 // 01 Read Only +}; diff --git a/server/libs/archiver/compress-commons/archivers/zip/general-purpose-bit.js b/server/libs/archiver/compress-commons/archivers/zip/general-purpose-bit.js new file mode 100644 index 000000000..62703996a --- /dev/null +++ b/server/libs/archiver/compress-commons/archivers/zip/general-purpose-bit.js @@ -0,0 +1,101 @@ +/** + * node-compress-commons + * + * Copyright (c) 2014 Chris Talkington, contributors. + * Licensed under the MIT license. + * https://github.com/archiverjs/node-compress-commons/blob/master/LICENSE-MIT + */ +var zipUtil = require('./util'); + +var DATA_DESCRIPTOR_FLAG = 1 << 3; +var ENCRYPTION_FLAG = 1 << 0; +var NUMBER_OF_SHANNON_FANO_TREES_FLAG = 1 << 2; +var SLIDING_DICTIONARY_SIZE_FLAG = 1 << 1; +var STRONG_ENCRYPTION_FLAG = 1 << 6; +var UFT8_NAMES_FLAG = 1 << 11; + +var GeneralPurposeBit = module.exports = function() { + if (!(this instanceof GeneralPurposeBit)) { + return new GeneralPurposeBit(); + } + + this.descriptor = false; + this.encryption = false; + this.utf8 = false; + this.numberOfShannonFanoTrees = 0; + this.strongEncryption = false; + this.slidingDictionarySize = 0; + + return this; +}; + +GeneralPurposeBit.prototype.encode = function() { + return zipUtil.getShortBytes( + (this.descriptor ? DATA_DESCRIPTOR_FLAG : 0) | + (this.utf8 ? UFT8_NAMES_FLAG : 0) | + (this.encryption ? ENCRYPTION_FLAG : 0) | + (this.strongEncryption ? STRONG_ENCRYPTION_FLAG : 0) + ); +}; + +GeneralPurposeBit.prototype.parse = function(buf, offset) { + var flag = zipUtil.getShortBytesValue(buf, offset); + var gbp = new GeneralPurposeBit(); + + gbp.useDataDescriptor((flag & DATA_DESCRIPTOR_FLAG) !== 0); + gbp.useUTF8ForNames((flag & UFT8_NAMES_FLAG) !== 0); + gbp.useStrongEncryption((flag & STRONG_ENCRYPTION_FLAG) !== 0); + gbp.useEncryption((flag & ENCRYPTION_FLAG) !== 0); + gbp.setSlidingDictionarySize((flag & SLIDING_DICTIONARY_SIZE_FLAG) !== 0 ? 8192 : 4096); + gbp.setNumberOfShannonFanoTrees((flag & NUMBER_OF_SHANNON_FANO_TREES_FLAG) !== 0 ? 3 : 2); + + return gbp; +}; + +GeneralPurposeBit.prototype.setNumberOfShannonFanoTrees = function(n) { + this.numberOfShannonFanoTrees = n; +}; + +GeneralPurposeBit.prototype.getNumberOfShannonFanoTrees = function() { + return this.numberOfShannonFanoTrees; +}; + +GeneralPurposeBit.prototype.setSlidingDictionarySize = function(n) { + this.slidingDictionarySize = n; +}; + +GeneralPurposeBit.prototype.getSlidingDictionarySize = function() { + return this.slidingDictionarySize; +}; + +GeneralPurposeBit.prototype.useDataDescriptor = function(b) { + this.descriptor = b; +}; + +GeneralPurposeBit.prototype.usesDataDescriptor = function() { + return this.descriptor; +}; + +GeneralPurposeBit.prototype.useEncryption = function(b) { + this.encryption = b; +}; + +GeneralPurposeBit.prototype.usesEncryption = function() { + return this.encryption; +}; + +GeneralPurposeBit.prototype.useStrongEncryption = function(b) { + this.strongEncryption = b; +}; + +GeneralPurposeBit.prototype.usesStrongEncryption = function() { + return this.strongEncryption; +}; + +GeneralPurposeBit.prototype.useUTF8ForNames = function(b) { + this.utf8 = b; +}; + +GeneralPurposeBit.prototype.usesUTF8ForNames = function() { + return this.utf8; +}; \ No newline at end of file diff --git a/server/libs/archiver/compress-commons/archivers/zip/unix-stat.js b/server/libs/archiver/compress-commons/archivers/zip/unix-stat.js new file mode 100644 index 000000000..1326cd1d8 --- /dev/null +++ b/server/libs/archiver/compress-commons/archivers/zip/unix-stat.js @@ -0,0 +1,53 @@ +/** + * node-compress-commons + * + * Copyright (c) 2014 Chris Talkington, contributors. + * Licensed under the MIT license. + * https://github.com/archiverjs/node-compress-commons/blob/master/LICENSE-MIT + */ +module.exports = { + /** + * Bits used for permissions (and sticky bit) + */ + PERM_MASK: 4095, // 07777 + + /** + * Bits used to indicate the filesystem object type. + */ + FILE_TYPE_FLAG: 61440, // 0170000 + + /** + * Indicates symbolic links. + */ + LINK_FLAG: 40960, // 0120000 + + /** + * Indicates plain files. + */ + FILE_FLAG: 32768, // 0100000 + + /** + * Indicates directories. + */ + DIR_FLAG: 16384, // 040000 + + // ---------------------------------------------------------- + // somewhat arbitrary choices that are quite common for shared + // installations + // ----------------------------------------------------------- + + /** + * Default permissions for symbolic links. + */ + DEFAULT_LINK_PERM: 511, // 0777 + + /** + * Default permissions for directories. + */ + DEFAULT_DIR_PERM: 493, // 0755 + + /** + * Default permissions for plain files. + */ + DEFAULT_FILE_PERM: 420 // 0644 +}; \ No newline at end of file diff --git a/server/libs/archiver/compress-commons/archivers/zip/util.js b/server/libs/archiver/compress-commons/archivers/zip/util.js new file mode 100644 index 000000000..22055ae51 --- /dev/null +++ b/server/libs/archiver/compress-commons/archivers/zip/util.js @@ -0,0 +1,74 @@ +/** + * node-compress-commons + * + * Copyright (c) 2014 Chris Talkington, contributors. + * Licensed under the MIT license. + * https://github.com/archiverjs/node-compress-commons/blob/master/LICENSE-MIT + */ +var util = module.exports = {}; + +util.dateToDos = function(d, forceLocalTime) { + forceLocalTime = forceLocalTime || false; + + var year = forceLocalTime ? d.getFullYear() : d.getUTCFullYear(); + + if (year < 1980) { + return 2162688; // 1980-1-1 00:00:00 + } else if (year >= 2044) { + return 2141175677; // 2043-12-31 23:59:58 + } + + var val = { + year: year, + month: forceLocalTime ? d.getMonth() : d.getUTCMonth(), + date: forceLocalTime ? d.getDate() : d.getUTCDate(), + hours: forceLocalTime ? d.getHours() : d.getUTCHours(), + minutes: forceLocalTime ? d.getMinutes() : d.getUTCMinutes(), + seconds: forceLocalTime ? d.getSeconds() : d.getUTCSeconds() + }; + + return ((val.year - 1980) << 25) | ((val.month + 1) << 21) | (val.date << 16) | + (val.hours << 11) | (val.minutes << 5) | (val.seconds / 2); +}; + +util.dosToDate = function(dos) { + return new Date(((dos >> 25) & 0x7f) + 1980, ((dos >> 21) & 0x0f) - 1, (dos >> 16) & 0x1f, (dos >> 11) & 0x1f, (dos >> 5) & 0x3f, (dos & 0x1f) << 1); +}; + +util.fromDosTime = function(buf) { + return util.dosToDate(buf.readUInt32LE(0)); +}; + +util.getEightBytes = function(v) { + var buf = Buffer.alloc(8); + buf.writeUInt32LE(v % 0x0100000000, 0); + buf.writeUInt32LE((v / 0x0100000000) | 0, 4); + + return buf; +}; + +util.getShortBytes = function(v) { + var buf = Buffer.alloc(2); + buf.writeUInt16LE((v & 0xFFFF) >>> 0, 0); + + return buf; +}; + +util.getShortBytesValue = function(buf, offset) { + return buf.readUInt16LE(offset); +}; + +util.getLongBytes = function(v) { + var buf = Buffer.alloc(4); + buf.writeUInt32LE((v & 0xFFFFFFFF) >>> 0, 0); + + return buf; +}; + +util.getLongBytesValue = function(buf, offset) { + return buf.readUInt32LE(offset); +}; + +util.toDosTime = function(d) { + return util.getLongBytes(util.dateToDos(d)); +}; \ No newline at end of file diff --git a/server/libs/archiver/compress-commons/archivers/zip/zip-archive-entry.js b/server/libs/archiver/compress-commons/archivers/zip/zip-archive-entry.js new file mode 100644 index 000000000..16fe56fb7 --- /dev/null +++ b/server/libs/archiver/compress-commons/archivers/zip/zip-archive-entry.js @@ -0,0 +1,413 @@ +/** + * node-compress-commons + * + * Copyright (c) 2014 Chris Talkington, contributors. + * Licensed under the MIT license. + * https://github.com/archiverjs/node-compress-commons/blob/master/LICENSE-MIT + */ +var inherits = require('util').inherits; +var normalizePath = require('../../../normalize-path'); + +var ArchiveEntry = require('../archive-entry'); +var GeneralPurposeBit = require('./general-purpose-bit'); +var UnixStat = require('./unix-stat'); + +var constants = require('./constants'); +var zipUtil = require('./util'); + +var ZipArchiveEntry = module.exports = function (name) { + if (!(this instanceof ZipArchiveEntry)) { + return new ZipArchiveEntry(name); + } + + ArchiveEntry.call(this); + + this.platform = constants.PLATFORM_FAT; + this.method = -1; + + this.name = null; + this.size = 0; + this.csize = 0; + this.gpb = new GeneralPurposeBit(); + this.crc = 0; + this.time = -1; + + this.minver = constants.MIN_VERSION_INITIAL; + this.mode = -1; + this.extra = null; + this.exattr = 0; + this.inattr = 0; + this.comment = null; + + if (name) { + this.setName(name); + } +}; + +inherits(ZipArchiveEntry, ArchiveEntry); + +/** + * Returns the extra fields related to the entry. + * + * @returns {Buffer} + */ +ZipArchiveEntry.prototype.getCentralDirectoryExtra = function () { + return this.getExtra(); +}; + +/** + * Returns the comment set for the entry. + * + * @returns {string} + */ +ZipArchiveEntry.prototype.getComment = function () { + return this.comment !== null ? this.comment : ''; +}; + +/** + * Returns the compressed size of the entry. + * + * @returns {number} + */ +ZipArchiveEntry.prototype.getCompressedSize = function () { + return this.csize; +}; + +/** + * Returns the CRC32 digest for the entry. + * + * @returns {number} + */ +ZipArchiveEntry.prototype.getCrc = function () { + return this.crc; +}; + +/** + * Returns the external file attributes for the entry. + * + * @returns {number} + */ +ZipArchiveEntry.prototype.getExternalAttributes = function () { + return this.exattr; +}; + +/** + * Returns the extra fields related to the entry. + * + * @returns {Buffer} + */ +ZipArchiveEntry.prototype.getExtra = function () { + return this.extra !== null ? this.extra : constants.EMPTY; +}; + +/** + * Returns the general purpose bits related to the entry. + * + * @returns {GeneralPurposeBit} + */ +ZipArchiveEntry.prototype.getGeneralPurposeBit = function () { + return this.gpb; +}; + +/** + * Returns the internal file attributes for the entry. + * + * @returns {number} + */ +ZipArchiveEntry.prototype.getInternalAttributes = function () { + return this.inattr; +}; + +/** + * Returns the last modified date of the entry. + * + * @returns {number} + */ +ZipArchiveEntry.prototype.getLastModifiedDate = function () { + return this.getTime(); +}; + +/** + * Returns the extra fields related to the entry. + * + * @returns {Buffer} + */ +ZipArchiveEntry.prototype.getLocalFileDataExtra = function () { + return this.getExtra(); +}; + +/** + * Returns the compression method used on the entry. + * + * @returns {number} + */ +ZipArchiveEntry.prototype.getMethod = function () { + return this.method; +}; + +/** + * Returns the filename of the entry. + * + * @returns {string} + */ +ZipArchiveEntry.prototype.getName = function () { + return this.name; +}; + +/** + * Returns the platform on which the entry was made. + * + * @returns {number} + */ +ZipArchiveEntry.prototype.getPlatform = function () { + return this.platform; +}; + +/** + * Returns the size of the entry. + * + * @returns {number} + */ +ZipArchiveEntry.prototype.getSize = function () { + return this.size; +}; + +/** + * Returns a date object representing the last modified date of the entry. + * + * @returns {number|Date} + */ +ZipArchiveEntry.prototype.getTime = function () { + return this.time !== -1 ? zipUtil.dosToDate(this.time) : -1; +}; + +/** + * Returns the DOS timestamp for the entry. + * + * @returns {number} + */ +ZipArchiveEntry.prototype.getTimeDos = function () { + return this.time !== -1 ? this.time : 0; +}; + +/** + * Returns the UNIX file permissions for the entry. + * + * @returns {number} + */ +ZipArchiveEntry.prototype.getUnixMode = function () { + return this.platform !== constants.PLATFORM_UNIX ? 0 : ((this.getExternalAttributes() >> constants.SHORT_SHIFT) & constants.SHORT_MASK); +}; + +/** + * Returns the version of ZIP needed to extract the entry. + * + * @returns {number} + */ +ZipArchiveEntry.prototype.getVersionNeededToExtract = function () { + return this.minver; +}; + +/** + * Sets the comment of the entry. + * + * @param comment + */ +ZipArchiveEntry.prototype.setComment = function (comment) { + if (Buffer.byteLength(comment) !== comment.length) { + this.getGeneralPurposeBit().useUTF8ForNames(true); + } + + this.comment = comment; +}; + +/** + * Sets the compressed size of the entry. + * + * @param size + */ +ZipArchiveEntry.prototype.setCompressedSize = function (size) { + if (size < 0) { + throw new Error('invalid entry compressed size'); + } + + this.csize = size; +}; + +/** + * Sets the checksum of the entry. + * + * @param crc + */ +ZipArchiveEntry.prototype.setCrc = function (crc) { + if (crc < 0) { + throw new Error('invalid entry crc32'); + } + + this.crc = crc; +}; + +/** + * Sets the external file attributes of the entry. + * + * @param attr + */ +ZipArchiveEntry.prototype.setExternalAttributes = function (attr) { + this.exattr = attr >>> 0; +}; + +/** + * Sets the extra fields related to the entry. + * + * @param extra + */ +ZipArchiveEntry.prototype.setExtra = function (extra) { + this.extra = extra; +}; + +/** + * Sets the general purpose bits related to the entry. + * + * @param gpb + */ +ZipArchiveEntry.prototype.setGeneralPurposeBit = function (gpb) { + if (!(gpb instanceof GeneralPurposeBit)) { + throw new Error('invalid entry GeneralPurposeBit'); + } + + this.gpb = gpb; +}; + +/** + * Sets the internal file attributes of the entry. + * + * @param attr + */ +ZipArchiveEntry.prototype.setInternalAttributes = function (attr) { + this.inattr = attr; +}; + +/** + * Sets the compression method of the entry. + * + * @param method + */ +ZipArchiveEntry.prototype.setMethod = function (method) { + if (method < 0) { + throw new Error('invalid entry compression method'); + } + + this.method = method; +}; + +/** + * Sets the name of the entry. + * + * @param name + * @param prependSlash + */ +ZipArchiveEntry.prototype.setName = function (name, prependSlash = false) { + name = normalizePath(name, false) + .replace(/^\w+:/, '') + .replace(/^(\.\.\/|\/)+/, ''); + + if (prependSlash) { + name = `/${name}`; + } + + if (Buffer.byteLength(name) !== name.length) { + this.getGeneralPurposeBit().useUTF8ForNames(true); + } + + this.name = name; +}; + +/** + * Sets the platform on which the entry was made. + * + * @param platform + */ +ZipArchiveEntry.prototype.setPlatform = function (platform) { + this.platform = platform; +}; + +/** + * Sets the size of the entry. + * + * @param size + */ +ZipArchiveEntry.prototype.setSize = function (size) { + if (size < 0) { + throw new Error('invalid entry size'); + } + + this.size = size; +}; + +/** + * Sets the time of the entry. + * + * @param time + * @param forceLocalTime + */ +ZipArchiveEntry.prototype.setTime = function (time, forceLocalTime) { + if (!(time instanceof Date)) { + throw new Error('invalid entry time'); + } + + this.time = zipUtil.dateToDos(time, forceLocalTime); +}; + +/** + * Sets the UNIX file permissions for the entry. + * + * @param mode + */ +ZipArchiveEntry.prototype.setUnixMode = function (mode) { + mode |= this.isDirectory() ? constants.S_IFDIR : constants.S_IFREG; + + var extattr = 0; + extattr |= (mode << constants.SHORT_SHIFT) | (this.isDirectory() ? constants.S_DOS_D : constants.S_DOS_A); + + this.setExternalAttributes(extattr); + this.mode = mode & constants.MODE_MASK; + this.platform = constants.PLATFORM_UNIX; +}; + +/** + * Sets the version of ZIP needed to extract this entry. + * + * @param minver + */ +ZipArchiveEntry.prototype.setVersionNeededToExtract = function (minver) { + this.minver = minver; +}; + +/** + * Returns true if this entry represents a directory. + * + * @returns {boolean} + */ +ZipArchiveEntry.prototype.isDirectory = function () { + return this.getName().slice(-1) === '/'; +}; + +/** + * Returns true if this entry represents a unix symlink, + * in which case the entry's content contains the target path + * for the symlink. + * + * @returns {boolean} + */ +ZipArchiveEntry.prototype.isUnixSymlink = function () { + return (this.getUnixMode() & UnixStat.FILE_TYPE_FLAG) === UnixStat.LINK_FLAG; +}; + +/** + * Returns true if this entry is using the ZIP64 extension of ZIP. + * + * @returns {boolean} + */ +ZipArchiveEntry.prototype.isZip64 = function () { + return this.csize > constants.ZIP64_MAGIC || this.size > constants.ZIP64_MAGIC; +}; diff --git a/server/libs/archiver/compress-commons/archivers/zip/zip-archive-output-stream.js b/server/libs/archiver/compress-commons/archivers/zip/zip-archive-output-stream.js new file mode 100644 index 000000000..bc90058de --- /dev/null +++ b/server/libs/archiver/compress-commons/archivers/zip/zip-archive-output-stream.js @@ -0,0 +1,437 @@ +/** + * node-compress-commons + * + * Copyright (c) 2014 Chris Talkington, contributors. + * Licensed under the MIT license. + * https://github.com/archiverjs/node-compress-commons/blob/master/LICENSE-MIT + */ +var inherits = require('util').inherits; +var crc32 = require('../../../buffer-crc32'); +var { CRC32Stream } = require('../../../crc32-stream'); +var { DeflateCRC32Stream } = require('../../../crc32-stream'); + +var ArchiveOutputStream = require('../archive-output-stream'); + +var constants = require('./constants'); +var zipUtil = require('./util'); + +var ZipArchiveOutputStream = module.exports = function (options) { + if (!(this instanceof ZipArchiveOutputStream)) { + return new ZipArchiveOutputStream(options); + } + + options = this.options = this._defaults(options); + + ArchiveOutputStream.call(this, options); + + this._entry = null; + this._entries = []; + this._archive = { + centralLength: 0, + centralOffset: 0, + comment: '', + finish: false, + finished: false, + processing: false, + forceZip64: options.forceZip64, + forceLocalTime: options.forceLocalTime + }; +}; + +inherits(ZipArchiveOutputStream, ArchiveOutputStream); + +ZipArchiveOutputStream.prototype._afterAppend = function (ae) { + this._entries.push(ae); + + if (ae.getGeneralPurposeBit().usesDataDescriptor()) { + this._writeDataDescriptor(ae); + } + + this._archive.processing = false; + this._entry = null; + + if (this._archive.finish && !this._archive.finished) { + this._finish(); + } +}; + +ZipArchiveOutputStream.prototype._appendBuffer = function (ae, source, callback) { + if (source.length === 0) { + ae.setMethod(constants.METHOD_STORED); + } + + var method = ae.getMethod(); + + if (method === constants.METHOD_STORED) { + ae.setSize(source.length); + ae.setCompressedSize(source.length); + ae.setCrc(crc32.unsigned(source)); + } + + this._writeLocalFileHeader(ae); + + if (method === constants.METHOD_STORED) { + this.write(source); + this._afterAppend(ae); + callback(null, ae); + return; + } else if (method === constants.METHOD_DEFLATED) { + this._smartStream(ae, callback).end(source); + return; + } else { + callback(new Error('compression method ' + method + ' not implemented')); + return; + } +}; + +ZipArchiveOutputStream.prototype._appendStream = function (ae, source, callback) { + ae.getGeneralPurposeBit().useDataDescriptor(true); + ae.setVersionNeededToExtract(constants.MIN_VERSION_DATA_DESCRIPTOR); + + this._writeLocalFileHeader(ae); + + var smart = this._smartStream(ae, callback); + source.once('error', function (err) { + smart.emit('error', err); + smart.end(); + }) + source.pipe(smart); +}; + +ZipArchiveOutputStream.prototype._defaults = function (o) { + if (typeof o !== 'object') { + o = {}; + } + + if (typeof o.zlib !== 'object') { + o.zlib = {}; + } + + if (typeof o.zlib.level !== 'number') { + o.zlib.level = constants.ZLIB_BEST_SPEED; + } + + o.forceZip64 = !!o.forceZip64; + o.forceLocalTime = !!o.forceLocalTime; + + return o; +}; + +ZipArchiveOutputStream.prototype._finish = function () { + this._archive.centralOffset = this.offset; + + this._entries.forEach(function (ae) { + this._writeCentralFileHeader(ae); + }.bind(this)); + + this._archive.centralLength = this.offset - this._archive.centralOffset; + + if (this.isZip64()) { + this._writeCentralDirectoryZip64(); + } + + this._writeCentralDirectoryEnd(); + + this._archive.processing = false; + this._archive.finish = true; + this._archive.finished = true; + this.end(); +}; + +ZipArchiveOutputStream.prototype._normalizeEntry = function (ae) { + if (ae.getMethod() === -1) { + ae.setMethod(constants.METHOD_DEFLATED); + } + + if (ae.getMethod() === constants.METHOD_DEFLATED) { + ae.getGeneralPurposeBit().useDataDescriptor(true); + ae.setVersionNeededToExtract(constants.MIN_VERSION_DATA_DESCRIPTOR); + } + + if (ae.getTime() === -1) { + ae.setTime(new Date(), this._archive.forceLocalTime); + } + + ae._offsets = { + file: 0, + data: 0, + contents: 0, + }; +}; + +ZipArchiveOutputStream.prototype._smartStream = function (ae, callback) { + var deflate = ae.getMethod() === constants.METHOD_DEFLATED; + var process = deflate ? new DeflateCRC32Stream(this.options.zlib) : new CRC32Stream(); + var error = null; + + function handleStuff() { + var digest = process.digest().readUInt32BE(0); + ae.setCrc(digest); + ae.setSize(process.size()); + ae.setCompressedSize(process.size(true)); + this._afterAppend(ae); + callback(error, ae); + } + + process.once('end', handleStuff.bind(this)); + process.once('error', function (err) { + error = err; + }); + + process.pipe(this, { end: false }); + + return process; +}; + +ZipArchiveOutputStream.prototype._writeCentralDirectoryEnd = function () { + var records = this._entries.length; + var size = this._archive.centralLength; + var offset = this._archive.centralOffset; + + if (this.isZip64()) { + records = constants.ZIP64_MAGIC_SHORT; + size = constants.ZIP64_MAGIC; + offset = constants.ZIP64_MAGIC; + } + + // signature + this.write(zipUtil.getLongBytes(constants.SIG_EOCD)); + + // disk numbers + this.write(constants.SHORT_ZERO); + this.write(constants.SHORT_ZERO); + + // number of entries + this.write(zipUtil.getShortBytes(records)); + this.write(zipUtil.getShortBytes(records)); + + // length and location of CD + this.write(zipUtil.getLongBytes(size)); + this.write(zipUtil.getLongBytes(offset)); + + // archive comment + var comment = this.getComment(); + var commentLength = Buffer.byteLength(comment); + this.write(zipUtil.getShortBytes(commentLength)); + this.write(comment); +}; + +ZipArchiveOutputStream.prototype._writeCentralDirectoryZip64 = function () { + // signature + this.write(zipUtil.getLongBytes(constants.SIG_ZIP64_EOCD)); + + // size of the ZIP64 EOCD record + this.write(zipUtil.getEightBytes(44)); + + // version made by + this.write(zipUtil.getShortBytes(constants.MIN_VERSION_ZIP64)); + + // version to extract + this.write(zipUtil.getShortBytes(constants.MIN_VERSION_ZIP64)); + + // disk numbers + this.write(constants.LONG_ZERO); + this.write(constants.LONG_ZERO); + + // number of entries + this.write(zipUtil.getEightBytes(this._entries.length)); + this.write(zipUtil.getEightBytes(this._entries.length)); + + // length and location of CD + this.write(zipUtil.getEightBytes(this._archive.centralLength)); + this.write(zipUtil.getEightBytes(this._archive.centralOffset)); + + // extensible data sector + // not implemented at this time + + // end of central directory locator + this.write(zipUtil.getLongBytes(constants.SIG_ZIP64_EOCD_LOC)); + + // disk number holding the ZIP64 EOCD record + this.write(constants.LONG_ZERO); + + // relative offset of the ZIP64 EOCD record + this.write(zipUtil.getEightBytes(this._archive.centralOffset + this._archive.centralLength)); + + // total number of disks + this.write(zipUtil.getLongBytes(1)); +}; + +ZipArchiveOutputStream.prototype._writeCentralFileHeader = function (ae) { + var gpb = ae.getGeneralPurposeBit(); + var method = ae.getMethod(); + var offsets = ae._offsets; + + var size = ae.getSize(); + var compressedSize = ae.getCompressedSize(); + + if (ae.isZip64() || offsets.file > constants.ZIP64_MAGIC) { + size = constants.ZIP64_MAGIC; + compressedSize = constants.ZIP64_MAGIC; + + ae.setVersionNeededToExtract(constants.MIN_VERSION_ZIP64); + + var extraBuf = Buffer.concat([ + zipUtil.getShortBytes(constants.ZIP64_EXTRA_ID), + zipUtil.getShortBytes(24), + zipUtil.getEightBytes(ae.getSize()), + zipUtil.getEightBytes(ae.getCompressedSize()), + zipUtil.getEightBytes(offsets.file) + ], 28); + + ae.setExtra(extraBuf); + } + + // signature + this.write(zipUtil.getLongBytes(constants.SIG_CFH)); + + // version made by + this.write(zipUtil.getShortBytes((ae.getPlatform() << 8) | constants.VERSION_MADEBY)); + + // version to extract and general bit flag + this.write(zipUtil.getShortBytes(ae.getVersionNeededToExtract())); + this.write(gpb.encode()); + + // compression method + this.write(zipUtil.getShortBytes(method)); + + // datetime + this.write(zipUtil.getLongBytes(ae.getTimeDos())); + + // crc32 checksum + this.write(zipUtil.getLongBytes(ae.getCrc())); + + // sizes + this.write(zipUtil.getLongBytes(compressedSize)); + this.write(zipUtil.getLongBytes(size)); + + var name = ae.getName(); + var comment = ae.getComment(); + var extra = ae.getCentralDirectoryExtra(); + + if (gpb.usesUTF8ForNames()) { + name = Buffer.from(name); + comment = Buffer.from(comment); + } + + // name length + this.write(zipUtil.getShortBytes(name.length)); + + // extra length + this.write(zipUtil.getShortBytes(extra.length)); + + // comments length + this.write(zipUtil.getShortBytes(comment.length)); + + // disk number start + this.write(constants.SHORT_ZERO); + + // internal attributes + this.write(zipUtil.getShortBytes(ae.getInternalAttributes())); + + // external attributes + this.write(zipUtil.getLongBytes(ae.getExternalAttributes())); + + // relative offset of LFH + if (offsets.file > constants.ZIP64_MAGIC) { + this.write(zipUtil.getLongBytes(constants.ZIP64_MAGIC)); + } else { + this.write(zipUtil.getLongBytes(offsets.file)); + } + + // name + this.write(name); + + // extra + this.write(extra); + + // comment + this.write(comment); +}; + +ZipArchiveOutputStream.prototype._writeDataDescriptor = function (ae) { + // signature + this.write(zipUtil.getLongBytes(constants.SIG_DD)); + + // crc32 checksum + this.write(zipUtil.getLongBytes(ae.getCrc())); + + // sizes + if (ae.isZip64()) { + this.write(zipUtil.getEightBytes(ae.getCompressedSize())); + this.write(zipUtil.getEightBytes(ae.getSize())); + } else { + this.write(zipUtil.getLongBytes(ae.getCompressedSize())); + this.write(zipUtil.getLongBytes(ae.getSize())); + } +}; + +ZipArchiveOutputStream.prototype._writeLocalFileHeader = function (ae) { + var gpb = ae.getGeneralPurposeBit(); + var method = ae.getMethod(); + var name = ae.getName(); + var extra = ae.getLocalFileDataExtra(); + + if (ae.isZip64()) { + gpb.useDataDescriptor(true); + ae.setVersionNeededToExtract(constants.MIN_VERSION_ZIP64); + } + + if (gpb.usesUTF8ForNames()) { + name = Buffer.from(name); + } + + ae._offsets.file = this.offset; + + // signature + this.write(zipUtil.getLongBytes(constants.SIG_LFH)); + + // version to extract and general bit flag + this.write(zipUtil.getShortBytes(ae.getVersionNeededToExtract())); + this.write(gpb.encode()); + + // compression method + this.write(zipUtil.getShortBytes(method)); + + // datetime + this.write(zipUtil.getLongBytes(ae.getTimeDos())); + + ae._offsets.data = this.offset; + + // crc32 checksum and sizes + if (gpb.usesDataDescriptor()) { + this.write(constants.LONG_ZERO); + this.write(constants.LONG_ZERO); + this.write(constants.LONG_ZERO); + } else { + this.write(zipUtil.getLongBytes(ae.getCrc())); + this.write(zipUtil.getLongBytes(ae.getCompressedSize())); + this.write(zipUtil.getLongBytes(ae.getSize())); + } + + // name length + this.write(zipUtil.getShortBytes(name.length)); + + // extra length + this.write(zipUtil.getShortBytes(extra.length)); + + // name + this.write(name); + + // extra + this.write(extra); + + ae._offsets.contents = this.offset; +}; + +ZipArchiveOutputStream.prototype.getComment = function (comment) { + return this._archive.comment !== null ? this._archive.comment : ''; +}; + +ZipArchiveOutputStream.prototype.isZip64 = function () { + return this._archive.forceZip64 || this._entries.length > constants.ZIP64_MAGIC_SHORT || this._archive.centralLength > constants.ZIP64_MAGIC || this._archive.centralOffset > constants.ZIP64_MAGIC; +}; + +ZipArchiveOutputStream.prototype.setComment = function (comment) { + this._archive.comment = comment; +}; diff --git a/server/libs/archiver/compress-commons/index.js b/server/libs/archiver/compress-commons/index.js new file mode 100644 index 000000000..ef3bc1dbe --- /dev/null +++ b/server/libs/archiver/compress-commons/index.js @@ -0,0 +1,13 @@ +/** + * node-compress-commons + * + * Copyright (c) 2014 Chris Talkington, contributors. + * Licensed under the MIT license. + * https://github.com/archiverjs/node-compress-commons/blob/master/LICENSE-MIT + */ +module.exports = { + ArchiveEntry: require('./archivers/archive-entry'), + ZipArchiveEntry: require('./archivers/zip/zip-archive-entry'), + ArchiveOutputStream: require('./archivers/archive-output-stream'), + ZipArchiveOutputStream: require('./archivers/zip/zip-archive-output-stream') +}; \ No newline at end of file diff --git a/server/libs/archiver/compress-commons/util/index.js b/server/libs/archiver/compress-commons/util/index.js new file mode 100644 index 000000000..20a678331 --- /dev/null +++ b/server/libs/archiver/compress-commons/util/index.js @@ -0,0 +1,30 @@ +/** + * node-compress-commons + * + * Copyright (c) 2014 Chris Talkington, contributors. + * Licensed under the MIT license. + * https://github.com/archiverjs/node-compress-commons/blob/master/LICENSE-MIT + */ +var Stream = require('stream').Stream; +var PassThrough = require('readable-stream').PassThrough; + +var util = module.exports = {}; + +util.isStream = function(source) { + return source instanceof Stream; +}; + +util.normalizeInputSource = function(source) { + if (source === null) { + return Buffer.alloc(0); + } else if (typeof source === 'string') { + return Buffer.from(source); + } else if (util.isStream(source) && !source._readableState) { + var normalized = new PassThrough(); + source.pipe(normalized); + + return normalized; + } + + return source; +}; \ No newline at end of file diff --git a/server/libs/archiver/crc32-stream/LICENSE b/server/libs/archiver/crc32-stream/LICENSE new file mode 100644 index 000000000..56420a6a0 --- /dev/null +++ b/server/libs/archiver/crc32-stream/LICENSE @@ -0,0 +1,22 @@ +Copyright (c) 2014 Chris Talkington, contributors. + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/server/libs/archiver/crc32-stream/crc32-stream.js b/server/libs/archiver/crc32-stream/crc32-stream.js new file mode 100644 index 000000000..b3588b268 --- /dev/null +++ b/server/libs/archiver/crc32-stream/crc32-stream.js @@ -0,0 +1,48 @@ +/** + * node-crc32-stream + * + * Copyright (c) 2014 Chris Talkington, contributors. + * Licensed under the MIT license. + * https://github.com/archiverjs/node-crc32-stream/blob/master/LICENSE-MIT + */ + +'use strict'; + +const { Transform } = require('readable-stream'); + +const crc32 = require('../crc32'); + +class CRC32Stream extends Transform { + constructor(options) { + super(options); + this.checksum = Buffer.allocUnsafe(4); + this.checksum.writeInt32BE(0, 0); + + this.rawSize = 0; + } + + _transform(chunk, encoding, callback) { + if (chunk) { + this.checksum = crc32.buf(chunk, this.checksum) >>> 0; + this.rawSize += chunk.length; + } + + callback(null, chunk); + } + + digest(encoding) { + const checksum = Buffer.allocUnsafe(4); + checksum.writeUInt32BE(this.checksum >>> 0, 0); + return encoding ? checksum.toString(encoding) : checksum; + } + + hex() { + return this.digest('hex').toUpperCase(); + } + + size() { + return this.rawSize; + } +} + +module.exports = CRC32Stream; diff --git a/server/libs/archiver/crc32-stream/deflate-crc32-stream.js b/server/libs/archiver/crc32-stream/deflate-crc32-stream.js new file mode 100644 index 000000000..ee8814e33 --- /dev/null +++ b/server/libs/archiver/crc32-stream/deflate-crc32-stream.js @@ -0,0 +1,62 @@ +/** + * node-crc32-stream + * + * Copyright (c) 2014 Chris Talkington, contributors. + * Licensed under the MIT license. + * https://github.com/archiverjs/node-crc32-stream/blob/master/LICENSE-MIT + */ + +'use strict'; + +const { DeflateRaw } = require('zlib'); + +const crc32 = require('../crc32'); + +class DeflateCRC32Stream extends DeflateRaw { + constructor(options) { + super(options); + + this.checksum = Buffer.allocUnsafe(4); + this.checksum.writeInt32BE(0, 0); + + this.rawSize = 0; + this.compressedSize = 0; + } + + push(chunk, encoding) { + if (chunk) { + this.compressedSize += chunk.length; + } + + return super.push(chunk, encoding); + } + + _transform(chunk, encoding, callback) { + if (chunk) { + this.checksum = crc32.buf(chunk, this.checksum) >>> 0; + this.rawSize += chunk.length; + } + + super._transform(chunk, encoding, callback) + } + + digest(encoding) { + const checksum = Buffer.allocUnsafe(4); + checksum.writeUInt32BE(this.checksum >>> 0, 0); + return encoding ? checksum.toString(encoding) : checksum; + } + + hex() { + return this.digest('hex').toUpperCase(); + } + + size(compressed = false) { + if (compressed) { + return this.compressedSize; + } else { + return this.rawSize; + } + } +} + +module.exports = DeflateCRC32Stream; diff --git a/server/libs/archiver/crc32-stream/index.js b/server/libs/archiver/crc32-stream/index.js new file mode 100644 index 000000000..8e154ecd3 --- /dev/null +++ b/server/libs/archiver/crc32-stream/index.js @@ -0,0 +1,14 @@ +/** + * node-crc32-stream + * + * Copyright (c) 2014 Chris Talkington, contributors. + * Licensed under the MIT license. + * https://github.com/archiverjs/node-crc32-stream/blob/master/LICENSE-MIT + */ + +'use strict'; + +module.exports = { + CRC32Stream: require('./crc32-stream'), + DeflateCRC32Stream: require('./deflate-crc32-stream') +} diff --git a/server/libs/archiver/crc32/LICENSE b/server/libs/archiver/crc32/LICENSE new file mode 100644 index 000000000..d6f5b4cb6 --- /dev/null +++ b/server/libs/archiver/crc32/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright (C) 2014-present SheetJS LLC + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. \ No newline at end of file diff --git a/server/libs/archiver/crc32/index.js b/server/libs/archiver/crc32/index.js new file mode 100644 index 000000000..63852b0f2 --- /dev/null +++ b/server/libs/archiver/crc32/index.js @@ -0,0 +1,115 @@ +/*! crc32.js (C) 2014-present SheetJS -- http://sheetjs.com */ +/* vim: set ts=2: */ +/*exported CRC32 */ +var CRC32; +(function (factory) { + /*jshint ignore:start */ + /*eslint-disable */ + if(typeof DO_NOT_EXPORT_CRC === 'undefined') { + if('object' === typeof exports) { + factory(exports); + } else if ('function' === typeof define && define.amd) { + define(function () { + var module = {}; + factory(module); + return module; + }); + } else { + factory(CRC32 = {}); + } + } else { + factory(CRC32 = {}); + } + /*eslint-enable */ + /*jshint ignore:end */ +}(function(CRC32) { +CRC32.version = '1.2.2'; +/*global Int32Array */ +function signed_crc_table() { + var c = 0, table = new Array(256); + + for(var n =0; n != 256; ++n){ + c = n; + c = ((c&1) ? (-306674912 ^ (c >>> 1)) : (c >>> 1)); + c = ((c&1) ? (-306674912 ^ (c >>> 1)) : (c >>> 1)); + c = ((c&1) ? (-306674912 ^ (c >>> 1)) : (c >>> 1)); + c = ((c&1) ? (-306674912 ^ (c >>> 1)) : (c >>> 1)); + c = ((c&1) ? (-306674912 ^ (c >>> 1)) : (c >>> 1)); + c = ((c&1) ? (-306674912 ^ (c >>> 1)) : (c >>> 1)); + c = ((c&1) ? (-306674912 ^ (c >>> 1)) : (c >>> 1)); + c = ((c&1) ? (-306674912 ^ (c >>> 1)) : (c >>> 1)); + table[n] = c; + } + + return typeof Int32Array !== 'undefined' ? new Int32Array(table) : table; +} + +var T0 = signed_crc_table(); +function slice_by_16_tables(T) { + var c = 0, v = 0, n = 0, table = typeof Int32Array !== 'undefined' ? new Int32Array(4096) : new Array(4096) ; + + for(n = 0; n != 256; ++n) table[n] = T[n]; + for(n = 0; n != 256; ++n) { + v = T[n]; + for(c = 256 + n; c < 4096; c += 256) v = table[c] = (v >>> 8) ^ T[v & 0xFF]; + } + var out = []; + for(n = 1; n != 16; ++n) out[n - 1] = typeof Int32Array !== 'undefined' ? table.subarray(n * 256, n * 256 + 256) : table.slice(n * 256, n * 256 + 256); + return out; +} +var TT = slice_by_16_tables(T0); +var T1 = TT[0], T2 = TT[1], T3 = TT[2], T4 = TT[3], T5 = TT[4]; +var T6 = TT[5], T7 = TT[6], T8 = TT[7], T9 = TT[8], Ta = TT[9]; +var Tb = TT[10], Tc = TT[11], Td = TT[12], Te = TT[13], Tf = TT[14]; +function crc32_bstr(bstr, seed) { + var C = seed ^ -1; + for(var i = 0, L = bstr.length; i < L;) C = (C>>>8) ^ T0[(C^bstr.charCodeAt(i++))&0xFF]; + return ~C; +} + +function crc32_buf(B, seed) { + var C = seed ^ -1, L = B.length - 15, i = 0; + for(; i < L;) C = + Tf[B[i++] ^ (C & 255)] ^ + Te[B[i++] ^ ((C >> 8) & 255)] ^ + Td[B[i++] ^ ((C >> 16) & 255)] ^ + Tc[B[i++] ^ (C >>> 24)] ^ + Tb[B[i++]] ^ Ta[B[i++]] ^ T9[B[i++]] ^ T8[B[i++]] ^ + T7[B[i++]] ^ T6[B[i++]] ^ T5[B[i++]] ^ T4[B[i++]] ^ + T3[B[i++]] ^ T2[B[i++]] ^ T1[B[i++]] ^ T0[B[i++]]; + L += 15; + while(i < L) C = (C>>>8) ^ T0[(C^B[i++])&0xFF]; + return ~C; +} + +function crc32_str(str, seed) { + var C = seed ^ -1; + for(var i = 0, L = str.length, c = 0, d = 0; i < L;) { + c = str.charCodeAt(i++); + if(c < 0x80) { + C = (C>>>8) ^ T0[(C^c)&0xFF]; + } else if(c < 0x800) { + C = (C>>>8) ^ T0[(C ^ (192|((c>>6)&31)))&0xFF]; + C = (C>>>8) ^ T0[(C ^ (128|(c&63)))&0xFF]; + } else if(c >= 0xD800 && c < 0xE000) { + c = (c&1023)+64; d = str.charCodeAt(i++)&1023; + C = (C>>>8) ^ T0[(C ^ (240|((c>>8)&7)))&0xFF]; + C = (C>>>8) ^ T0[(C ^ (128|((c>>2)&63)))&0xFF]; + C = (C>>>8) ^ T0[(C ^ (128|((d>>6)&15)|((c&3)<<4)))&0xFF]; + C = (C>>>8) ^ T0[(C ^ (128|(d&63)))&0xFF]; + } else { + C = (C>>>8) ^ T0[(C ^ (224|((c>>12)&15)))&0xFF]; + C = (C>>>8) ^ T0[(C ^ (128|((c>>6)&63)))&0xFF]; + C = (C>>>8) ^ T0[(C ^ (128|(c&63)))&0xFF]; + } + } + return ~C; +} +CRC32.table = T0; +// $FlowIgnore +CRC32.bstr = crc32_bstr; +// $FlowIgnore +CRC32.buf = crc32_buf; +// $FlowIgnore +CRC32.str = crc32_str; +})); \ No newline at end of file diff --git a/server/libs/archiver/index.js b/server/libs/archiver/index.js new file mode 100644 index 000000000..95cff93e3 --- /dev/null +++ b/server/libs/archiver/index.js @@ -0,0 +1,83 @@ +/** + * Archiver Vending + * + * @ignore + * @license [MIT]{@link https://github.com/archiverjs/node-archiver/blob/master/LICENSE} + * @copyright (c) 2012-2014 Chris Talkington, contributors. + */ +var Archiver = require('./lib/core'); + +var formats = {}; + +/** + * Dispenses a new Archiver instance. + * + * @constructor + * @param {String} format The archive format to use. + * @param {Object} options See [Archiver]{@link Archiver} + * @return {Archiver} + */ +var vending = function (format, options) { + return vending.create(format, options); +}; + +/** + * Creates a new Archiver instance. + * + * @param {String} format The archive format to use. + * @param {Object} options See [Archiver]{@link Archiver} + * @return {Archiver} + */ +vending.create = function (format, options) { + if (formats[format]) { + var instance = new Archiver(format, options); + instance.setFormat(format); + instance.setModule(new formats[format](options)); + + return instance; + } else { + throw new Error('create(' + format + '): format not registered'); + } +}; + +/** + * Registers a format for use with archiver. + * + * @param {String} format The name of the format. + * @param {Function} module The function for archiver to interact with. + * @return void + */ +vending.registerFormat = function (format, module) { + if (formats[format]) { + throw new Error('register(' + format + '): format already registered'); + } + + if (typeof module !== 'function') { + throw new Error('register(' + format + '): format module invalid'); + } + + if (typeof module.prototype.append !== 'function' || typeof module.prototype.finalize !== 'function') { + throw new Error('register(' + format + '): format module missing methods'); + } + + formats[format] = module; +}; + +/** + * Check if the format is already registered. + * + * @param {String} format the name of the format. + * @return boolean + */ +vending.isRegisteredFormat = function (format) { + if (formats[format]) { + return true; + } + + return false; +}; + +vending.registerFormat('zip', require('./lib/plugins/zip')); +vending.registerFormat('json', require('./lib/plugins/json')); + +module.exports = vending; \ No newline at end of file diff --git a/server/libs/archiver/lib/core.js b/server/libs/archiver/lib/core.js new file mode 100644 index 000000000..8e4aa96d2 --- /dev/null +++ b/server/libs/archiver/lib/core.js @@ -0,0 +1,974 @@ +/** + * Archiver Core + * + * @ignore + * @license [MIT]{@link https://github.com/archiverjs/node-archiver/blob/master/LICENSE} + * @copyright (c) 2012-2014 Chris Talkington, contributors. + */ +var fs = require('fs'); +var glob = require('../readdir-glob'); +var async = require('../../async'); +var path = require('path'); +var util = require('archiver-utils'); + +var inherits = require('util').inherits; +var ArchiverError = require('./error'); +var Transform = require('readable-stream').Transform; + +var win32 = process.platform === 'win32'; + +/** + * @constructor + * @param {String} format The archive format to use. + * @param {(CoreOptions|TransformOptions)} options See also {@link ZipOptions} and {@link TarOptions}. + */ +var Archiver = function (format, options) { + if (!(this instanceof Archiver)) { + return new Archiver(format, options); + } + + if (typeof format !== 'string') { + options = format; + format = 'zip'; + } + + options = this.options = util.defaults(options, { + highWaterMark: 1024 * 1024, + statConcurrency: 4 + }); + + Transform.call(this, options); + + this._format = false; + this._module = false; + this._pending = 0; + this._pointer = 0; + + this._entriesCount = 0; + this._entriesProcessedCount = 0; + this._fsEntriesTotalBytes = 0; + this._fsEntriesProcessedBytes = 0; + + this._queue = async.queue(this._onQueueTask.bind(this), 1); + this._queue.drain(this._onQueueDrain.bind(this)); + + this._statQueue = async.queue(this._onStatQueueTask.bind(this), options.statConcurrency); + this._statQueue.drain(this._onQueueDrain.bind(this)); + + this._state = { + aborted: false, + finalize: false, + finalizing: false, + finalized: false, + modulePiped: false + }; + + this._streams = []; +}; + +inherits(Archiver, Transform); + +/** + * Internal logic for `abort`. + * + * @private + * @return void + */ +Archiver.prototype._abort = function () { + this._state.aborted = true; + this._queue.kill(); + this._statQueue.kill(); + + if (this._queue.idle()) { + this._shutdown(); + } +}; + +/** + * Internal helper for appending files. + * + * @private + * @param {String} filepath The source filepath. + * @param {EntryData} data The entry data. + * @return void + */ +Archiver.prototype._append = function (filepath, data) { + data = data || {}; + + var task = { + source: null, + filepath: filepath + }; + + if (!data.name) { + data.name = filepath; + } + + data.sourcePath = filepath; + task.data = data; + this._entriesCount++; + + if (data.stats && data.stats instanceof fs.Stats) { + task = this._updateQueueTaskWithStats(task, data.stats); + if (task) { + if (data.stats.size) { + this._fsEntriesTotalBytes += data.stats.size; + } + + this._queue.push(task); + } + } else { + this._statQueue.push(task); + } +}; + +/** + * Internal logic for `finalize`. + * + * @private + * @return void + */ +Archiver.prototype._finalize = function () { + if (this._state.finalizing || this._state.finalized || this._state.aborted) { + return; + } + + this._state.finalizing = true; + + this._moduleFinalize(); + + this._state.finalizing = false; + this._state.finalized = true; +}; + +/** + * Checks the various state variables to determine if we can `finalize`. + * + * @private + * @return {Boolean} + */ +Archiver.prototype._maybeFinalize = function () { + if (this._state.finalizing || this._state.finalized || this._state.aborted) { + return false; + } + + if (this._state.finalize && this._pending === 0 && this._queue.idle() && this._statQueue.idle()) { + this._finalize(); + return true; + } + + return false; +}; + +/** + * Appends an entry to the module. + * + * @private + * @fires Archiver#entry + * @param {(Buffer|Stream)} source + * @param {EntryData} data + * @param {Function} callback + * @return void + */ +Archiver.prototype._moduleAppend = function (source, data, callback) { + if (this._state.aborted) { + callback(); + return; + } + + this._module.append(source, data, function (err) { + this._task = null; + + if (this._state.aborted) { + this._shutdown(); + return; + } + + if (err) { + this.emit('error', err); + setImmediate(callback); + return; + } + + /** + * Fires when the entry's input has been processed and appended to the archive. + * + * @event Archiver#entry + * @type {EntryData} + */ + this.emit('entry', data); + this._entriesProcessedCount++; + + if (data.stats && data.stats.size) { + this._fsEntriesProcessedBytes += data.stats.size; + } + + /** + * @event Archiver#progress + * @type {ProgressData} + */ + this.emit('progress', { + entries: { + total: this._entriesCount, + processed: this._entriesProcessedCount + }, + fs: { + totalBytes: this._fsEntriesTotalBytes, + processedBytes: this._fsEntriesProcessedBytes + } + }); + + setImmediate(callback); + }.bind(this)); +}; + +/** + * Finalizes the module. + * + * @private + * @return void + */ +Archiver.prototype._moduleFinalize = function () { + if (typeof this._module.finalize === 'function') { + this._module.finalize(); + } else if (typeof this._module.end === 'function') { + this._module.end(); + } else { + this.emit('error', new ArchiverError('NOENDMETHOD')); + } +}; + +/** + * Pipes the module to our internal stream with error bubbling. + * + * @private + * @return void + */ +Archiver.prototype._modulePipe = function () { + this._module.on('error', this._onModuleError.bind(this)); + this._module.pipe(this); + this._state.modulePiped = true; +}; + +/** + * Determines if the current module supports a defined feature. + * + * @private + * @param {String} key + * @return {Boolean} + */ +Archiver.prototype._moduleSupports = function (key) { + if (!this._module.supports || !this._module.supports[key]) { + return false; + } + + return this._module.supports[key]; +}; + +/** + * Unpipes the module from our internal stream. + * + * @private + * @return void + */ +Archiver.prototype._moduleUnpipe = function () { + this._module.unpipe(this); + this._state.modulePiped = false; +}; + +/** + * Normalizes entry data with fallbacks for key properties. + * + * @private + * @param {Object} data + * @param {fs.Stats} stats + * @return {Object} + */ +Archiver.prototype._normalizeEntryData = function (data, stats) { + data = util.defaults(data, { + type: 'file', + name: null, + date: null, + mode: null, + prefix: null, + sourcePath: null, + stats: false + }); + + if (stats && data.stats === false) { + data.stats = stats; + } + + var isDir = data.type === 'directory'; + + if (data.name) { + if (typeof data.prefix === 'string' && '' !== data.prefix) { + data.name = data.prefix + '/' + data.name; + data.prefix = null; + } + + data.name = util.sanitizePath(data.name); + + if (data.type !== 'symlink' && data.name.slice(-1) === '/') { + isDir = true; + data.type = 'directory'; + } else if (isDir) { + data.name += '/'; + } + } + + // 511 === 0777; 493 === 0755; 438 === 0666; 420 === 0644 + if (typeof data.mode === 'number') { + if (win32) { + data.mode &= 511; + } else { + data.mode &= 4095 + } + } else if (data.stats && data.mode === null) { + if (win32) { + data.mode = data.stats.mode & 511; + } else { + data.mode = data.stats.mode & 4095; + } + + // stat isn't reliable on windows; force 0755 for dir + if (win32 && isDir) { + data.mode = 493; + } + } else if (data.mode === null) { + data.mode = isDir ? 493 : 420; + } + + if (data.stats && data.date === null) { + data.date = data.stats.mtime; + } else { + data.date = util.dateify(data.date); + } + + return data; +}; + +/** + * Error listener that re-emits error on to our internal stream. + * + * @private + * @param {Error} err + * @return void + */ +Archiver.prototype._onModuleError = function (err) { + /** + * @event Archiver#error + * @type {ErrorData} + */ + this.emit('error', err); +}; + +/** + * Checks the various state variables after queue has drained to determine if + * we need to `finalize`. + * + * @private + * @return void + */ +Archiver.prototype._onQueueDrain = function () { + if (this._state.finalizing || this._state.finalized || this._state.aborted) { + return; + } + + if (this._state.finalize && this._pending === 0 && this._queue.idle() && this._statQueue.idle()) { + this._finalize(); + } +}; + +/** + * Appends each queue task to the module. + * + * @private + * @param {Object} task + * @param {Function} callback + * @return void + */ +Archiver.prototype._onQueueTask = function (task, callback) { + var fullCallback = () => { + if (task.data.callback) { + task.data.callback(); + } + callback(); + } + + if (this._state.finalizing || this._state.finalized || this._state.aborted) { + fullCallback(); + return; + } + + this._task = task; + this._moduleAppend(task.source, task.data, fullCallback); +}; + +/** + * Performs a file stat and reinjects the task back into the queue. + * + * @private + * @param {Object} task + * @param {Function} callback + * @return void + */ +Archiver.prototype._onStatQueueTask = function (task, callback) { + if (this._state.finalizing || this._state.finalized || this._state.aborted) { + callback(); + return; + } + + fs.lstat(task.filepath, function (err, stats) { + if (this._state.aborted) { + setImmediate(callback); + return; + } + + if (err) { + this._entriesCount--; + + /** + * @event Archiver#warning + * @type {ErrorData} + */ + this.emit('warning', err); + setImmediate(callback); + return; + } + + task = this._updateQueueTaskWithStats(task, stats); + + if (task) { + if (stats.size) { + this._fsEntriesTotalBytes += stats.size; + } + + this._queue.push(task); + } + + setImmediate(callback); + }.bind(this)); +}; + +/** + * Unpipes the module and ends our internal stream. + * + * @private + * @return void + */ +Archiver.prototype._shutdown = function () { + this._moduleUnpipe(); + this.end(); +}; + +/** + * Tracks the bytes emitted by our internal stream. + * + * @private + * @param {Buffer} chunk + * @param {String} encoding + * @param {Function} callback + * @return void + */ +Archiver.prototype._transform = function (chunk, encoding, callback) { + if (chunk) { + this._pointer += chunk.length; + } + + callback(null, chunk); +}; + +/** + * Updates and normalizes a queue task using stats data. + * + * @private + * @param {Object} task + * @param {fs.Stats} stats + * @return {Object} + */ +Archiver.prototype._updateQueueTaskWithStats = function (task, stats) { + if (stats.isFile()) { + task.data.type = 'file'; + task.data.sourceType = 'stream'; + task.source = util.lazyReadStream(task.filepath); + } else if (stats.isDirectory() && this._moduleSupports('directory')) { + task.data.name = util.trailingSlashIt(task.data.name); + task.data.type = 'directory'; + task.data.sourcePath = util.trailingSlashIt(task.filepath); + task.data.sourceType = 'buffer'; + task.source = Buffer.concat([]); + } else if (stats.isSymbolicLink() && this._moduleSupports('symlink')) { + var linkPath = fs.readlinkSync(task.filepath); + var dirName = path.dirname(task.filepath); + task.data.type = 'symlink'; + task.data.linkname = path.relative(dirName, path.resolve(dirName, linkPath)); + task.data.sourceType = 'buffer'; + task.source = Buffer.concat([]); + } else { + if (stats.isDirectory()) { + this.emit('warning', new ArchiverError('DIRECTORYNOTSUPPORTED', task.data)); + } else if (stats.isSymbolicLink()) { + this.emit('warning', new ArchiverError('SYMLINKNOTSUPPORTED', task.data)); + } else { + this.emit('warning', new ArchiverError('ENTRYNOTSUPPORTED', task.data)); + } + + return null; + } + + task.data = this._normalizeEntryData(task.data, stats); + + return task; +}; + +/** + * Aborts the archiving process, taking a best-effort approach, by: + * + * - removing any pending queue tasks + * - allowing any active queue workers to finish + * - detaching internal module pipes + * - ending both sides of the Transform stream + * + * It will NOT drain any remaining sources. + * + * @return {this} + */ +Archiver.prototype.abort = function () { + if (this._state.aborted || this._state.finalized) { + return this; + } + + this._abort(); + + return this; +}; + +/** + * Appends an input source (text string, buffer, or stream) to the instance. + * + * When the instance has received, processed, and emitted the input, the `entry` + * event is fired. + * + * @fires Archiver#entry + * @param {(Buffer|Stream|String)} source The input source. + * @param {EntryData} data See also {@link ZipEntryData} and {@link TarEntryData}. + * @return {this} + */ +Archiver.prototype.append = function (source, data) { + if (this._state.finalize || this._state.aborted) { + this.emit('error', new ArchiverError('QUEUECLOSED')); + return this; + } + + data = this._normalizeEntryData(data); + + if (typeof data.name !== 'string' || data.name.length === 0) { + this.emit('error', new ArchiverError('ENTRYNAMEREQUIRED')); + return this; + } + + if (data.type === 'directory' && !this._moduleSupports('directory')) { + this.emit('error', new ArchiverError('DIRECTORYNOTSUPPORTED', { name: data.name })); + return this; + } + + source = util.normalizeInputSource(source); + + if (Buffer.isBuffer(source)) { + data.sourceType = 'buffer'; + } else if (util.isStream(source)) { + data.sourceType = 'stream'; + } else { + this.emit('error', new ArchiverError('INPUTSTEAMBUFFERREQUIRED', { name: data.name })); + return this; + } + + this._entriesCount++; + this._queue.push({ + data: data, + source: source + }); + + return this; +}; + +/** + * Appends a directory and its files, recursively, given its dirpath. + * + * @param {String} dirpath The source directory path. + * @param {String} destpath The destination path within the archive. + * @param {(EntryData|Function)} data See also [ZipEntryData]{@link ZipEntryData} and + * [TarEntryData]{@link TarEntryData}. + * @return {this} + */ +Archiver.prototype.directory = function (dirpath, destpath, data) { + if (this._state.finalize || this._state.aborted) { + this.emit('error', new ArchiverError('QUEUECLOSED')); + return this; + } + + if (typeof dirpath !== 'string' || dirpath.length === 0) { + this.emit('error', new ArchiverError('DIRECTORYDIRPATHREQUIRED')); + return this; + } + + this._pending++; + + if (destpath === false) { + destpath = ''; + } else if (typeof destpath !== 'string') { + destpath = dirpath; + } + + var dataFunction = false; + if (typeof data === 'function') { + dataFunction = data; + data = {}; + } else if (typeof data !== 'object') { + data = {}; + } + + var globOptions = { + stat: true, + dot: true + }; + + function onGlobEnd() { + this._pending--; + this._maybeFinalize(); + } + + function onGlobError(err) { + this.emit('error', err); + } + + function onGlobMatch(match) { + globber.pause(); + + var ignoreMatch = false; + var entryData = Object.assign({}, data); + entryData.name = match.relative; + entryData.prefix = destpath; + entryData.stats = match.stat; + entryData.callback = globber.resume.bind(globber); + + try { + if (dataFunction) { + entryData = dataFunction(entryData); + + if (entryData === false) { + ignoreMatch = true; + } else if (typeof entryData !== 'object') { + throw new ArchiverError('DIRECTORYFUNCTIONINVALIDDATA', { dirpath: dirpath }); + } + } + } catch (e) { + this.emit('error', e); + return; + } + + if (ignoreMatch) { + globber.resume(); + return; + } + + this._append(match.absolute, entryData); + } + + var globber = glob(dirpath, globOptions); + globber.on('error', onGlobError.bind(this)); + globber.on('match', onGlobMatch.bind(this)); + globber.on('end', onGlobEnd.bind(this)); + + return this; +}; + +/** + * Appends a file given its filepath using a + * [lazystream]{@link https://github.com/jpommerening/node-lazystream} wrapper to + * prevent issues with open file limits. + * + * When the instance has received, processed, and emitted the file, the `entry` + * event is fired. + * + * @param {String} filepath The source filepath. + * @param {EntryData} data See also [ZipEntryData]{@link ZipEntryData} and + * [TarEntryData]{@link TarEntryData}. + * @return {this} + */ +Archiver.prototype.file = function (filepath, data) { + if (this._state.finalize || this._state.aborted) { + this.emit('error', new ArchiverError('QUEUECLOSED')); + return this; + } + + if (typeof filepath !== 'string' || filepath.length === 0) { + this.emit('error', new ArchiverError('FILEFILEPATHREQUIRED')); + return this; + } + + this._append(filepath, data); + + return this; +}; + +/** + * Appends multiple files that match a glob pattern. + * + * @param {String} pattern The [glob pattern]{@link https://github.com/isaacs/minimatch} to match. + * @param {Object} options See [node-readdir-glob]{@link https://github.com/yqnn/node-readdir-glob#options}. + * @param {EntryData} data See also [ZipEntryData]{@link ZipEntryData} and + * [TarEntryData]{@link TarEntryData}. + * @return {this} + */ +Archiver.prototype.glob = function (pattern, options, data) { + this._pending++; + + options = util.defaults(options, { + stat: true, + pattern: pattern + }); + + function onGlobEnd() { + this._pending--; + this._maybeFinalize(); + } + + function onGlobError(err) { + this.emit('error', err); + } + + function onGlobMatch(match) { + globber.pause(); + var entryData = Object.assign({}, data); + entryData.callback = globber.resume.bind(globber); + entryData.stats = match.stat; + entryData.name = match.relative; + + this._append(match.absolute, entryData); + } + + var globber = glob(options.cwd || '.', options); + globber.on('error', onGlobError.bind(this)); + globber.on('match', onGlobMatch.bind(this)); + globber.on('end', onGlobEnd.bind(this)); + + return this; +}; + +/** + * Finalizes the instance and prevents further appending to the archive + * structure (queue will continue til drained). + * + * The `end`, `close` or `finish` events on the destination stream may fire + * right after calling this method so you should set listeners beforehand to + * properly detect stream completion. + * + * @return {Promise} + */ +Archiver.prototype.finalize = function () { + if (this._state.aborted) { + var abortedError = new ArchiverError('ABORTED'); + this.emit('error', abortedError); + return Promise.reject(abortedError); + } + + if (this._state.finalize) { + var finalizingError = new ArchiverError('FINALIZING'); + this.emit('error', finalizingError); + return Promise.reject(finalizingError); + } + + this._state.finalize = true; + + if (this._pending === 0 && this._queue.idle() && this._statQueue.idle()) { + this._finalize(); + } + + var self = this; + + return new Promise(function (resolve, reject) { + var errored; + + self._module.on('end', function () { + if (!errored) { + resolve(); + } + }) + + self._module.on('error', function (err) { + errored = true; + reject(err); + }) + }) +}; + +/** + * Sets the module format name used for archiving. + * + * @param {String} format The name of the format. + * @return {this} + */ +Archiver.prototype.setFormat = function (format) { + if (this._format) { + this.emit('error', new ArchiverError('FORMATSET')); + return this; + } + + this._format = format; + + return this; +}; + +/** + * Sets the module used for archiving. + * + * @param {Function} module The function for archiver to interact with. + * @return {this} + */ +Archiver.prototype.setModule = function (module) { + if (this._state.aborted) { + this.emit('error', new ArchiverError('ABORTED')); + return this; + } + + if (this._state.module) { + this.emit('error', new ArchiverError('MODULESET')); + return this; + } + + this._module = module; + this._modulePipe(); + + return this; +}; + +/** + * Appends a symlink to the instance. + * + * This does NOT interact with filesystem and is used for programmatically creating symlinks. + * + * @param {String} filepath The symlink path (within archive). + * @param {String} target The target path (within archive). + * @param {Number} mode Sets the entry permissions. + * @return {this} + */ +Archiver.prototype.symlink = function (filepath, target, mode) { + if (this._state.finalize || this._state.aborted) { + this.emit('error', new ArchiverError('QUEUECLOSED')); + return this; + } + + if (typeof filepath !== 'string' || filepath.length === 0) { + this.emit('error', new ArchiverError('SYMLINKFILEPATHREQUIRED')); + return this; + } + + if (typeof target !== 'string' || target.length === 0) { + this.emit('error', new ArchiverError('SYMLINKTARGETREQUIRED', { filepath: filepath })); + return this; + } + + if (!this._moduleSupports('symlink')) { + this.emit('error', new ArchiverError('SYMLINKNOTSUPPORTED', { filepath: filepath })); + return this; + } + + var data = {}; + data.type = 'symlink'; + data.name = filepath.replace(/\\/g, '/'); + data.linkname = target.replace(/\\/g, '/'); + data.sourceType = 'buffer'; + + if (typeof mode === "number") { + data.mode = mode; + } + + this._entriesCount++; + this._queue.push({ + data: data, + source: Buffer.concat([]) + }); + + return this; +}; + +/** + * Returns the current length (in bytes) that has been emitted. + * + * @return {Number} + */ +Archiver.prototype.pointer = function () { + return this._pointer; +}; + +/** + * Middleware-like helper that has yet to be fully implemented. + * + * @private + * @param {Function} plugin + * @return {this} + */ +Archiver.prototype.use = function (plugin) { + this._streams.push(plugin); + return this; +}; + +module.exports = Archiver; + +/** + * @typedef {Object} CoreOptions + * @global + * @property {Number} [statConcurrency=4] Sets the number of workers used to + * process the internal fs stat queue. + */ + +/** + * @typedef {Object} TransformOptions + * @property {Boolean} [allowHalfOpen=true] If set to false, then the stream + * will automatically end the readable side when the writable side ends and vice + * versa. + * @property {Boolean} [readableObjectMode=false] Sets objectMode for readable + * side of the stream. Has no effect if objectMode is true. + * @property {Boolean} [writableObjectMode=false] Sets objectMode for writable + * side of the stream. Has no effect if objectMode is true. + * @property {Boolean} [decodeStrings=true] Whether or not to decode strings + * into Buffers before passing them to _write(). `Writable` + * @property {String} [encoding=NULL] If specified, then buffers will be decoded + * to strings using the specified encoding. `Readable` + * @property {Number} [highWaterMark=16kb] The maximum number of bytes to store + * in the internal buffer before ceasing to read from the underlying resource. + * `Readable` `Writable` + * @property {Boolean} [objectMode=false] Whether this stream should behave as a + * stream of objects. Meaning that stream.read(n) returns a single value instead + * of a Buffer of size n. `Readable` `Writable` + */ + +/** + * @typedef {Object} EntryData + * @property {String} name Sets the entry name including internal path. + * @property {(String|Date)} [date=NOW()] Sets the entry date. + * @property {Number} [mode=D:0755/F:0644] Sets the entry permissions. + * @property {String} [prefix] Sets a path prefix for the entry name. Useful + * when working with methods like `directory` or `glob`. + * @property {fs.Stats} [stats] Sets the fs stat data for this entry allowing + * for reduction of fs stat calls when stat data is already known. + */ + +/** + * @typedef {Object} ErrorData + * @property {String} message The message of the error. + * @property {String} code The error code assigned to this error. + * @property {String} data Additional data provided for reporting or debugging (where available). + */ + +/** + * @typedef {Object} ProgressData + * @property {Object} entries + * @property {Number} entries.total Number of entries that have been appended. + * @property {Number} entries.processed Number of entries that have been processed. + * @property {Object} fs + * @property {Number} fs.totalBytes Number of bytes that have been appended. Calculated asynchronously and might not be accurate: it growth while entries are added. (based on fs.Stats) + * @property {Number} fs.processedBytes Number of bytes that have been processed. (based on fs.Stats) + */ diff --git a/server/libs/archiver/lib/error.js b/server/libs/archiver/lib/error.js new file mode 100644 index 000000000..6bcb0ae1a --- /dev/null +++ b/server/libs/archiver/lib/error.js @@ -0,0 +1,40 @@ +/** + * Archiver Core + * + * @ignore + * @license [MIT]{@link https://github.com/archiverjs/node-archiver/blob/master/LICENSE} + * @copyright (c) 2012-2014 Chris Talkington, contributors. + */ + +var util = require('util'); + +const ERROR_CODES = { + 'ABORTED': 'archive was aborted', + 'DIRECTORYDIRPATHREQUIRED': 'diretory dirpath argument must be a non-empty string value', + 'DIRECTORYFUNCTIONINVALIDDATA': 'invalid data returned by directory custom data function', + 'ENTRYNAMEREQUIRED': 'entry name must be a non-empty string value', + 'FILEFILEPATHREQUIRED': 'file filepath argument must be a non-empty string value', + 'FINALIZING': 'archive already finalizing', + 'QUEUECLOSED': 'queue closed', + 'NOENDMETHOD': 'no suitable finalize/end method defined by module', + 'DIRECTORYNOTSUPPORTED': 'support for directory entries not defined by module', + 'FORMATSET': 'archive format already set', + 'INPUTSTEAMBUFFERREQUIRED': 'input source must be valid Stream or Buffer instance', + 'MODULESET': 'module already set', + 'SYMLINKNOTSUPPORTED': 'support for symlink entries not defined by module', + 'SYMLINKFILEPATHREQUIRED': 'symlink filepath argument must be a non-empty string value', + 'SYMLINKTARGETREQUIRED': 'symlink target argument must be a non-empty string value', + 'ENTRYNOTSUPPORTED': 'entry not supported' +}; + +function ArchiverError(code, data) { + Error.captureStackTrace(this, this.constructor); + //this.name = this.constructor.name; + this.message = ERROR_CODES[code] || code; + this.code = code; + this.data = data; +} + +util.inherits(ArchiverError, Error); + +exports = module.exports = ArchiverError; \ No newline at end of file diff --git a/server/libs/archiver/lib/plugins/json.js b/server/libs/archiver/lib/plugins/json.js new file mode 100644 index 000000000..713594c3b --- /dev/null +++ b/server/libs/archiver/lib/plugins/json.js @@ -0,0 +1,110 @@ +/** + * JSON Format Plugin + * + * @module plugins/json + * @license [MIT]{@link https://github.com/archiverjs/node-archiver/blob/master/LICENSE} + * @copyright (c) 2012-2014 Chris Talkington, contributors. + */ +var inherits = require('util').inherits; +var Transform = require('readable-stream').Transform; + +var crc32 = require('../../buffer-crc32'); +var util = require('archiver-utils'); + +/** + * @constructor + * @param {(JsonOptions|TransformOptions)} options + */ +var Json = function (options) { + if (!(this instanceof Json)) { + return new Json(options); + } + + options = this.options = util.defaults(options, {}); + + Transform.call(this, options); + + this.supports = { + directory: true, + symlink: true + }; + + this.files = []; +}; + +inherits(Json, Transform); + +/** + * [_transform description] + * + * @private + * @param {Buffer} chunk + * @param {String} encoding + * @param {Function} callback + * @return void + */ +Json.prototype._transform = function (chunk, encoding, callback) { + callback(null, chunk); +}; + +/** + * [_writeStringified description] + * + * @private + * @return void + */ +Json.prototype._writeStringified = function () { + var fileString = JSON.stringify(this.files); + this.write(fileString); +}; + +/** + * [append description] + * + * @param {(Buffer|Stream)} source + * @param {EntryData} data + * @param {Function} callback + * @return void + */ +Json.prototype.append = function (source, data, callback) { + var self = this; + + data.crc32 = 0; + + function onend(err, sourceBuffer) { + if (err) { + callback(err); + return; + } + + data.size = sourceBuffer.length || 0; + data.crc32 = crc32.unsigned(sourceBuffer); + + self.files.push(data); + + callback(null, data); + } + + if (data.sourceType === 'buffer') { + onend(null, source); + } else if (data.sourceType === 'stream') { + util.collectStream(source, onend); + } +}; + +/** + * [finalize description] + * + * @return void + */ +Json.prototype.finalize = function () { + this._writeStringified(); + this.end(); +}; + +module.exports = Json; + +/** + * @typedef {Object} JsonOptions + * @global + */ diff --git a/server/libs/archiver/lib/plugins/zip.js b/server/libs/archiver/lib/plugins/zip.js new file mode 100644 index 000000000..fe5d8ee2f --- /dev/null +++ b/server/libs/archiver/lib/plugins/zip.js @@ -0,0 +1,120 @@ +/** + * ZIP Format Plugin + * + * @module plugins/zip + * @license [MIT]{@link https://github.com/archiverjs/node-archiver/blob/master/LICENSE} + * @copyright (c) 2012-2014 Chris Talkington, contributors. + */ +var engine = require('../../zip-stream'); +var util = require('archiver-utils'); + +/** + * @constructor + * @param {ZipOptions} [options] + * @param {String} [options.comment] Sets the zip archive comment. + * @param {Boolean} [options.forceLocalTime=false] Forces the archive to contain local file times instead of UTC. + * @param {Boolean} [options.forceZip64=false] Forces the archive to contain ZIP64 headers. + * @param {Boolean} [options.namePrependSlash=false] Prepends a forward slash to archive file paths. + * @param {Boolean} [options.store=false] Sets the compression method to STORE. + * @param {Object} [options.zlib] Passed to [zlib]{@link https://nodejs.org/api/zlib.html#zlib_class_options} + */ +var Zip = function (options) { + if (!(this instanceof Zip)) { + return new Zip(options); + } + + options = this.options = util.defaults(options, { + comment: '', + forceUTC: false, + namePrependSlash: false, + store: false + }); + + this.supports = { + directory: true, + symlink: true + }; + + this.engine = new engine(options); +}; + +/** + * @param {(Buffer|Stream)} source + * @param {ZipEntryData} data + * @param {String} data.name Sets the entry name including internal path. + * @param {(String|Date)} [data.date=NOW()] Sets the entry date. + * @param {Number} [data.mode=D:0755/F:0644] Sets the entry permissions. + * @param {String} [data.prefix] Sets a path prefix for the entry name. Useful + * when working with methods like `directory` or `glob`. + * @param {fs.Stats} [data.stats] Sets the fs stat data for this entry allowing + * for reduction of fs stat calls when stat data is already known. + * @param {Boolean} [data.store=ZipOptions.store] Sets the compression method to STORE. + * @param {Function} callback + * @return void + */ +Zip.prototype.append = function (source, data, callback) { + this.engine.entry(source, data, callback); +}; + +/** + * @return void + */ +Zip.prototype.finalize = function () { + this.engine.finalize(); +}; + +/** + * @return this.engine + */ +Zip.prototype.on = function () { + return this.engine.on.apply(this.engine, arguments); +}; + +/** + * @return this.engine + */ +Zip.prototype.pipe = function () { + return this.engine.pipe.apply(this.engine, arguments); +}; + +/** + * @return this.engine + */ +Zip.prototype.unpipe = function () { + return this.engine.unpipe.apply(this.engine, arguments); +}; + +module.exports = Zip; + +/** + * @typedef {Object} ZipOptions + * @global + * @property {String} [comment] Sets the zip archive comment. + * @property {Boolean} [forceLocalTime=false] Forces the archive to contain local file times instead of UTC. + * @property {Boolean} [forceZip64=false] Forces the archive to contain ZIP64 headers. + * @prpperty {Boolean} [namePrependSlash=false] Prepends a forward slash to archive file paths. + * @property {Boolean} [store=false] Sets the compression method to STORE. + * @property {Object} [zlib] Passed to [zlib]{@link https://nodejs.org/api/zlib.html#zlib_class_options} + * to control compression. + * @property {*} [*] See [zip-stream]{@link https://archiverjs.com/zip-stream/ZipStream.html} documentation for current list of properties. + */ + +/** + * @typedef {Object} ZipEntryData + * @global + * @property {String} name Sets the entry name including internal path. + * @property {(String|Date)} [date=NOW()] Sets the entry date. + * @property {Number} [mode=D:0755/F:0644] Sets the entry permissions. + * @property {Boolean} [namePrependSlash=ZipOptions.namePrependSlash] Prepends a forward slash to archive file paths. + * @property {String} [prefix] Sets a path prefix for the entry name. Useful + * when working with methods like `directory` or `glob`. + * @property {fs.Stats} [stats] Sets the fs stat data for this entry allowing + * for reduction of fs stat calls when stat data is already known. + * @property {Boolean} [store=ZipOptions.store] Sets the compression method to STORE. + */ + +/** + * ZipStream Module + * @external ZipStream + * @see {@link https://www.archiverjs.com/zip-stream/ZipStream.html} + */ diff --git a/server/libs/archiver/normalize-path/LICENSE b/server/libs/archiver/normalize-path/LICENSE new file mode 100644 index 000000000..569ca73c0 --- /dev/null +++ b/server/libs/archiver/normalize-path/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2014-2018, Jon Schlinkert. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. \ No newline at end of file diff --git a/server/libs/archiver/normalize-path/index.js b/server/libs/archiver/normalize-path/index.js new file mode 100644 index 000000000..8062f4bf2 --- /dev/null +++ b/server/libs/archiver/normalize-path/index.js @@ -0,0 +1,35 @@ +/*! + * normalize-path + * + * Copyright (c) 2014-2018, Jon Schlinkert. + * Released under the MIT License. + */ + +module.exports = function (path, stripTrailing) { + if (typeof path !== 'string') { + throw new TypeError('expected path to be a string'); + } + + if (path === '\\' || path === '/') return '/'; + + var len = path.length; + if (len <= 1) return path; + + // ensure that win32 namespaces has two leading slashes, so that the path is + // handled properly by the win32 version of path.parse() after being normalized + // https://msdn.microsoft.com/library/windows/desktop/aa365247(v=vs.85).aspx#namespaces + var prefix = ''; + if (len > 4 && path[3] === '\\') { + var ch = path[2]; + if ((ch === '?' || ch === '.') && path.slice(0, 2) === '\\\\') { + path = path.slice(2); + prefix = '//'; + } + } + + var segs = path.split(/[/\\]+/); + if (stripTrailing !== false && segs[segs.length - 1] === '') { + segs.pop(); + } + return prefix + segs.join('/'); +}; \ No newline at end of file diff --git a/server/libs/archiver/readdir-glob/LICENSE b/server/libs/archiver/readdir-glob/LICENSE new file mode 100644 index 000000000..7ba928d30 --- /dev/null +++ b/server/libs/archiver/readdir-glob/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2020 Yann Armelin + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. \ No newline at end of file diff --git a/server/libs/archiver/readdir-glob/index.js b/server/libs/archiver/readdir-glob/index.js new file mode 100644 index 000000000..a188f3acd --- /dev/null +++ b/server/libs/archiver/readdir-glob/index.js @@ -0,0 +1,248 @@ +// +// used by archiver +// Source: https://github.com/Yqnn/node-readdir-glob +// + +module.exports = readdirGlob; + +const fs = require('fs'); +const { EventEmitter } = require('events'); +const { Minimatch } = require('minimatch'); +const { resolve } = require('path'); + +function readdir(dir, strict) { + return new Promise((resolve, reject) => { + fs.readdir(dir, { withFileTypes: true }, (err, files) => { + if (err) { + switch (err.code) { + case 'ENOTDIR': // Not a directory + if (strict) { + reject(err); + } else { + resolve([]); + } + break; + case 'ENOTSUP': // Operation not supported + case 'ENOENT': // No such file or directory + case 'ENAMETOOLONG': // Filename too long + case 'UNKNOWN': + resolve([]); + break; + case 'ELOOP': // Too many levels of symbolic links + default: + reject(err); + break; + } + } else { + resolve(files); + } + }); + }); +} +function stat(file, followSymlinks) { + return new Promise((resolve, reject) => { + const statFunc = followSymlinks ? fs.stat : fs.lstat; + statFunc(file, (err, stats) => { + if (err) { + switch (err.code) { + case 'ENOENT': + if (followSymlinks) { + // Fallback to lstat to handle broken links as files + resolve(stat(file, false)); + } else { + resolve(null); + } + break; + default: + resolve(null); + break; + } + } else { + resolve(stats); + } + }); + }); +} + +async function* exploreWalkAsync(dir, path, followSymlinks, useStat, shouldSkip, strict) { + let files = await readdir(path + dir, strict); + for (const file of files) { + let name = file.name; + if (name === undefined) { + // undefined file.name means the `withFileTypes` options is not supported by node + // we have to call the stat function to know if file is directory or not. + name = file; + useStat = true; + } + const filename = dir + '/' + name; + const relative = filename.slice(1); // Remove the leading / + const absolute = path + '/' + relative; + let stats = null; + if (useStat || followSymlinks) { + stats = await stat(absolute, followSymlinks); + } + if (!stats && file.name !== undefined) { + stats = file; + } + if (stats === null) { + stats = { isDirectory: () => false }; + } + + if (stats.isDirectory()) { + if (!shouldSkip(relative)) { + yield { relative, absolute, stats }; + yield* exploreWalkAsync(filename, path, followSymlinks, useStat, shouldSkip, false); + } + } else { + yield { relative, absolute, stats }; + } + } +} +async function* explore(path, followSymlinks, useStat, shouldSkip) { + yield* exploreWalkAsync('', path, followSymlinks, useStat, shouldSkip, true); +} + + +function readOptions(options) { + return { + pattern: options.pattern, + dot: !!options.dot, + noglobstar: !!options.noglobstar, + matchBase: !!options.matchBase, + nocase: !!options.nocase, + ignore: options.ignore, + skip: options.skip, + + follow: !!options.follow, + stat: !!options.stat, + nodir: !!options.nodir, + mark: !!options.mark, + silent: !!options.silent, + absolute: !!options.absolute + }; +} + +class ReaddirGlob extends EventEmitter { + constructor(cwd, options, cb) { + super(); + if (typeof options === 'function') { + cb = options; + options = null; + } + + this.options = readOptions(options || {}); + + this.matchers = []; + if (this.options.pattern) { + const matchers = Array.isArray(this.options.pattern) ? this.options.pattern : [this.options.pattern]; + this.matchers = matchers.map(m => + new Minimatch(m, { + dot: this.options.dot, + noglobstar: this.options.noglobstar, + matchBase: this.options.matchBase, + nocase: this.options.nocase + }) + ); + } + + this.ignoreMatchers = []; + if (this.options.ignore) { + const ignorePatterns = Array.isArray(this.options.ignore) ? this.options.ignore : [this.options.ignore]; + this.ignoreMatchers = ignorePatterns.map(ignore => + new Minimatch(ignore, { dot: true }) + ); + } + + this.skipMatchers = []; + if (this.options.skip) { + const skipPatterns = Array.isArray(this.options.skip) ? this.options.skip : [this.options.skip]; + this.skipMatchers = skipPatterns.map(skip => + new Minimatch(skip, { dot: true }) + ); + } + + this.iterator = explore(resolve(cwd || '.'), this.options.follow, this.options.stat, this._shouldSkipDirectory.bind(this)); + this.paused = false; + this.inactive = false; + this.aborted = false; + + if (cb) { + this._matches = []; + this.on('match', match => this._matches.push(this.options.absolute ? match.absolute : match.relative)); + this.on('error', err => cb(err)); + this.on('end', () => cb(null, this._matches)); + } + + setTimeout(() => this._next(), 0); + } + + _shouldSkipDirectory(relative) { + //console.log(relative, this.skipMatchers.some(m => m.match(relative))); + return this.skipMatchers.some(m => m.match(relative)); + } + + _fileMatches(relative, isDirectory) { + const file = relative + (isDirectory ? '/' : ''); + return (this.matchers.length === 0 || this.matchers.some(m => m.match(file))) + && !this.ignoreMatchers.some(m => m.match(file)) + && (!this.options.nodir || !isDirectory); + } + + _next() { + if (!this.paused && !this.aborted) { + this.iterator.next() + .then((obj) => { + if (!obj.done) { + const isDirectory = obj.value.stats.isDirectory(); + if (this._fileMatches(obj.value.relative, isDirectory)) { + let relative = obj.value.relative; + let absolute = obj.value.absolute; + if (this.options.mark && isDirectory) { + relative += '/'; + absolute += '/'; + } + if (this.options.stat) { + this.emit('match', { relative, absolute, stat: obj.value.stats }); + } else { + this.emit('match', { relative, absolute }); + } + } + this._next(this.iterator); + } else { + this.emit('end'); + } + }) + .catch((err) => { + this.abort(); + this.emit('error', err); + if (!err.code && !this.options.silent) { + console.error(err); + } + }); + } else { + this.inactive = true; + } + } + + abort() { + this.aborted = true; + } + + pause() { + this.paused = true; + } + + resume() { + this.paused = false; + if (this.inactive) { + this.inactive = false; + this._next(); + } + } +} + + +function readdirGlob(pattern, options, cb) { + return new ReaddirGlob(pattern, options, cb); +} +readdirGlob.ReaddirGlob = ReaddirGlob; \ No newline at end of file diff --git a/server/libs/archiver/zip-stream/LICENSE b/server/libs/archiver/zip-stream/LICENSE new file mode 100644 index 000000000..56420a6a0 --- /dev/null +++ b/server/libs/archiver/zip-stream/LICENSE @@ -0,0 +1,22 @@ +Copyright (c) 2014 Chris Talkington, contributors. + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/server/libs/archiver/zip-stream/index.js b/server/libs/archiver/zip-stream/index.js new file mode 100644 index 000000000..de182f3bf --- /dev/null +++ b/server/libs/archiver/zip-stream/index.js @@ -0,0 +1,187 @@ +/** + * ZipStream + * + * @ignore + * @license [MIT]{@link https://github.com/archiverjs/node-zip-stream/blob/master/LICENSE} + * @copyright (c) 2014 Chris Talkington, contributors. + */ +var inherits = require('util').inherits; + +var ZipArchiveOutputStream = require('../compress-commons').ZipArchiveOutputStream; +var ZipArchiveEntry = require('../compress-commons').ZipArchiveEntry; + +var util = require('archiver-utils'); + +/** + * @constructor + * @extends external:ZipArchiveOutputStream + * @param {Object} [options] + * @param {String} [options.comment] Sets the zip archive comment. + * @param {Boolean} [options.forceLocalTime=false] Forces the archive to contain local file times instead of UTC. + * @param {Boolean} [options.forceZip64=false] Forces the archive to contain ZIP64 headers. + * @param {Boolean} [options.store=false] Sets the compression method to STORE. + * @param {Object} [options.zlib] Passed to [zlib]{@link https://nodejs.org/api/zlib.html#zlib_class_options} + * to control compression. + */ +var ZipStream = module.exports = function (options) { + if (!(this instanceof ZipStream)) { + return new ZipStream(options); + } + + options = this.options = options || {}; + options.zlib = options.zlib || {}; + + ZipArchiveOutputStream.call(this, options); + + if (typeof options.level === 'number' && options.level >= 0) { + options.zlib.level = options.level; + delete options.level; + } + + if (!options.forceZip64 && typeof options.zlib.level === 'number' && options.zlib.level === 0) { + options.store = true; + } + + options.namePrependSlash = options.namePrependSlash || false; + + if (options.comment && options.comment.length > 0) { + this.setComment(options.comment); + } +}; + +inherits(ZipStream, ZipArchiveOutputStream); + +/** + * Normalizes entry data with fallbacks for key properties. + * + * @private + * @param {Object} data + * @return {Object} + */ +ZipStream.prototype._normalizeFileData = function (data) { + data = util.defaults(data, { + type: 'file', + name: null, + namePrependSlash: this.options.namePrependSlash, + linkname: null, + date: null, + mode: null, + store: this.options.store, + comment: '' + }); + + var isDir = data.type === 'directory'; + var isSymlink = data.type === 'symlink'; + + if (data.name) { + data.name = util.sanitizePath(data.name); + + if (!isSymlink && data.name.slice(-1) === '/') { + isDir = true; + data.type = 'directory'; + } else if (isDir) { + data.name += '/'; + } + } + + if (isDir || isSymlink) { + data.store = true; + } + + data.date = util.dateify(data.date); + + return data; +}; + +/** + * Appends an entry given an input source (text string, buffer, or stream). + * + * @param {(Buffer|Stream|String)} source The input source. + * @param {Object} data + * @param {String} data.name Sets the entry name including internal path. + * @param {String} [data.comment] Sets the entry comment. + * @param {(String|Date)} [data.date=NOW()] Sets the entry date. + * @param {Number} [data.mode=D:0755/F:0644] Sets the entry permissions. + * @param {Boolean} [data.store=options.store] Sets the compression method to STORE. + * @param {String} [data.type=file] Sets the entry type. Defaults to `directory` + * if name ends with trailing slash. + * @param {Function} callback + * @return this + */ +ZipStream.prototype.entry = function (source, data, callback) { + if (typeof callback !== 'function') { + callback = this._emitErrorCallback.bind(this); + } + + data = this._normalizeFileData(data); + + if (data.type !== 'file' && data.type !== 'directory' && data.type !== 'symlink') { + callback(new Error(data.type + ' entries not currently supported')); + return; + } + + if (typeof data.name !== 'string' || data.name.length === 0) { + callback(new Error('entry name must be a non-empty string value')); + return; + } + + if (data.type === 'symlink' && typeof data.linkname !== 'string') { + callback(new Error('entry linkname must be a non-empty string value when type equals symlink')); + return; + } + + var entry = new ZipArchiveEntry(data.name); + entry.setTime(data.date, this.options.forceLocalTime); + + if (data.namePrependSlash) { + entry.setName(data.name, true); + } + + if (data.store) { + entry.setMethod(0); + } + + if (data.comment.length > 0) { + entry.setComment(data.comment); + } + + if (data.type === 'symlink' && typeof data.mode !== 'number') { + data.mode = 40960; // 0120000 + } + + if (typeof data.mode === 'number') { + if (data.type === 'symlink') { + data.mode |= 40960; + } + + entry.setUnixMode(data.mode); + } + + if (data.type === 'symlink' && typeof data.linkname === 'string') { + source = Buffer.from(data.linkname); + } + + return ZipArchiveOutputStream.prototype.entry.call(this, entry, source, callback); +}; + +/** + * Finalizes the instance and prevents further appending to the archive + * structure (queue will continue til drained). + * + * @return void + */ +ZipStream.prototype.finalize = function () { + this.finish(); +}; + +/** + * Returns the current number of bytes written to this stream. + * @function ZipStream#getBytesWritten + * @returns {Number} + */ + +/** + * Compress Commons ZipArchiveOutputStream + * @external ZipArchiveOutputStream + * @see {@link https://github.com/archiverjs/node-compress-commons} + */ \ No newline at end of file diff --git a/server/managers/BackupManager.js b/server/managers/BackupManager.js index a66d69996..1a6288eae 100644 --- a/server/managers/BackupManager.js +++ b/server/managers/BackupManager.js @@ -2,7 +2,7 @@ const Path = require('path') const cron = require('../libs/nodeCron') const fs = require('../libs/fsExtra') -const archiver = require('archiver') +const archiver = require('../libs/archiver') const StreamZip = require('../libs/nodeStreamZip') // Utils diff --git a/server/managers/DownloadManager.js b/server/managers/DownloadManager.js index 66f660c8f..50a933e62 100644 --- a/server/managers/DownloadManager.js +++ b/server/managers/DownloadManager.js @@ -1,6 +1,6 @@ const Path = require('path') const fs = require('../libs/fsExtra') -const archiver = require('archiver') +const archiver = require('../libs/archiver') const workerThreads = require('worker_threads') const Logger = require('../Logger') From bca2cfda13ee3139001a132872fc3806a97d073c Mon Sep 17 00:00:00 2001 From: advplyr Date: Thu, 7 Jul 2022 17:25:52 -0500 Subject: [PATCH 010/100] Update:Remove log listener for root user & only set when on logger config page --- client/pages/config/log.vue | 1 + server/Server.js | 14 +++++--------- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/client/pages/config/log.vue b/client/pages/config/log.vue index 50ccc3e93..f621b9f26 100644 --- a/client/pages/config/log.vue +++ b/client/pages/config/log.vue @@ -161,6 +161,7 @@ export default { }, beforeDestroy() { if (!this.$root.socket) return + this.$root.socket.emit('remove_log_listener') this.$root.socket.off('daily_logs', this.dailyLogsLoaded) this.$root.socket.off('log', this.logEvtReceived) } diff --git a/server/Server.js b/server/Server.js index c2895de96..0d75eaeaa 100644 --- a/server/Server.js +++ b/server/Server.js @@ -278,6 +278,7 @@ class Server { // Logs socket.on('set_log_listener', (level) => Logger.addSocketListener(socket, level)) + socket.on('remove_log_listener', () => Logger.removeSocketListener(socket.id)) socket.on('fetch_daily_logs', () => this.logManager.socketRequestDailyLogs(socket)) socket.on('ping', () => { @@ -287,21 +288,21 @@ class Server { socket.emit('pong') }) - socket.on('disconnect', () => { + socket.on('disconnect', (reason) => { Logger.removeSocketListener(socket.id) var _client = this.clients[socket.id] if (!_client) { - Logger.warn('[Server] Socket disconnect, no client ' + socket.id) + Logger.warn(`[Server] Socket ${socket.id} disconnect, no client (Reason: ${reason})`) } else if (!_client.user) { - Logger.info('[Server] Unauth socket disconnected ' + socket.id) + Logger.info(`[Server] Unauth socket ${socket.id} disconnected (Reason: ${reason})`) delete this.clients[socket.id] } else { Logger.debug('[Server] User Offline ' + _client.user.username) this.io.emit('user_offline', _client.user.toJSONForPublic(this.playbackSessionManager.sessions, this.db.libraryItems)) const disconnectTime = Date.now() - _client.connected_at - Logger.info(`[Server] Socket ${socket.id} disconnected from client "${_client.user.username}" after ${disconnectTime}ms`) + Logger.info(`[Server] Socket ${socket.id} disconnected from client "${_client.user.username}" after ${disconnectTime}ms (Reason: ${reason})`) delete this.clients[socket.id] } }) @@ -471,11 +472,6 @@ class Server { initialPayload.usersOnline = this.usersOnline } client.socket.emit('init', initialPayload) - - // Setup log listener for root user - if (user.type === 'root') { - Logger.addSocketListener(socket, this.db.serverSettings.logLevel || 0) - } } async stop() { From 3c5bf376b5331bf61363617b41161f819940777b Mon Sep 17 00:00:00 2001 From: advplyr Date: Fri, 8 Jul 2022 18:11:09 -0500 Subject: [PATCH 011/100] Remove archiver-utils dependency --- package-lock.json | 1125 +++++++++++--- package.json | 2 +- .../archiverUtils/balancedMatch/LICENSE | 21 + .../archiverUtils/balancedMatch/index.js | 81 + .../archiverUtils/braceExpansion/LICENSE | 21 + .../archiverUtils/braceExpansion/index.js | 235 +++ server/libs/archiver/archiverUtils/file.js | 209 +++ .../archiver/archiverUtils/fsRealpath/LICENSE | 43 + .../archiverUtils/fsRealpath/index.js | 54 + .../archiver/archiverUtils/fsRealpath/old.js | 302 ++++ .../libs/archiver/archiverUtils/glob/LICENSE | 15 + .../archiver/archiverUtils/glob/common.js | 240 +++ .../libs/archiver/archiverUtils/glob/index.js | 789 ++++++++++ .../libs/archiver/archiverUtils/glob/sync.js | 483 ++++++ server/libs/archiver/archiverUtils/index.js | 162 ++ .../archiver/archiverUtils/inflight/LICENSE | 15 + .../archiver/archiverUtils/inflight/index.js | 54 + .../archiver/archiverUtils/lazystream/LICENSE | 22 + .../archiverUtils/lazystream/index.js | 57 + .../readable-stream/lib/_stream_duplex.js | 133 ++ .../lib/_stream_passthrough.js | 47 + .../readable-stream/lib/_stream_readable.js | 1023 +++++++++++++ .../readable-stream/lib/_stream_transform.js | 215 +++ .../readable-stream/lib/_stream_writable.js | 689 +++++++++ .../lib/internal/streams/BufferList.js | 79 + .../lib/internal/streams/destroy.js | 75 + .../lib/internal/streams/stream-browser.js | 1 + .../lib/internal/streams/stream.js | 1 + .../lazystream/readable-stream/passthrough.js | 1 + .../lazystream/readable-stream/readable.js | 19 + .../archiverUtils/lodash.difference/LICENSE | 47 + .../archiverUtils/lodash.difference/index.js | 1170 +++++++++++++++ .../archiverUtils/lodash.flatten/LICENSE | 47 + .../archiverUtils/lodash.flatten/index.js | 349 +++++ .../lodash.isplainobject/LICENSE | 47 + .../lodash.isplainobject/index.js | 139 ++ .../archiverUtils/lodash.union/LICENSE | 47 + .../archiverUtils/lodash.union/index.js | 1181 +++++++++++++++ .../archiver/archiverUtils/minimatch/LICENSE | 15 + .../archiver/archiverUtils/minimatch/index.js | 909 ++++++++++++ .../archiverUtils/readableStream/LICENSE | 47 + .../readableStream/_stream_duplex.js | 3 + .../readableStream/_stream_passthrough.js | 3 + .../readableStream/_stream_readable.js | 3 + .../readableStream/_stream_transform.js | 3 + .../readableStream/_stream_writable.js | 3 + .../archiverUtils/readableStream/index.js | 67 + .../internal/streams/add-abort-signal.js | 52 + .../internal/streams/buffer_list.js | 178 +++ .../internal/streams/compose.js | 161 ++ .../internal/streams/destroy.js | 332 +++++ .../readableStream/internal/streams/duplex.js | 128 ++ .../internal/streams/duplexify.js | 422 ++++++ .../internal/streams/end-of-stream.js | 258 ++++ .../readableStream/internal/streams/from.js | 108 ++ .../internal/streams/lazy_transform.js | 58 + .../readableStream/internal/streams/legacy.js | 100 ++ .../internal/streams/operators.js | 537 +++++++ .../internal/streams/passthrough.js | 42 + .../internal/streams/pipeline.js | 415 ++++++ .../internal/streams/readable.js | 1314 +++++++++++++++++ .../readableStream/internal/streams/state.js | 33 + .../internal/streams/transform.js | 175 +++ .../readableStream/internal/streams/utils.js | 328 ++++ .../internal/streams/writable.js | 860 +++++++++++ .../readableStream/internal/validators.js | 246 +++ .../readableStream/ours/browser.js | 36 + .../readableStream/ours/errors.js | 380 +++++ .../readableStream/ours/primordials.js | 130 ++ .../archiverUtils/readableStream/ours/util.js | 149 ++ .../archiverUtils/readableStream/stream.js | 149 ++ .../readableStream/stream/promises.js | 43 + .../archiver/archiverUtils/safeBuffer/LICENSE | 21 + .../archiverUtils/safeBuffer/index.js | 65 + .../archiverUtils/stringDecoder/LICENSE | 47 + .../archiverUtils/stringDecoder/index.js | 295 ++++ .../archiver/archiverUtils/wrappy/LICENSE | 15 + .../archiver/archiverUtils/wrappy/index.js | 29 + .../archivers/archive-output-stream.js | 24 +- .../archiver/compress-commons/util/index.js | 6 +- .../archiver/crc32-stream/crc32-stream.js | 3 +- server/libs/archiver/lib/core.js | 4 +- server/libs/archiver/lib/plugins/json.js | 4 +- server/libs/archiver/lib/plugins/zip.js | 2 +- server/libs/archiver/readdir-glob/index.js | 2 +- server/libs/archiver/zip-stream/index.js | 2 +- 86 files changed, 17236 insertions(+), 210 deletions(-) create mode 100644 server/libs/archiver/archiverUtils/balancedMatch/LICENSE create mode 100644 server/libs/archiver/archiverUtils/balancedMatch/index.js create mode 100644 server/libs/archiver/archiverUtils/braceExpansion/LICENSE create mode 100644 server/libs/archiver/archiverUtils/braceExpansion/index.js create mode 100644 server/libs/archiver/archiverUtils/file.js create mode 100644 server/libs/archiver/archiverUtils/fsRealpath/LICENSE create mode 100644 server/libs/archiver/archiverUtils/fsRealpath/index.js create mode 100644 server/libs/archiver/archiverUtils/fsRealpath/old.js create mode 100644 server/libs/archiver/archiverUtils/glob/LICENSE create mode 100644 server/libs/archiver/archiverUtils/glob/common.js create mode 100644 server/libs/archiver/archiverUtils/glob/index.js create mode 100644 server/libs/archiver/archiverUtils/glob/sync.js create mode 100644 server/libs/archiver/archiverUtils/index.js create mode 100644 server/libs/archiver/archiverUtils/inflight/LICENSE create mode 100644 server/libs/archiver/archiverUtils/inflight/index.js create mode 100644 server/libs/archiver/archiverUtils/lazystream/LICENSE create mode 100644 server/libs/archiver/archiverUtils/lazystream/index.js create mode 100644 server/libs/archiver/archiverUtils/lazystream/readable-stream/lib/_stream_duplex.js create mode 100644 server/libs/archiver/archiverUtils/lazystream/readable-stream/lib/_stream_passthrough.js create mode 100644 server/libs/archiver/archiverUtils/lazystream/readable-stream/lib/_stream_readable.js create mode 100644 server/libs/archiver/archiverUtils/lazystream/readable-stream/lib/_stream_transform.js create mode 100644 server/libs/archiver/archiverUtils/lazystream/readable-stream/lib/_stream_writable.js create mode 100644 server/libs/archiver/archiverUtils/lazystream/readable-stream/lib/internal/streams/BufferList.js create mode 100644 server/libs/archiver/archiverUtils/lazystream/readable-stream/lib/internal/streams/destroy.js create mode 100644 server/libs/archiver/archiverUtils/lazystream/readable-stream/lib/internal/streams/stream-browser.js create mode 100644 server/libs/archiver/archiverUtils/lazystream/readable-stream/lib/internal/streams/stream.js create mode 100644 server/libs/archiver/archiverUtils/lazystream/readable-stream/passthrough.js create mode 100644 server/libs/archiver/archiverUtils/lazystream/readable-stream/readable.js create mode 100644 server/libs/archiver/archiverUtils/lodash.difference/LICENSE create mode 100644 server/libs/archiver/archiverUtils/lodash.difference/index.js create mode 100644 server/libs/archiver/archiverUtils/lodash.flatten/LICENSE create mode 100644 server/libs/archiver/archiverUtils/lodash.flatten/index.js create mode 100644 server/libs/archiver/archiverUtils/lodash.isplainobject/LICENSE create mode 100644 server/libs/archiver/archiverUtils/lodash.isplainobject/index.js create mode 100644 server/libs/archiver/archiverUtils/lodash.union/LICENSE create mode 100644 server/libs/archiver/archiverUtils/lodash.union/index.js create mode 100644 server/libs/archiver/archiverUtils/minimatch/LICENSE create mode 100644 server/libs/archiver/archiverUtils/minimatch/index.js create mode 100644 server/libs/archiver/archiverUtils/readableStream/LICENSE create mode 100644 server/libs/archiver/archiverUtils/readableStream/_stream_duplex.js create mode 100644 server/libs/archiver/archiverUtils/readableStream/_stream_passthrough.js create mode 100644 server/libs/archiver/archiverUtils/readableStream/_stream_readable.js create mode 100644 server/libs/archiver/archiverUtils/readableStream/_stream_transform.js create mode 100644 server/libs/archiver/archiverUtils/readableStream/_stream_writable.js create mode 100644 server/libs/archiver/archiverUtils/readableStream/index.js create mode 100644 server/libs/archiver/archiverUtils/readableStream/internal/streams/add-abort-signal.js create mode 100644 server/libs/archiver/archiverUtils/readableStream/internal/streams/buffer_list.js create mode 100644 server/libs/archiver/archiverUtils/readableStream/internal/streams/compose.js create mode 100644 server/libs/archiver/archiverUtils/readableStream/internal/streams/destroy.js create mode 100644 server/libs/archiver/archiverUtils/readableStream/internal/streams/duplex.js create mode 100644 server/libs/archiver/archiverUtils/readableStream/internal/streams/duplexify.js create mode 100644 server/libs/archiver/archiverUtils/readableStream/internal/streams/end-of-stream.js create mode 100644 server/libs/archiver/archiverUtils/readableStream/internal/streams/from.js create mode 100644 server/libs/archiver/archiverUtils/readableStream/internal/streams/lazy_transform.js create mode 100644 server/libs/archiver/archiverUtils/readableStream/internal/streams/legacy.js create mode 100644 server/libs/archiver/archiverUtils/readableStream/internal/streams/operators.js create mode 100644 server/libs/archiver/archiverUtils/readableStream/internal/streams/passthrough.js create mode 100644 server/libs/archiver/archiverUtils/readableStream/internal/streams/pipeline.js create mode 100644 server/libs/archiver/archiverUtils/readableStream/internal/streams/readable.js create mode 100644 server/libs/archiver/archiverUtils/readableStream/internal/streams/state.js create mode 100644 server/libs/archiver/archiverUtils/readableStream/internal/streams/transform.js create mode 100644 server/libs/archiver/archiverUtils/readableStream/internal/streams/utils.js create mode 100644 server/libs/archiver/archiverUtils/readableStream/internal/streams/writable.js create mode 100644 server/libs/archiver/archiverUtils/readableStream/internal/validators.js create mode 100644 server/libs/archiver/archiverUtils/readableStream/ours/browser.js create mode 100644 server/libs/archiver/archiverUtils/readableStream/ours/errors.js create mode 100644 server/libs/archiver/archiverUtils/readableStream/ours/primordials.js create mode 100644 server/libs/archiver/archiverUtils/readableStream/ours/util.js create mode 100644 server/libs/archiver/archiverUtils/readableStream/stream.js create mode 100644 server/libs/archiver/archiverUtils/readableStream/stream/promises.js create mode 100644 server/libs/archiver/archiverUtils/safeBuffer/LICENSE create mode 100644 server/libs/archiver/archiverUtils/safeBuffer/index.js create mode 100644 server/libs/archiver/archiverUtils/stringDecoder/LICENSE create mode 100644 server/libs/archiver/archiverUtils/stringDecoder/index.js create mode 100644 server/libs/archiver/archiverUtils/wrappy/LICENSE create mode 100644 server/libs/archiver/archiverUtils/wrappy/index.js diff --git a/package-lock.json b/package-lock.json index b07681898..83f891ccb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,8 +1,945 @@ { "name": "audiobookshelf", "version": "2.0.23", - "lockfileVersion": 1, + "lockfileVersion": 2, "requires": true, + "packages": { + "": { + "name": "audiobookshelf", + "version": "2.0.23", + "license": "GPL-3.0", + "dependencies": { + "axios": "^0.26.1", + "express": "^4.17.1", + "graceful-fs": "^4.2.10", + "htmlparser2": "^8.0.1", + "socket.io": "^4.4.1", + "xml2js": "^0.4.23" + }, + "bin": { + "audiobookshelf": "prod.js" + } + }, + "node_modules/@types/component-emitter": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/@types/component-emitter/-/component-emitter-1.2.11.tgz", + "integrity": "sha512-SRXjM+tfsSlA9VuG8hGO2nft2p8zjXCK1VcC6N4NXbBbYbSia9kzCChYQajIjzIqOOOuh5Ock6MmV2oux4jDZQ==" + }, + "node_modules/@types/cookie": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.4.1.tgz", + "integrity": "sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==" + }, + "node_modules/@types/cors": { + "version": "2.8.12", + "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.12.tgz", + "integrity": "sha512-vt+kDhq/M2ayberEtJcIN/hxXy1Pk+59g2FV/ZQceeaTyCtCucjL2Q7FXlFjtWn4n15KCr1NE2lNNFhp0lEThw==" + }, + "node_modules/@types/node": { + "version": "17.0.41", + "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.41.tgz", + "integrity": "sha512-xA6drNNeqb5YyV5fO3OAEsnXLfO7uF0whiOfPTz5AeDo8KeZFmODKnvwPymMNO8qE/an8pVY/O50tig2SQCrGw==" + }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" + }, + "node_modules/axios": { + "version": "0.26.1", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.26.1.tgz", + "integrity": "sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==", + "dependencies": { + "follow-redirects": "^1.14.8" + } + }, + "node_modules/base64id": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz", + "integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==", + "engines": { + "node": "^4.5.0 || >= 5.9" + } + }, + "node_modules/body-parser": { + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.0.tgz", + "integrity": "sha512-DfJ+q6EPcGKZD1QWUjSpqp+Q7bDQTsQIF4zfUAtZ6qk+H/3/QRhg9CEp39ss+/T2vw0+HaidC0ecJj/DRLIaKg==", + "dependencies": { + "bytes": "3.1.2", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.10.3", + "raw-body": "2.5.1", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dependencies": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/component-emitter": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", + "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==" + }, + "node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/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==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", + "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" + }, + "node_modules/cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "dependencies": { + "object-assign": "^4", + "vary": "^1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/dom-serializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", + "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "entities": "^4.2.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ] + }, + "node_modules/domhandler": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", + "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", + "dependencies": { + "domelementtype": "^2.3.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/domutils": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.0.1.tgz", + "integrity": "sha512-z08c1l761iKhDFtfXO04C7kTdPBLi41zwOZl00WS8b5eiaebNpY00HKbztwBq+e3vyqWNwWF3mP9YLUeqIrF+Q==", + "dependencies": { + "dom-serializer": "^2.0.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.1" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" + }, + "node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/engine.io": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.2.0.tgz", + "integrity": "sha512-4KzwW3F3bk+KlzSOY57fj/Jx6LyRQ1nbcyIadehl+AnXjKT7gDO0ORdRi/84ixvMKTym6ZKuxvbzN62HDDU1Lg==", + "dependencies": { + "@types/cookie": "^0.4.1", + "@types/cors": "^2.8.12", + "@types/node": ">=10.0.0", + "accepts": "~1.3.4", + "base64id": "2.0.0", + "cookie": "~0.4.1", + "cors": "~2.8.5", + "debug": "~4.3.1", + "engine.io-parser": "~5.0.3", + "ws": "~8.2.3" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/engine.io-parser": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.0.4.tgz", + "integrity": "sha512-+nVFp+5z1E3HcToEnO7ZIj3g+3k9389DvWtvJZz0T6/eOCPIyyxehFcedoYrZQrp0LgQbD9pPXhpMBKMd5QURg==", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/engine.io/node_modules/cookie": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", + "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/engine.io/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/engine.io/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/entities": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.3.0.tgz", + "integrity": "sha512-/iP1rZrSEJ0DTlPiX+jbzlA3eVkY/e8L8SozroF395fIqE3TYF/Nz7YOMAawta+vLmyJ/hkGNNPcSbMADCCXbg==", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/express": { + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.18.1.tgz", + "integrity": "sha512-zZBcOX9TfehHQhtupq57OF8lFZ3UZi08Y97dwFCkD8p9d/d2Y3M+ykKcwaMDEL+4qyUolgBDX6AblpR3fL212Q==", + "dependencies": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.0", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.5.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.2.0", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.7", + "qs": "6.10.3", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.18.0", + "serve-static": "1.15.0", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/finalhandler": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", + "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "statuses": "2.0.1", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/follow-redirects": { + "version": "1.15.1", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.1.tgz", + "integrity": "sha512-yLAMQs+k0b2m7cVxpS1VKJVvoz7SS9Td1zss3XRwXj+ZDH00RJgnuLx7E44wx02kQLrdM3aOOy+FpzS7+8OizA==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + }, + "node_modules/get-intrinsic": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", + "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", + "dependencies": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" + }, + "node_modules/has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dependencies": { + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/htmlparser2": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.1.tgz", + "integrity": "sha512-4lVbmc1diZC7GUJQtRQ5yBAeUCL1exyMwmForWkRLnwyzWBFxN633SALPMGYaWZvKe9j1pRZJpauvmxENSp/EA==", + "funding": [ + "https://github.com/fb55/htmlparser2?sponsor=1", + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "domutils": "^3.0.1", + "entities": "^4.3.0" + } + }, + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz", + "integrity": "sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/qs": { + "version": "6.10.3", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.3.tgz", + "integrity": "sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ==", + "dependencies": { + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", + "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "node_modules/sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" + }, + "node_modules/send": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", + "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "node_modules/serve-static": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", + "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", + "dependencies": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.18.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + }, + "node_modules/side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "dependencies": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/socket.io": { + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.5.1.tgz", + "integrity": "sha512-0y9pnIso5a9i+lJmsCdtmTTgJFFSvNQKDnPQRz28mGNnxbmqYg2QPtJTLFxhymFZhAIn50eHAKzJeiNaKr+yUQ==", + "dependencies": { + "accepts": "~1.3.4", + "base64id": "~2.0.0", + "debug": "~4.3.2", + "engine.io": "~6.2.0", + "socket.io-adapter": "~2.4.0", + "socket.io-parser": "~4.0.4" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/socket.io-adapter": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.4.0.tgz", + "integrity": "sha512-W4N+o69rkMEGVuk2D/cvca3uYsvGlMwsySWV447y99gUPghxq42BxqLNMndb+a1mm/5/7NeXVQS7RLa2XyXvYg==" + }, + "node_modules/socket.io-parser": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.0.4.tgz", + "integrity": "sha512-t+b0SS+IxG7Rxzda2EVvyBZbvFPBCjJoyHuE0P//7OAsN23GItzDRdWa6ALxZI/8R5ygK7jAR6t028/z+7295g==", + "dependencies": { + "@types/component-emitter": "^1.2.10", + "component-emitter": "~1.3.0", + "debug": "~4.3.1" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/socket.io-parser/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/socket.io-parser/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/socket.io/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/socket.io/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/ws": { + "version": "8.2.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.2.3.tgz", + "integrity": "sha512-wBuoj1BDpC6ZQ1B7DWQBYVLphPWkm8i9Y0/3YdHjHKHiohOJ1ws+3OccDWtH+PoC9DZD5WOTrJvNbWvjS6JWaA==", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xml2js": { + "version": "0.4.23", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.23.tgz", + "integrity": "sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug==", + "dependencies": { + "sax": ">=0.6.0", + "xmlbuilder": "~11.0.0" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/xmlbuilder": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", + "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", + "engines": { + "node": ">=4.0" + } + } + }, "dependencies": { "@types/component-emitter": { "version": "1.2.11", @@ -33,23 +970,6 @@ "negotiator": "0.6.3" } }, - "archiver-utils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-2.1.0.tgz", - "integrity": "sha512-bEL/yUb/fNNiNTuUz979Z0Yg5L+LzLxGJz8x79lYmR54fmTIb6ob/hNQgkQnIUDWIFjZVQwl9Xs356I6BAMHfw==", - "requires": { - "glob": "^7.1.4", - "graceful-fs": "^4.2.0", - "lazystream": "^1.0.0", - "lodash.defaults": "^4.2.0", - "lodash.difference": "^4.5.0", - "lodash.flatten": "^4.4.0", - "lodash.isplainobject": "^4.0.6", - "lodash.union": "^4.6.0", - "normalize-path": "^3.0.0", - "readable-stream": "^2.0.0" - } - }, "array-flatten": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", @@ -63,11 +983,6 @@ "follow-redirects": "^1.14.8" } }, - "balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" - }, "base64id": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz", @@ -92,15 +1007,6 @@ "unpipe": "1.0.0" } }, - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, "bytes": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", @@ -120,11 +1026,6 @@ "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==" }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" - }, "content-disposition": { "version": "0.5.4", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", @@ -148,11 +1049,6 @@ "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" }, - "core-util-is": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", - "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" - }, "cors": { "version": "2.8.5", "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", @@ -347,11 +1243,6 @@ "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==" }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" - }, "function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", @@ -367,19 +1258,6 @@ "has-symbols": "^1.0.1" } }, - "glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, "graceful-fs": { "version": "4.2.10", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", @@ -429,15 +1307,6 @@ "safer-buffer": ">= 2.1.2 < 3" } }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, "inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", @@ -448,44 +1317,6 @@ "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==" }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" - }, - "lazystream": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.1.tgz", - "integrity": "sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw==", - "requires": { - "readable-stream": "^2.0.5" - } - }, - "lodash.defaults": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", - "integrity": "sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==" - }, - "lodash.difference": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.difference/-/lodash.difference-4.5.0.tgz", - "integrity": "sha512-dS2j+W26TQ7taQBGN8Lbbq04ssV3emRw4NY58WErlTO29pIqS0HmoT5aJ9+TUQ1N3G+JOZSji4eugsWwGp9yPA==" - }, - "lodash.flatten": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz", - "integrity": "sha512-C5N2Z3DgnnKr0LOpv/hKCgKdb7ZZwafIrsesve6lmzvZIRZRGaZ/l6Q8+2W7NaT+ZwO3fFlSCzCzrDCFdJfZ4g==" - }, - "lodash.isplainobject": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", - "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==" - }, - "lodash.union": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/lodash.union/-/lodash.union-4.6.0.tgz", - "integrity": "sha512-c4pB2CdGrGdjMKYLA+XiRDO7Y0PRQbm/Gzg8qMj+QH+pFVAoTp5sBpO0odL3FjoPCGjK96p6qsP+yQoiLoOBcw==" - }, "media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", @@ -519,14 +1350,6 @@ "mime-db": "1.52.0" } }, - "minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "requires": { - "brace-expansion": "^1.1.7" - } - }, "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", @@ -537,11 +1360,6 @@ "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==" }, - "normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==" - }, "object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -560,34 +1378,16 @@ "ee-first": "1.1.1" } }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "requires": { - "wrappy": "1" - } - }, "parseurl": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==" - }, "path-to-regexp": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" }, - "process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" - }, "proxy-addr": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", @@ -621,27 +1421,6 @@ "unpipe": "1.0.0" } }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - }, - "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==" - } - } - }, "safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", @@ -773,21 +1552,6 @@ "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==" }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - }, - "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==" - } - } - }, "toidentifier": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", @@ -807,11 +1571,6 @@ "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": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" - }, "utils-merge": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", @@ -822,15 +1581,11 @@ "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" - }, "ws": { "version": "8.2.3", "resolved": "https://registry.npmjs.org/ws/-/ws-8.2.3.tgz", - "integrity": "sha512-wBuoj1BDpC6ZQ1B7DWQBYVLphPWkm8i9Y0/3YdHjHKHiohOJ1ws+3OccDWtH+PoC9DZD5WOTrJvNbWvjS6JWaA==" + "integrity": "sha512-wBuoj1BDpC6ZQ1B7DWQBYVLphPWkm8i9Y0/3YdHjHKHiohOJ1ws+3OccDWtH+PoC9DZD5WOTrJvNbWvjS6JWaA==", + "requires": {} }, "xml2js": { "version": "0.4.23", diff --git a/package.json b/package.json index 6ab44fd8a..eaeb8cf20 100644 --- a/package.json +++ b/package.json @@ -30,9 +30,9 @@ "author": "advplyr", "license": "GPL-3.0", "dependencies": { - "archiver-utils": "^2.1.0", "axios": "^0.26.1", "express": "^4.17.1", + "graceful-fs": "^4.2.10", "htmlparser2": "^8.0.1", "socket.io": "^4.4.1", "xml2js": "^0.4.23" diff --git a/server/libs/archiver/archiverUtils/balancedMatch/LICENSE b/server/libs/archiver/archiverUtils/balancedMatch/LICENSE new file mode 100644 index 000000000..6c781ed62 --- /dev/null +++ b/server/libs/archiver/archiverUtils/balancedMatch/LICENSE @@ -0,0 +1,21 @@ +(MIT) + +Copyright (c) 2013 Julian Gruber <julian@juliangruber.com> + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/server/libs/archiver/archiverUtils/balancedMatch/index.js b/server/libs/archiver/archiverUtils/balancedMatch/index.js new file mode 100644 index 000000000..77ecb0216 --- /dev/null +++ b/server/libs/archiver/archiverUtils/balancedMatch/index.js @@ -0,0 +1,81 @@ +'use strict' + +/** + * @param {string | RegExp} a + * @param {string | RegExp} b + * @param {string} str + */ +function balanced(a, b, str) { + if (a instanceof RegExp) a = maybeMatch(a, str) + if (b instanceof RegExp) b = maybeMatch(b, str) + + const r = range(a, b, str) + + return ( + r && { + start: r[0], + end: r[1], + pre: str.slice(0, r[0]), + body: str.slice(r[0] + a.length, r[1]), + post: str.slice(r[1] + b.length) + } + ) +} + +/** + * @param {RegExp} reg + * @param {string} str + */ +function maybeMatch(reg, str) { + const m = str.match(reg) + return m ? m[0] : null +} + +balanced.range = range + +/** + * @param {string} a + * @param {string} b + * @param {string} str + */ +function range(a, b, str) { + let begs, beg, left, right, result + let ai = str.indexOf(a) + let bi = str.indexOf(b, ai + 1) + let i = ai + + if (ai >= 0 && bi > 0) { + if (a === b) { + return [ai, bi] + } + begs = [] + left = str.length + + while (i >= 0 && !result) { + if (i === ai) { + begs.push(i) + ai = str.indexOf(a, i + 1) + } else if (begs.length === 1) { + result = [begs.pop(), bi] + } else { + beg = begs.pop() + if (beg < left) { + left = beg + right = bi + } + + bi = str.indexOf(b, i + 1) + } + + i = ai < bi && ai >= 0 ? ai : bi + } + + if (begs.length) { + result = [left, right] + } + } + + return result +} + +module.exports = balanced \ No newline at end of file diff --git a/server/libs/archiver/archiverUtils/braceExpansion/LICENSE b/server/libs/archiver/archiverUtils/braceExpansion/LICENSE new file mode 100644 index 000000000..f32aa2c6b --- /dev/null +++ b/server/libs/archiver/archiverUtils/braceExpansion/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2013 Julian Gruber + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/server/libs/archiver/archiverUtils/braceExpansion/index.js b/server/libs/archiver/archiverUtils/braceExpansion/index.js new file mode 100644 index 000000000..4dad5b380 --- /dev/null +++ b/server/libs/archiver/archiverUtils/braceExpansion/index.js @@ -0,0 +1,235 @@ +const balanced = require('../balancedMatch'); + +const escSlash = '\0SLASH' + Math.random() + '\0'; +const escOpen = '\0OPEN' + Math.random() + '\0'; +const escClose = '\0CLOSE' + Math.random() + '\0'; +const escComma = '\0COMMA' + Math.random() + '\0'; +const escPeriod = '\0PERIOD' + Math.random() + '\0'; + +/** + * @return {number} + */ +function numeric(str) { + return parseInt(str, 10) == str + ? parseInt(str, 10) + : str.charCodeAt(0); +} + +/** + * @param {string} str + */ +function escapeBraces(str) { + return str.split('\\\\').join(escSlash) + .split('\\{').join(escOpen) + .split('\\}').join(escClose) + .split('\\,').join(escComma) + .split('\\.').join(escPeriod); +} + +/** + * @param {string} str + */ +function unescapeBraces(str) { + return str.split(escSlash).join('\\') + .split(escOpen).join('{') + .split(escClose).join('}') + .split(escComma).join(',') + .split(escPeriod).join('.'); +} + +/** + * Basically just str.split(","), but handling cases + * where we have nested braced sections, which should be + * treated as individual members, like {a,{b,c},d} + * @param {string} str + */ +function parseCommaParts(str) { + if (!str) + return ['']; + + const parts = []; + const m = balanced('{', '}', str); + + if (!m) + return str.split(','); + + const { pre, body, post } = m; + const p = pre.split(','); + + p[p.length - 1] += '{' + body + '}'; + const postParts = parseCommaParts(post); + if (post.length) { + p[p.length - 1] += postParts.shift(); + p.push.apply(p, postParts); + } + + parts.push.apply(parts, p); + + return parts; +} + +/** + * @param {string} str + */ +function expandTop(str) { + if (!str) + return []; + + // I don't know why Bash 4.3 does this, but it does. + // Anything starting with {} will have the first two bytes preserved + // but *only* at the top level, so {},a}b will not expand to anything, + // but a{},b}c will be expanded to [a}c,abc]. + // One could argue that this is a bug in Bash, but since the goal of + // this module is to match Bash's rules, we escape a leading {} + if (str.slice(0, 2) === '{}') { + str = '\\{\\}' + str.slice(2); + } + + return expand(escapeBraces(str), true).map(unescapeBraces); +} + +/** + * @param {string} str + */ +function embrace(str) { + return '{' + str + '}'; +} + +/** + * @param {string} el + */ +function isPadded(el) { + return /^-?0\d/.test(el); +} + +/** + * @param {number} i + * @param {number} y + */ +function lte(i, y) { + return i <= y; +} + +/** + * @param {number} i + * @param {number} y + */ +function gte(i, y) { + return i >= y; +} + +/** + * @param {string} str + * @param {boolean} [isTop] + */ +function expand(str, isTop) { + /** @type {string[]} */ + const expansions = []; + + const m = balanced('{', '}', str); + if (!m) return [str]; + + // no need to expand pre, since it is guaranteed to be free of brace-sets + const pre = m.pre; + const post = m.post.length + ? expand(m.post, false) + : ['']; + + if (/\$$/.test(m.pre)) { + for (let k = 0; k < post.length; k++) { + const expansion = pre + '{' + m.body + '}' + post[k]; + expansions.push(expansion); + } + } else { + const isNumericSequence = /^-?\d+\.\.-?\d+(?:\.\.-?\d+)?$/.test(m.body); + const isAlphaSequence = /^[a-zA-Z]\.\.[a-zA-Z](?:\.\.-?\d+)?$/.test(m.body); + const isSequence = isNumericSequence || isAlphaSequence; + const isOptions = m.body.indexOf(',') >= 0; + if (!isSequence && !isOptions) { + // {a},b} + if (m.post.match(/,.*\}/)) { + str = m.pre + '{' + m.body + escClose + m.post; + return expand(str); + } + return [str]; + } + + let n; + if (isSequence) { + n = m.body.split(/\.\./); + } else { + n = parseCommaParts(m.body); + if (n.length === 1) { + // x{{a,b}}y ==> x{a}y x{b}y + n = expand(n[0], false).map(embrace); + if (n.length === 1) { + return post.map(function (p) { + return m.pre + n[0] + p; + }); + } + } + } + + // at this point, n is the parts, and we know it's not a comma set + // with a single entry. + let N; + + if (isSequence) { + const x = numeric(n[0]); + const y = numeric(n[1]); + const width = Math.max(n[0].length, n[1].length) + let incr = n.length == 3 + ? Math.abs(numeric(n[2])) + : 1; + let test = lte; + const reverse = y < x; + if (reverse) { + incr *= -1; + test = gte; + } + const pad = n.some(isPadded); + + N = []; + + for (let i = x; test(i, y); i += incr) { + let c; + if (isAlphaSequence) { + c = String.fromCharCode(i); + if (c === '\\') + c = ''; + } else { + c = String(i); + if (pad) { + const need = width - c.length; + if (need > 0) { + const z = new Array(need + 1).join('0'); + if (i < 0) + c = '-' + z + c.slice(1); + else + c = z + c; + } + } + } + N.push(c); + } + } else { + N = []; + + for (let j = 0; j < n.length; j++) { + N.push.apply(N, expand(n[j], false)); + } + } + + for (let j = 0; j < N.length; j++) { + for (let k = 0; k < post.length; k++) { + const expansion = pre + N[j] + post[k]; + if (!isTop || isSequence || expansion) + expansions.push(expansion); + } + } + } + + return expansions; +} + +module.exports = expandTop; \ No newline at end of file diff --git a/server/libs/archiver/archiverUtils/file.js b/server/libs/archiver/archiverUtils/file.js new file mode 100644 index 000000000..6cbc2cb49 --- /dev/null +++ b/server/libs/archiver/archiverUtils/file.js @@ -0,0 +1,209 @@ +/** + * archiver-utils + * + * Copyright (c) 2012-2014 Chris Talkington, contributors. + * Licensed under the MIT license. + * https://github.com/archiverjs/node-archiver/blob/master/LICENSE-MIT + */ +var fs = require('graceful-fs'); +var path = require('path'); + +var flatten = require('./lodash.flatten') +var difference = require('./lodash.difference'); +var union = require('./lodash.union'); +var isPlainObject = require('./lodash.isplainobject'); + +var glob = require('./glob'); + +var file = module.exports = {}; + +var pathSeparatorRe = /[\/\\]/g; + +// Process specified wildcard glob patterns or filenames against a +// callback, excluding and uniquing files in the result set. +var processPatterns = function (patterns, fn) { + // Filepaths to return. + var result = []; + // Iterate over flattened patterns array. + flatten(patterns).forEach(function (pattern) { + // If the first character is ! it should be omitted + var exclusion = pattern.indexOf('!') === 0; + // If the pattern is an exclusion, remove the ! + if (exclusion) { pattern = pattern.slice(1); } + // Find all matching files for this pattern. + var matches = fn(pattern); + if (exclusion) { + // If an exclusion, remove matching files. + result = difference(result, matches); + } else { + // Otherwise add matching files. + result = union(result, matches); + } + }); + return result; +}; + +// True if the file path exists. +file.exists = function () { + var filepath = path.join.apply(path, arguments); + return fs.existsSync(filepath); +}; + +// Return an array of all file paths that match the given wildcard patterns. +file.expand = function (...args) { + // If the first argument is an options object, save those options to pass + // into the File.prototype.glob.sync method. + var options = isPlainObject(args[0]) ? args.shift() : {}; + // Use the first argument if it's an Array, otherwise convert the arguments + // object to an array and use that. + var patterns = Array.isArray(args[0]) ? args[0] : args; + // Return empty set if there are no patterns or filepaths. + if (patterns.length === 0) { return []; } + // Return all matching filepaths. + var matches = processPatterns(patterns, function (pattern) { + // Find all matching files for this pattern. + return glob.sync(pattern, options); + }); + // Filter result set? + if (options.filter) { + matches = matches.filter(function (filepath) { + filepath = path.join(options.cwd || '', filepath); + try { + if (typeof options.filter === 'function') { + return options.filter(filepath); + } else { + // If the file is of the right type and exists, this should work. + return fs.statSync(filepath)[options.filter](); + } + } catch (e) { + // Otherwise, it's probably not the right type. + return false; + } + }); + } + return matches; +}; + +// Build a multi task "files" object dynamically. +file.expandMapping = function (patterns, destBase, options) { + options = Object.assign({ + rename: function (destBase, destPath) { + return path.join(destBase || '', destPath); + } + }, options); + var files = []; + var fileByDest = {}; + // Find all files matching pattern, using passed-in options. + file.expand(options, patterns).forEach(function (src) { + var destPath = src; + // Flatten? + if (options.flatten) { + destPath = path.basename(destPath); + } + // Change the extension? + if (options.ext) { + destPath = destPath.replace(/(\.[^\/]*)?$/, options.ext); + } + // Generate destination filename. + var dest = options.rename(destBase, destPath, options); + // Prepend cwd to src path if necessary. + if (options.cwd) { src = path.join(options.cwd, src); } + // Normalize filepaths to be unix-style. + dest = dest.replace(pathSeparatorRe, '/'); + src = src.replace(pathSeparatorRe, '/'); + // Map correct src path to dest path. + if (fileByDest[dest]) { + // If dest already exists, push this src onto that dest's src array. + fileByDest[dest].src.push(src); + } else { + // Otherwise create a new src-dest file mapping object. + files.push({ + src: [src], + dest: dest, + }); + // And store a reference for later use. + fileByDest[dest] = files[files.length - 1]; + } + }); + return files; +}; + +// reusing bits of grunt's multi-task source normalization +file.normalizeFilesArray = function (data) { + var files = []; + + data.forEach(function (obj) { + var prop; + if ('src' in obj || 'dest' in obj) { + files.push(obj); + } + }); + + if (files.length === 0) { + return []; + } + + files = _(files).chain().forEach(function (obj) { + if (!('src' in obj) || !obj.src) { return; } + // Normalize .src properties to flattened array. + if (Array.isArray(obj.src)) { + obj.src = flatten(obj.src); + } else { + obj.src = [obj.src]; + } + }).map(function (obj) { + // Build options object, removing unwanted properties. + var expandOptions = Object.assign({}, obj); + delete expandOptions.src; + delete expandOptions.dest; + + // Expand file mappings. + if (obj.expand) { + return file.expandMapping(obj.src, obj.dest, expandOptions).map(function (mapObj) { + // Copy obj properties to result. + var result = Object.assign({}, obj); + // Make a clone of the orig obj available. + result.orig = Object.assign({}, obj); + // Set .src and .dest, processing both as templates. + result.src = mapObj.src; + result.dest = mapObj.dest; + // Remove unwanted properties. + ['expand', 'cwd', 'flatten', 'rename', 'ext'].forEach(function (prop) { + delete result[prop]; + }); + return result; + }); + } + + // Copy obj properties to result, adding an .orig property. + var result = Object.assign({}, obj); + // Make a clone of the orig obj available. + result.orig = Object.assign({}, obj); + + if ('src' in result) { + // Expose an expand-on-demand getter method as .src. + Object.defineProperty(result, 'src', { + enumerable: true, + get: function fn() { + var src; + if (!('result' in fn)) { + src = obj.src; + // If src is an array, flatten it. Otherwise, make it into an array. + src = Array.isArray(src) ? flatten(src) : [src]; + // Expand src files, memoizing result. + fn.result = file.expand(expandOptions, src); + } + return fn.result; + } + }); + } + + if ('dest' in result) { + result.dest = obj.dest; + } + + return result; + }).flatten().value(); + + return files; +}; diff --git a/server/libs/archiver/archiverUtils/fsRealpath/LICENSE b/server/libs/archiver/archiverUtils/fsRealpath/LICENSE new file mode 100644 index 000000000..7c6e4735c --- /dev/null +++ b/server/libs/archiver/archiverUtils/fsRealpath/LICENSE @@ -0,0 +1,43 @@ +The ISC License + +Copyright (c) 2016-2022 Isaac Z. Schlueter and Contributors + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR +IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +---- + +This library bundles a version of the `fs.realpath` and `fs.realpathSync` +methods from Node.js v0.10 under the terms of the Node.js MIT license. + +Node's license follows, also included at the header of `old.js` which contains +the licensed code: + +Copyright (c) 2016-2022 Joyent, Inc. and other Node contributors. + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/server/libs/archiver/archiverUtils/fsRealpath/index.js b/server/libs/archiver/archiverUtils/fsRealpath/index.js new file mode 100644 index 000000000..4666e6f46 --- /dev/null +++ b/server/libs/archiver/archiverUtils/fsRealpath/index.js @@ -0,0 +1,54 @@ +module.exports = realpath +realpath.realpath = realpath +realpath.sync = realpathSync +realpath.realpathSync = realpathSync + +var fs = require('fs') +var origRealpath = fs.realpath +var origRealpathSync = fs.realpathSync + +var version = process.version +var ok = /^v[0-5]\./.test(version) +var old = require('./old.js') + +function newError(er) { + return er && er.syscall === 'realpath' && ( + er.code === 'ELOOP' || + er.code === 'ENOMEM' || + er.code === 'ENAMETOOLONG' + ) +} + +function realpath(p, cache, cb) { + if (ok) { + return origRealpath(p, cache, cb) + } + + if (typeof cache === 'function') { + cb = cache + cache = null + } + origRealpath(p, cache, function (er, result) { + if (newError(er)) { + old.realpath(p, cache, cb) + } else { + cb(er, result) + } + }) +} + +function realpathSync(p, cache) { + if (ok) { + return origRealpathSync(p, cache) + } + + try { + return origRealpathSync(p, cache) + } catch (er) { + if (newError(er)) { + return old.realpathSync(p, cache) + } else { + throw er + } + } +} diff --git a/server/libs/archiver/archiverUtils/fsRealpath/old.js b/server/libs/archiver/archiverUtils/fsRealpath/old.js new file mode 100644 index 000000000..379711e12 --- /dev/null +++ b/server/libs/archiver/archiverUtils/fsRealpath/old.js @@ -0,0 +1,302 @@ +/* istanbul ignore file - tested in node */ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +var pathModule = require('path'); +var isWindows = process.platform === 'win32'; +var fs = require('fs'); + +// JavaScript implementation of realpath, ported from node pre-v6 + +var DEBUG = process.env.NODE_DEBUG && /fs/.test(process.env.NODE_DEBUG); + +function rethrow() { + // Only enable in debug mode. A backtrace uses ~1000 bytes of heap space and + // is fairly slow to generate. + var callback; + if (DEBUG) { + var backtrace = new Error; + callback = debugCallback; + } else + callback = missingCallback; + + return callback; + + function debugCallback(err) { + if (err) { + backtrace.message = err.message; + err = backtrace; + missingCallback(err); + } + } + + function missingCallback(err) { + if (err) { + if (process.throwDeprecation) + throw err; // Forgot a callback but don't know where? Use NODE_DEBUG=fs + else if (!process.noDeprecation) { + var msg = 'fs: missing callback ' + (err.stack || err.message); + if (process.traceDeprecation) + console.trace(msg); + else + console.error(msg); + } + } + } +} + +function maybeCallback(cb) { + return typeof cb === 'function' ? cb : rethrow(); +} + +// Regexp that finds the next partion of a (partial) path +// result is [base_with_slash, base], e.g. ['somedir/', 'somedir'] +if (isWindows) { + var nextPartRe = /(.*?)(?:[\/\\]+|$)/g; +} else { + var nextPartRe = /(.*?)(?:[\/]+|$)/g; +} + +// Regex to find the device root, including trailing slash. E.g. 'c:\\'. +if (isWindows) { + var splitRootRe = /^(?:[a-zA-Z]:|[\\\/]{2}[^\\\/]+[\\\/][^\\\/]+)?[\\\/]*/; +} else { + var splitRootRe = /^[\/]*/; +} + +exports.realpathSync = function realpathSync(p, cache) { + // make p is absolute + p = pathModule.resolve(p); + + if (cache && Object.prototype.hasOwnProperty.call(cache, p)) { + return cache[p]; + } + + var original = p, + seenLinks = {}, + knownHard = {}; + + // current character position in p + var pos; + // the partial path so far, including a trailing slash if any + var current; + // the partial path without a trailing slash (except when pointing at a root) + var base; + // the partial path scanned in the previous round, with slash + var previous; + + start(); + + function start() { + // Skip over roots + var m = splitRootRe.exec(p); + pos = m[0].length; + current = m[0]; + base = m[0]; + previous = ''; + + // On windows, check that the root exists. On unix there is no need. + if (isWindows && !knownHard[base]) { + fs.lstatSync(base); + knownHard[base] = true; + } + } + + // walk down the path, swapping out linked pathparts for their real + // values + // NB: p.length changes. + while (pos < p.length) { + // find the next part + nextPartRe.lastIndex = pos; + var result = nextPartRe.exec(p); + previous = current; + current += result[0]; + base = previous + result[1]; + pos = nextPartRe.lastIndex; + + // continue if not a symlink + if (knownHard[base] || (cache && cache[base] === base)) { + continue; + } + + var resolvedLink; + if (cache && Object.prototype.hasOwnProperty.call(cache, base)) { + // some known symbolic link. no need to stat again. + resolvedLink = cache[base]; + } else { + var stat = fs.lstatSync(base); + if (!stat.isSymbolicLink()) { + knownHard[base] = true; + if (cache) cache[base] = base; + continue; + } + + // read the link if it wasn't read before + // dev/ino always return 0 on windows, so skip the check. + var linkTarget = null; + if (!isWindows) { + var id = stat.dev.toString(32) + ':' + stat.ino.toString(32); + if (seenLinks.hasOwnProperty(id)) { + linkTarget = seenLinks[id]; + } + } + if (linkTarget === null) { + fs.statSync(base); + linkTarget = fs.readlinkSync(base); + } + resolvedLink = pathModule.resolve(previous, linkTarget); + // track this, if given a cache. + if (cache) cache[base] = resolvedLink; + if (!isWindows) seenLinks[id] = linkTarget; + } + + // resolve the link, then start over + p = pathModule.resolve(resolvedLink, p.slice(pos)); + start(); + } + + if (cache) cache[original] = p; + + return p; +}; + + +exports.realpath = function realpath(p, cache, cb) { + if (typeof cb !== 'function') { + cb = maybeCallback(cache); + cache = null; + } + + // make p is absolute + p = pathModule.resolve(p); + + if (cache && Object.prototype.hasOwnProperty.call(cache, p)) { + return process.nextTick(cb.bind(null, null, cache[p])); + } + + var original = p, + seenLinks = {}, + knownHard = {}; + + // current character position in p + var pos; + // the partial path so far, including a trailing slash if any + var current; + // the partial path without a trailing slash (except when pointing at a root) + var base; + // the partial path scanned in the previous round, with slash + var previous; + + start(); + + function start() { + // Skip over roots + var m = splitRootRe.exec(p); + pos = m[0].length; + current = m[0]; + base = m[0]; + previous = ''; + + // On windows, check that the root exists. On unix there is no need. + if (isWindows && !knownHard[base]) { + fs.lstat(base, function (err) { + if (err) return cb(err); + knownHard[base] = true; + LOOP(); + }); + } else { + process.nextTick(LOOP); + } + } + + // walk down the path, swapping out linked pathparts for their real + // values + function LOOP() { + // stop if scanned past end of path + if (pos >= p.length) { + if (cache) cache[original] = p; + return cb(null, p); + } + + // find the next part + nextPartRe.lastIndex = pos; + var result = nextPartRe.exec(p); + previous = current; + current += result[0]; + base = previous + result[1]; + pos = nextPartRe.lastIndex; + + // continue if not a symlink + if (knownHard[base] || (cache && cache[base] === base)) { + return process.nextTick(LOOP); + } + + if (cache && Object.prototype.hasOwnProperty.call(cache, base)) { + // known symbolic link. no need to stat again. + return gotResolvedLink(cache[base]); + } + + return fs.lstat(base, gotStat); + } + + function gotStat(err, stat) { + if (err) return cb(err); + + // if not a symlink, skip to the next path part + if (!stat.isSymbolicLink()) { + knownHard[base] = true; + if (cache) cache[base] = base; + return process.nextTick(LOOP); + } + + // stat & read the link if not read before + // call gotTarget as soon as the link target is known + // dev/ino always return 0 on windows, so skip the check. + if (!isWindows) { + var id = stat.dev.toString(32) + ':' + stat.ino.toString(32); + if (seenLinks.hasOwnProperty(id)) { + return gotTarget(null, seenLinks[id], base); + } + } + fs.stat(base, function (err) { + if (err) return cb(err); + + fs.readlink(base, function (err, target) { + if (!isWindows) seenLinks[id] = target; + gotTarget(err, target); + }); + }); + } + + function gotTarget(err, target, base) { + if (err) return cb(err); + + var resolvedLink = pathModule.resolve(previous, target); + if (cache) cache[base] = resolvedLink; + gotResolvedLink(resolvedLink); + } + + function gotResolvedLink(resolvedLink) { + // resolve the link, then start over + p = pathModule.resolve(resolvedLink, p.slice(pos)); + start(); + } +}; \ No newline at end of file diff --git a/server/libs/archiver/archiverUtils/glob/LICENSE b/server/libs/archiver/archiverUtils/glob/LICENSE new file mode 100644 index 000000000..8daf55fc9 --- /dev/null +++ b/server/libs/archiver/archiverUtils/glob/LICENSE @@ -0,0 +1,15 @@ +The ISC License + +Copyright (c) 2009-2022 Isaac Z. Schlueter and Contributors + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR +IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. \ No newline at end of file diff --git a/server/libs/archiver/archiverUtils/glob/common.js b/server/libs/archiver/archiverUtils/glob/common.js new file mode 100644 index 000000000..21ee4d721 --- /dev/null +++ b/server/libs/archiver/archiverUtils/glob/common.js @@ -0,0 +1,240 @@ +exports.setopts = setopts +exports.ownProp = ownProp +exports.makeAbs = makeAbs +exports.finish = finish +exports.mark = mark +exports.isIgnored = isIgnored +exports.childrenIgnored = childrenIgnored + +function ownProp(obj, field) { + return Object.prototype.hasOwnProperty.call(obj, field) +} + +var fs = require("fs") +var path = require("path") +var minimatch = require("../minimatch") +var isAbsolute = require("path").isAbsolute +var Minimatch = minimatch.Minimatch + +function alphasort(a, b) { + return a.localeCompare(b, 'en') +} + +function setupIgnores(self, options) { + self.ignore = options.ignore || [] + + if (!Array.isArray(self.ignore)) + self.ignore = [self.ignore] + + if (self.ignore.length) { + self.ignore = self.ignore.map(ignoreMap) + } +} + +// ignore patterns are always in dot:true mode. +function ignoreMap(pattern) { + var gmatcher = null + if (pattern.slice(-3) === '/**') { + var gpattern = pattern.replace(/(\/\*\*)+$/, '') + gmatcher = new Minimatch(gpattern, { dot: true }) + } + + return { + matcher: new Minimatch(pattern, { dot: true }), + gmatcher: gmatcher + } +} + +function setopts(self, pattern, options) { + if (!options) + options = {} + + // base-matching: just use globstar for that. + if (options.matchBase && -1 === pattern.indexOf("/")) { + if (options.noglobstar) { + throw new Error("base matching requires globstar") + } + pattern = "**/" + pattern + } + + self.silent = !!options.silent + self.pattern = pattern + self.strict = options.strict !== false + self.realpath = !!options.realpath + self.realpathCache = options.realpathCache || Object.create(null) + self.follow = !!options.follow + self.dot = !!options.dot + self.mark = !!options.mark + self.nodir = !!options.nodir + if (self.nodir) + self.mark = true + self.sync = !!options.sync + self.nounique = !!options.nounique + self.nonull = !!options.nonull + self.nosort = !!options.nosort + self.nocase = !!options.nocase + self.stat = !!options.stat + self.noprocess = !!options.noprocess + self.absolute = !!options.absolute + self.fs = options.fs || fs + + self.maxLength = options.maxLength || Infinity + self.cache = options.cache || Object.create(null) + self.statCache = options.statCache || Object.create(null) + self.symlinks = options.symlinks || Object.create(null) + + setupIgnores(self, options) + + self.changedCwd = false + var cwd = process.cwd() + if (!ownProp(options, "cwd")) + self.cwd = path.resolve(cwd) + else { + self.cwd = path.resolve(options.cwd) + self.changedCwd = self.cwd !== cwd + } + + self.root = options.root || path.resolve(self.cwd, "/") + self.root = path.resolve(self.root) + + // TODO: is an absolute `cwd` supposed to be resolved against `root`? + // e.g. { cwd: '/test', root: __dirname } === path.join(__dirname, '/test') + self.cwdAbs = isAbsolute(self.cwd) ? self.cwd : makeAbs(self, self.cwd) + self.nomount = !!options.nomount + + if (process.platform === "win32") { + self.root = self.root.replace(/\\/g, "/") + self.cwd = self.cwd.replace(/\\/g, "/") + self.cwdAbs = self.cwdAbs.replace(/\\/g, "/") + } + + // disable comments and negation in Minimatch. + // Note that they are not supported in Glob itself anyway. + options.nonegate = true + options.nocomment = true + // always treat \ in patterns as escapes, not path separators + options.allowWindowsEscape = true + + self.minimatch = new Minimatch(pattern, options) + self.options = self.minimatch.options +} + +function finish(self) { + var nou = self.nounique + var all = nou ? [] : Object.create(null) + + for (var i = 0, l = self.matches.length; i < l; i++) { + var matches = self.matches[i] + if (!matches || Object.keys(matches).length === 0) { + if (self.nonull) { + // do like the shell, and spit out the literal glob + var literal = self.minimatch.globSet[i] + if (nou) + all.push(literal) + else + all[literal] = true + } + } else { + // had matches + var m = Object.keys(matches) + if (nou) + all.push.apply(all, m) + else + m.forEach(function (m) { + all[m] = true + }) + } + } + + if (!nou) + all = Object.keys(all) + + if (!self.nosort) + all = all.sort(alphasort) + + // at *some* point we statted all of these + if (self.mark) { + for (var i = 0; i < all.length; i++) { + all[i] = self._mark(all[i]) + } + if (self.nodir) { + all = all.filter(function (e) { + var notDir = !(/\/$/.test(e)) + var c = self.cache[e] || self.cache[makeAbs(self, e)] + if (notDir && c) + notDir = c !== 'DIR' && !Array.isArray(c) + return notDir + }) + } + } + + if (self.ignore.length) + all = all.filter(function (m) { + return !isIgnored(self, m) + }) + + self.found = all +} + +function mark(self, p) { + var abs = makeAbs(self, p) + var c = self.cache[abs] + var m = p + if (c) { + var isDir = c === 'DIR' || Array.isArray(c) + var slash = p.slice(-1) === '/' + + if (isDir && !slash) + m += '/' + else if (!isDir && slash) + m = m.slice(0, -1) + + if (m !== p) { + var mabs = makeAbs(self, m) + self.statCache[mabs] = self.statCache[abs] + self.cache[mabs] = self.cache[abs] + } + } + + return m +} + +// lotta situps... +function makeAbs(self, f) { + var abs = f + if (f.charAt(0) === '/') { + abs = path.join(self.root, f) + } else if (isAbsolute(f) || f === '') { + abs = f + } else if (self.changedCwd) { + abs = path.resolve(self.cwd, f) + } else { + abs = path.resolve(f) + } + + if (process.platform === 'win32') + abs = abs.replace(/\\/g, '/') + + return abs +} + + +// Return true, if pattern ends with globstar '**', for the accompanying parent directory. +// Ex:- If node_modules/** is the pattern, add 'node_modules' to ignore list along with it's contents +function isIgnored(self, path) { + if (!self.ignore.length) + return false + + return self.ignore.some(function (item) { + return item.matcher.match(path) || !!(item.gmatcher && item.gmatcher.match(path)) + }) +} + +function childrenIgnored(self, path) { + if (!self.ignore.length) + return false + + return self.ignore.some(function (item) { + return !!(item.gmatcher && item.gmatcher.match(path)) + }) +} \ No newline at end of file diff --git a/server/libs/archiver/archiverUtils/glob/index.js b/server/libs/archiver/archiverUtils/glob/index.js new file mode 100644 index 000000000..2f29d8c5b --- /dev/null +++ b/server/libs/archiver/archiverUtils/glob/index.js @@ -0,0 +1,789 @@ +// Approach: +// +// 1. Get the minimatch set +// 2. For each pattern in the set, PROCESS(pattern, false) +// 3. Store matches per-set, then uniq them +// +// PROCESS(pattern, inGlobStar) +// Get the first [n] items from pattern that are all strings +// Join these together. This is PREFIX. +// If there is no more remaining, then stat(PREFIX) and +// add to matches if it succeeds. END. +// +// If inGlobStar and PREFIX is symlink and points to dir +// set ENTRIES = [] +// else readdir(PREFIX) as ENTRIES +// If fail, END +// +// with ENTRIES +// If pattern[n] is GLOBSTAR +// // handle the case where the globstar match is empty +// // by pruning it out, and testing the resulting pattern +// PROCESS(pattern[0..n] + pattern[n+1 .. $], false) +// // handle other cases. +// for ENTRY in ENTRIES (not dotfiles) +// // attach globstar + tail onto the entry +// // Mark that this entry is a globstar match +// PROCESS(pattern[0..n] + ENTRY + pattern[n .. $], true) +// +// else // not globstar +// for ENTRY in ENTRIES (not dotfiles, unless pattern[n] is dot) +// Test ENTRY against pattern[n] +// If fails, continue +// If passes, PROCESS(pattern[0..n] + item + pattern[n+1 .. $]) +// +// Caveat: +// Cache all stats and readdirs results to minimize syscall. Since all +// we ever care about is existence and directory-ness, we can just keep +// `true` for files, and [children,...] for directories, or `false` for +// things that don't exist. + +module.exports = glob + +var rp = require('../fsRealpath') +var minimatch = require('../minimatch') +// var inherits = require('inherits') +const util = require('util') +var EE = require('events').EventEmitter +var path = require('path') +var assert = require('assert') +var isAbsolute = require('path').isAbsolute +var globSync = require('./sync.js') +var common = require('./common.js') +var setopts = common.setopts +var ownProp = common.ownProp +var inflight = require('../inflight') +var childrenIgnored = common.childrenIgnored +var isIgnored = common.isIgnored + +var once = require('../../../lodash.once') + +function glob(pattern, options, cb) { + if (typeof options === 'function') cb = options, options = {} + if (!options) options = {} + + if (options.sync) { + if (cb) + throw new TypeError('callback provided to sync glob') + return globSync(pattern, options) + } + + return new Glob(pattern, options, cb) +} + +glob.sync = globSync +var GlobSync = glob.GlobSync = globSync.GlobSync + +// old api surface +glob.glob = glob + +function extend(origin, add) { + if (add === null || typeof add !== 'object') { + return origin + } + + var keys = Object.keys(add) + var i = keys.length + while (i--) { + origin[keys[i]] = add[keys[i]] + } + return origin +} + +glob.hasMagic = function (pattern, options_) { + var options = extend({}, options_) + options.noprocess = true + + var g = new Glob(pattern, options) + var set = g.minimatch.set + + if (!pattern) + return false + + if (set.length > 1) + return true + + for (var j = 0; j < set[0].length; j++) { + if (typeof set[0][j] !== 'string') + return true + } + + return false +} + +glob.Glob = Glob +util.inherits(Glob, EE) +function Glob(pattern, options, cb) { + if (typeof options === 'function') { + cb = options + options = null + } + + if (options && options.sync) { + if (cb) + throw new TypeError('callback provided to sync glob') + return new GlobSync(pattern, options) + } + + if (!(this instanceof Glob)) + return new Glob(pattern, options, cb) + + setopts(this, pattern, options) + this._didRealPath = false + + // process each pattern in the minimatch set + var n = this.minimatch.set.length + + // The matches are stored as {: true,...} so that + // duplicates are automagically pruned. + // Later, we do an Object.keys() on these. + // Keep them as a list so we can fill in when nonull is set. + this.matches = new Array(n) + + if (typeof cb === 'function') { + cb = once(cb) + this.on('error', cb) + this.on('end', function (matches) { + cb(null, matches) + }) + } + + var self = this + this._processing = 0 + + this._emitQueue = [] + this._processQueue = [] + this.paused = false + + if (this.noprocess) + return this + + if (n === 0) + return done() + + var sync = true + for (var i = 0; i < n; i++) { + this._process(this.minimatch.set[i], i, false, done) + } + sync = false + + function done() { + --self._processing + if (self._processing <= 0) { + if (sync) { + process.nextTick(function () { + self._finish() + }) + } else { + self._finish() + } + } + } +} + +Glob.prototype._finish = function () { + assert(this instanceof Glob) + if (this.aborted) + return + + if (this.realpath && !this._didRealpath) + return this._realpath() + + common.finish(this) + this.emit('end', this.found) +} + +Glob.prototype._realpath = function () { + if (this._didRealpath) + return + + this._didRealpath = true + + var n = this.matches.length + if (n === 0) + return this._finish() + + var self = this + for (var i = 0; i < this.matches.length; i++) + this._realpathSet(i, next) + + function next() { + if (--n === 0) + self._finish() + } +} + +Glob.prototype._realpathSet = function (index, cb) { + var matchset = this.matches[index] + if (!matchset) + return cb() + + var found = Object.keys(matchset) + var self = this + var n = found.length + + if (n === 0) + return cb() + + var set = this.matches[index] = Object.create(null) + found.forEach(function (p, i) { + // If there's a problem with the stat, then it means that + // one or more of the links in the realpath couldn't be + // resolved. just return the abs value in that case. + p = self._makeAbs(p) + rp.realpath(p, self.realpathCache, function (er, real) { + if (!er) + set[real] = true + else if (er.syscall === 'stat') + set[p] = true + else + self.emit('error', er) // srsly wtf right here + + if (--n === 0) { + self.matches[index] = set + cb() + } + }) + }) +} + +Glob.prototype._mark = function (p) { + return common.mark(this, p) +} + +Glob.prototype._makeAbs = function (f) { + return common.makeAbs(this, f) +} + +Glob.prototype.abort = function () { + this.aborted = true + this.emit('abort') +} + +Glob.prototype.pause = function () { + if (!this.paused) { + this.paused = true + this.emit('pause') + } +} + +Glob.prototype.resume = function () { + if (this.paused) { + this.emit('resume') + this.paused = false + if (this._emitQueue.length) { + var eq = this._emitQueue.slice(0) + this._emitQueue.length = 0 + for (var i = 0; i < eq.length; i++) { + var e = eq[i] + this._emitMatch(e[0], e[1]) + } + } + if (this._processQueue.length) { + var pq = this._processQueue.slice(0) + this._processQueue.length = 0 + for (var i = 0; i < pq.length; i++) { + var p = pq[i] + this._processing-- + this._process(p[0], p[1], p[2], p[3]) + } + } + } +} + +Glob.prototype._process = function (pattern, index, inGlobStar, cb) { + assert(this instanceof Glob) + assert(typeof cb === 'function') + + if (this.aborted) + return + + this._processing++ + if (this.paused) { + this._processQueue.push([pattern, index, inGlobStar, cb]) + return + } + + //console.error('PROCESS %d', this._processing, pattern) + + // Get the first [n] parts of pattern that are all strings. + var n = 0 + while (typeof pattern[n] === 'string') { + n++ + } + // now n is the index of the first one that is *not* a string. + + // see if there's anything else + var prefix + switch (n) { + // if not, then this is rather simple + case pattern.length: + this._processSimple(pattern.join('/'), index, cb) + return + + case 0: + // pattern *starts* with some non-trivial item. + // going to readdir(cwd), but not include the prefix in matches. + prefix = null + break + + default: + // pattern has some string bits in the front. + // whatever it starts with, whether that's 'absolute' like /foo/bar, + // or 'relative' like '../baz' + prefix = pattern.slice(0, n).join('/') + break + } + + var remain = pattern.slice(n) + + // get the list of entries. + var read + if (prefix === null) + read = '.' + else if (isAbsolute(prefix) || + isAbsolute(pattern.map(function (p) { + return typeof p === 'string' ? p : '[*]' + }).join('/'))) { + if (!prefix || !isAbsolute(prefix)) + prefix = '/' + prefix + read = prefix + } else + read = prefix + + var abs = this._makeAbs(read) + + //if ignored, skip _processing + if (childrenIgnored(this, read)) + return cb() + + var isGlobStar = remain[0] === minimatch.GLOBSTAR + if (isGlobStar) + this._processGlobStar(prefix, read, abs, remain, index, inGlobStar, cb) + else + this._processReaddir(prefix, read, abs, remain, index, inGlobStar, cb) +} + +Glob.prototype._processReaddir = function (prefix, read, abs, remain, index, inGlobStar, cb) { + var self = this + this._readdir(abs, inGlobStar, function (er, entries) { + return self._processReaddir2(prefix, read, abs, remain, index, inGlobStar, entries, cb) + }) +} + +Glob.prototype._processReaddir2 = function (prefix, read, abs, remain, index, inGlobStar, entries, cb) { + + // if the abs isn't a dir, then nothing can match! + if (!entries) + return cb() + + // It will only match dot entries if it starts with a dot, or if + // dot is set. Stuff like @(.foo|.bar) isn't allowed. + var pn = remain[0] + var negate = !!this.minimatch.negate + var rawGlob = pn._glob + var dotOk = this.dot || rawGlob.charAt(0) === '.' + + var matchedEntries = [] + for (var i = 0; i < entries.length; i++) { + var e = entries[i] + if (e.charAt(0) !== '.' || dotOk) { + var m + if (negate && !prefix) { + m = !e.match(pn) + } else { + m = e.match(pn) + } + if (m) + matchedEntries.push(e) + } + } + + //console.error('prd2', prefix, entries, remain[0]._glob, matchedEntries) + + var len = matchedEntries.length + // If there are no matched entries, then nothing matches. + if (len === 0) + return cb() + + // if this is the last remaining pattern bit, then no need for + // an additional stat *unless* the user has specified mark or + // stat explicitly. We know they exist, since readdir returned + // them. + + if (remain.length === 1 && !this.mark && !this.stat) { + if (!this.matches[index]) + this.matches[index] = Object.create(null) + + for (var i = 0; i < len; i++) { + var e = matchedEntries[i] + if (prefix) { + if (prefix !== '/') + e = prefix + '/' + e + else + e = prefix + e + } + + if (e.charAt(0) === '/' && !this.nomount) { + e = path.join(this.root, e) + } + this._emitMatch(index, e) + } + // This was the last one, and no stats were needed + return cb() + } + + // now test all matched entries as stand-ins for that part + // of the pattern. + remain.shift() + for (var i = 0; i < len; i++) { + var e = matchedEntries[i] + var newPattern + if (prefix) { + if (prefix !== '/') + e = prefix + '/' + e + else + e = prefix + e + } + this._process([e].concat(remain), index, inGlobStar, cb) + } + cb() +} + +Glob.prototype._emitMatch = function (index, e) { + if (this.aborted) + return + + if (isIgnored(this, e)) + return + + if (this.paused) { + this._emitQueue.push([index, e]) + return + } + + var abs = isAbsolute(e) ? e : this._makeAbs(e) + + if (this.mark) + e = this._mark(e) + + if (this.absolute) + e = abs + + if (this.matches[index][e]) + return + + if (this.nodir) { + var c = this.cache[abs] + if (c === 'DIR' || Array.isArray(c)) + return + } + + this.matches[index][e] = true + + var st = this.statCache[abs] + if (st) + this.emit('stat', e, st) + + this.emit('match', e) +} + +Glob.prototype._readdirInGlobStar = function (abs, cb) { + if (this.aborted) + return + + // follow all symlinked directories forever + // just proceed as if this is a non-globstar situation + if (this.follow) + return this._readdir(abs, false, cb) + + var lstatkey = 'lstat\0' + abs + var self = this + var lstatcb = inflight(lstatkey, lstatcb_) + + if (lstatcb) + self.fs.lstat(abs, lstatcb) + + function lstatcb_(er, lstat) { + if (er && er.code === 'ENOENT') + return cb() + + var isSym = lstat && lstat.isSymbolicLink() + self.symlinks[abs] = isSym + + // If it's not a symlink or a dir, then it's definitely a regular file. + // don't bother doing a readdir in that case. + if (!isSym && lstat && !lstat.isDirectory()) { + self.cache[abs] = 'FILE' + cb() + } else + self._readdir(abs, false, cb) + } +} + +Glob.prototype._readdir = function (abs, inGlobStar, cb) { + if (this.aborted) + return + + cb = inflight('readdir\0' + abs + '\0' + inGlobStar, cb) + if (!cb) + return + + //console.error('RD %j %j', +inGlobStar, abs) + if (inGlobStar && !ownProp(this.symlinks, abs)) + return this._readdirInGlobStar(abs, cb) + + if (ownProp(this.cache, abs)) { + var c = this.cache[abs] + if (!c || c === 'FILE') + return cb() + + if (Array.isArray(c)) + return cb(null, c) + } + + var self = this + self.fs.readdir(abs, readdirCb(this, abs, cb)) +} + +function readdirCb(self, abs, cb) { + return function (er, entries) { + if (er) + self._readdirError(abs, er, cb) + else + self._readdirEntries(abs, entries, cb) + } +} + +Glob.prototype._readdirEntries = function (abs, entries, cb) { + if (this.aborted) + return + + // if we haven't asked to stat everything, then just + // assume that everything in there exists, so we can avoid + // having to stat it a second time. + if (!this.mark && !this.stat) { + for (var i = 0; i < entries.length; i++) { + var e = entries[i] + if (abs === '/') + e = abs + e + else + e = abs + '/' + e + this.cache[e] = true + } + } + + this.cache[abs] = entries + return cb(null, entries) +} + +Glob.prototype._readdirError = function (f, er, cb) { + if (this.aborted) + return + + // handle errors, and cache the information + switch (er.code) { + case 'ENOTSUP': // https://github.com/isaacs/node-glob/issues/205 + case 'ENOTDIR': // totally normal. means it *does* exist. + var abs = this._makeAbs(f) + this.cache[abs] = 'FILE' + if (abs === this.cwdAbs) { + var error = new Error(er.code + ' invalid cwd ' + this.cwd) + error.path = this.cwd + error.code = er.code + this.emit('error', error) + this.abort() + } + break + + case 'ENOENT': // not terribly unusual + case 'ELOOP': + case 'ENAMETOOLONG': + case 'UNKNOWN': + this.cache[this._makeAbs(f)] = false + break + + default: // some unusual error. Treat as failure. + this.cache[this._makeAbs(f)] = false + if (this.strict) { + this.emit('error', er) + // If the error is handled, then we abort + // if not, we threw out of here + this.abort() + } + if (!this.silent) + console.error('glob error', er) + break + } + + return cb() +} + +Glob.prototype._processGlobStar = function (prefix, read, abs, remain, index, inGlobStar, cb) { + var self = this + this._readdir(abs, inGlobStar, function (er, entries) { + self._processGlobStar2(prefix, read, abs, remain, index, inGlobStar, entries, cb) + }) +} + + +Glob.prototype._processGlobStar2 = function (prefix, read, abs, remain, index, inGlobStar, entries, cb) { + //console.error('pgs2', prefix, remain[0], entries) + + // no entries means not a dir, so it can never have matches + // foo.txt/** doesn't match foo.txt + if (!entries) + return cb() + + // test without the globstar, and with every child both below + // and replacing the globstar. + var remainWithoutGlobStar = remain.slice(1) + var gspref = prefix ? [prefix] : [] + var noGlobStar = gspref.concat(remainWithoutGlobStar) + + // the noGlobStar pattern exits the inGlobStar state + this._process(noGlobStar, index, false, cb) + + var isSym = this.symlinks[abs] + var len = entries.length + + // If it's a symlink, and we're in a globstar, then stop + if (isSym && inGlobStar) + return cb() + + for (var i = 0; i < len; i++) { + var e = entries[i] + if (e.charAt(0) === '.' && !this.dot) + continue + + // these two cases enter the inGlobStar state + var instead = gspref.concat(entries[i], remainWithoutGlobStar) + this._process(instead, index, true, cb) + + var below = gspref.concat(entries[i], remain) + this._process(below, index, true, cb) + } + + cb() +} + +Glob.prototype._processSimple = function (prefix, index, cb) { + // XXX review this. Shouldn't it be doing the mounting etc + // before doing stat? kinda weird? + var self = this + this._stat(prefix, function (er, exists) { + self._processSimple2(prefix, index, er, exists, cb) + }) +} +Glob.prototype._processSimple2 = function (prefix, index, er, exists, cb) { + + //console.error('ps2', prefix, exists) + + if (!this.matches[index]) + this.matches[index] = Object.create(null) + + // If it doesn't exist, then just mark the lack of results + if (!exists) + return cb() + + if (prefix && isAbsolute(prefix) && !this.nomount) { + var trail = /[\/\\]$/.test(prefix) + if (prefix.charAt(0) === '/') { + prefix = path.join(this.root, prefix) + } else { + prefix = path.resolve(this.root, prefix) + if (trail) + prefix += '/' + } + } + + if (process.platform === 'win32') + prefix = prefix.replace(/\\/g, '/') + + // Mark this as a match + this._emitMatch(index, prefix) + cb() +} + +// Returns either 'DIR', 'FILE', or false +Glob.prototype._stat = function (f, cb) { + var abs = this._makeAbs(f) + var needDir = f.slice(-1) === '/' + + if (f.length > this.maxLength) + return cb() + + if (!this.stat && ownProp(this.cache, abs)) { + var c = this.cache[abs] + + if (Array.isArray(c)) + c = 'DIR' + + // It exists, but maybe not how we need it + if (!needDir || c === 'DIR') + return cb(null, c) + + if (needDir && c === 'FILE') + return cb() + + // otherwise we have to stat, because maybe c=true + // if we know it exists, but not what it is. + } + + var exists + var stat = this.statCache[abs] + if (stat !== undefined) { + if (stat === false) + return cb(null, stat) + else { + var type = stat.isDirectory() ? 'DIR' : 'FILE' + if (needDir && type === 'FILE') + return cb() + else + return cb(null, type, stat) + } + } + + var self = this + var statcb = inflight('stat\0' + abs, lstatcb_) + if (statcb) + self.fs.lstat(abs, statcb) + + function lstatcb_(er, lstat) { + if (lstat && lstat.isSymbolicLink()) { + // If it's a symlink, then treat it as the target, unless + // the target does not exist, then treat it as a file. + return self.fs.stat(abs, function (er, stat) { + if (er) + self._stat2(f, abs, null, lstat, cb) + else + self._stat2(f, abs, er, stat, cb) + }) + } else { + self._stat2(f, abs, er, lstat, cb) + } + } +} + +Glob.prototype._stat2 = function (f, abs, er, stat, cb) { + if (er && (er.code === 'ENOENT' || er.code === 'ENOTDIR')) { + this.statCache[abs] = false + return cb() + } + + var needDir = f.slice(-1) === '/' + this.statCache[abs] = stat + + if (abs.slice(-1) === '/' && stat && !stat.isDirectory()) + return cb(null, false, stat) + + var c = true + if (stat) + c = stat.isDirectory() ? 'DIR' : 'FILE' + this.cache[abs] = this.cache[abs] || c + + if (needDir && c === 'FILE') + return cb() + + return cb(null, c, stat) +} \ No newline at end of file diff --git a/server/libs/archiver/archiverUtils/glob/sync.js b/server/libs/archiver/archiverUtils/glob/sync.js new file mode 100644 index 000000000..7b8444add --- /dev/null +++ b/server/libs/archiver/archiverUtils/glob/sync.js @@ -0,0 +1,483 @@ +module.exports = globSync +globSync.GlobSync = GlobSync + +var rp = require('../fsRealpath') +var minimatch = require('../minimatch') +var path = require('path') +var assert = require('assert') +var isAbsolute = require('path').isAbsolute +var common = require('./common.js') +var setopts = common.setopts +var ownProp = common.ownProp +var childrenIgnored = common.childrenIgnored +var isIgnored = common.isIgnored + +function globSync(pattern, options) { + if (typeof options === 'function' || arguments.length === 3) + throw new TypeError('callback provided to sync glob\n' + + 'See: https://github.com/isaacs/node-glob/issues/167') + + return new GlobSync(pattern, options).found +} + +function GlobSync(pattern, options) { + if (!pattern) + throw new Error('must provide pattern') + + if (typeof options === 'function' || arguments.length === 3) + throw new TypeError('callback provided to sync glob\n' + + 'See: https://github.com/isaacs/node-glob/issues/167') + + if (!(this instanceof GlobSync)) + return new GlobSync(pattern, options) + + setopts(this, pattern, options) + + if (this.noprocess) + return this + + var n = this.minimatch.set.length + this.matches = new Array(n) + for (var i = 0; i < n; i++) { + this._process(this.minimatch.set[i], i, false) + } + this._finish() +} + +GlobSync.prototype._finish = function () { + assert.ok(this instanceof GlobSync) + if (this.realpath) { + var self = this + this.matches.forEach(function (matchset, index) { + var set = self.matches[index] = Object.create(null) + for (var p in matchset) { + try { + p = self._makeAbs(p) + var real = rp.realpathSync(p, self.realpathCache) + set[real] = true + } catch (er) { + if (er.syscall === 'stat') + set[self._makeAbs(p)] = true + else + throw er + } + } + }) + } + common.finish(this) +} + + +GlobSync.prototype._process = function (pattern, index, inGlobStar) { + assert.ok(this instanceof GlobSync) + + // Get the first [n] parts of pattern that are all strings. + var n = 0 + while (typeof pattern[n] === 'string') { + n++ + } + // now n is the index of the first one that is *not* a string. + + // See if there's anything else + var prefix + switch (n) { + // if not, then this is rather simple + case pattern.length: + this._processSimple(pattern.join('/'), index) + return + + case 0: + // pattern *starts* with some non-trivial item. + // going to readdir(cwd), but not include the prefix in matches. + prefix = null + break + + default: + // pattern has some string bits in the front. + // whatever it starts with, whether that's 'absolute' like /foo/bar, + // or 'relative' like '../baz' + prefix = pattern.slice(0, n).join('/') + break + } + + var remain = pattern.slice(n) + + // get the list of entries. + var read + if (prefix === null) + read = '.' + else if (isAbsolute(prefix) || + isAbsolute(pattern.map(function (p) { + return typeof p === 'string' ? p : '[*]' + }).join('/'))) { + if (!prefix || !isAbsolute(prefix)) + prefix = '/' + prefix + read = prefix + } else + read = prefix + + var abs = this._makeAbs(read) + + //if ignored, skip processing + if (childrenIgnored(this, read)) + return + + var isGlobStar = remain[0] === minimatch.GLOBSTAR + if (isGlobStar) + this._processGlobStar(prefix, read, abs, remain, index, inGlobStar) + else + this._processReaddir(prefix, read, abs, remain, index, inGlobStar) +} + + +GlobSync.prototype._processReaddir = function (prefix, read, abs, remain, index, inGlobStar) { + var entries = this._readdir(abs, inGlobStar) + + // if the abs isn't a dir, then nothing can match! + if (!entries) + return + + // It will only match dot entries if it starts with a dot, or if + // dot is set. Stuff like @(.foo|.bar) isn't allowed. + var pn = remain[0] + var negate = !!this.minimatch.negate + var rawGlob = pn._glob + var dotOk = this.dot || rawGlob.charAt(0) === '.' + + var matchedEntries = [] + for (var i = 0; i < entries.length; i++) { + var e = entries[i] + if (e.charAt(0) !== '.' || dotOk) { + var m + if (negate && !prefix) { + m = !e.match(pn) + } else { + m = e.match(pn) + } + if (m) + matchedEntries.push(e) + } + } + + var len = matchedEntries.length + // If there are no matched entries, then nothing matches. + if (len === 0) + return + + // if this is the last remaining pattern bit, then no need for + // an additional stat *unless* the user has specified mark or + // stat explicitly. We know they exist, since readdir returned + // them. + + if (remain.length === 1 && !this.mark && !this.stat) { + if (!this.matches[index]) + this.matches[index] = Object.create(null) + + for (var i = 0; i < len; i++) { + var e = matchedEntries[i] + if (prefix) { + if (prefix.slice(-1) !== '/') + e = prefix + '/' + e + else + e = prefix + e + } + + if (e.charAt(0) === '/' && !this.nomount) { + e = path.join(this.root, e) + } + this._emitMatch(index, e) + } + // This was the last one, and no stats were needed + return + } + + // now test all matched entries as stand-ins for that part + // of the pattern. + remain.shift() + for (var i = 0; i < len; i++) { + var e = matchedEntries[i] + var newPattern + if (prefix) + newPattern = [prefix, e] + else + newPattern = [e] + this._process(newPattern.concat(remain), index, inGlobStar) + } +} + + +GlobSync.prototype._emitMatch = function (index, e) { + if (isIgnored(this, e)) + return + + var abs = this._makeAbs(e) + + if (this.mark) + e = this._mark(e) + + if (this.absolute) { + e = abs + } + + if (this.matches[index][e]) + return + + if (this.nodir) { + var c = this.cache[abs] + if (c === 'DIR' || Array.isArray(c)) + return + } + + this.matches[index][e] = true + + if (this.stat) + this._stat(e) +} + + +GlobSync.prototype._readdirInGlobStar = function (abs) { + // follow all symlinked directories forever + // just proceed as if this is a non-globstar situation + if (this.follow) + return this._readdir(abs, false) + + var entries + var lstat + var stat + try { + lstat = this.fs.lstatSync(abs) + } catch (er) { + if (er.code === 'ENOENT') { + // lstat failed, doesn't exist + return null + } + } + + var isSym = lstat && lstat.isSymbolicLink() + this.symlinks[abs] = isSym + + // If it's not a symlink or a dir, then it's definitely a regular file. + // don't bother doing a readdir in that case. + if (!isSym && lstat && !lstat.isDirectory()) + this.cache[abs] = 'FILE' + else + entries = this._readdir(abs, false) + + return entries +} + +GlobSync.prototype._readdir = function (abs, inGlobStar) { + var entries + + if (inGlobStar && !ownProp(this.symlinks, abs)) + return this._readdirInGlobStar(abs) + + if (ownProp(this.cache, abs)) { + var c = this.cache[abs] + if (!c || c === 'FILE') + return null + + if (Array.isArray(c)) + return c + } + + try { + return this._readdirEntries(abs, this.fs.readdirSync(abs)) + } catch (er) { + this._readdirError(abs, er) + return null + } +} + +GlobSync.prototype._readdirEntries = function (abs, entries) { + // if we haven't asked to stat everything, then just + // assume that everything in there exists, so we can avoid + // having to stat it a second time. + if (!this.mark && !this.stat) { + for (var i = 0; i < entries.length; i++) { + var e = entries[i] + if (abs === '/') + e = abs + e + else + e = abs + '/' + e + this.cache[e] = true + } + } + + this.cache[abs] = entries + + // mark and cache dir-ness + return entries +} + +GlobSync.prototype._readdirError = function (f, er) { + // handle errors, and cache the information + switch (er.code) { + case 'ENOTSUP': // https://github.com/isaacs/node-glob/issues/205 + case 'ENOTDIR': // totally normal. means it *does* exist. + var abs = this._makeAbs(f) + this.cache[abs] = 'FILE' + if (abs === this.cwdAbs) { + var error = new Error(er.code + ' invalid cwd ' + this.cwd) + error.path = this.cwd + error.code = er.code + throw error + } + break + + case 'ENOENT': // not terribly unusual + case 'ELOOP': + case 'ENAMETOOLONG': + case 'UNKNOWN': + this.cache[this._makeAbs(f)] = false + break + + default: // some unusual error. Treat as failure. + this.cache[this._makeAbs(f)] = false + if (this.strict) + throw er + if (!this.silent) + console.error('glob error', er) + break + } +} + +GlobSync.prototype._processGlobStar = function (prefix, read, abs, remain, index, inGlobStar) { + + var entries = this._readdir(abs, inGlobStar) + + // no entries means not a dir, so it can never have matches + // foo.txt/** doesn't match foo.txt + if (!entries) + return + + // test without the globstar, and with every child both below + // and replacing the globstar. + var remainWithoutGlobStar = remain.slice(1) + var gspref = prefix ? [prefix] : [] + var noGlobStar = gspref.concat(remainWithoutGlobStar) + + // the noGlobStar pattern exits the inGlobStar state + this._process(noGlobStar, index, false) + + var len = entries.length + var isSym = this.symlinks[abs] + + // If it's a symlink, and we're in a globstar, then stop + if (isSym && inGlobStar) + return + + for (var i = 0; i < len; i++) { + var e = entries[i] + if (e.charAt(0) === '.' && !this.dot) + continue + + // these two cases enter the inGlobStar state + var instead = gspref.concat(entries[i], remainWithoutGlobStar) + this._process(instead, index, true) + + var below = gspref.concat(entries[i], remain) + this._process(below, index, true) + } +} + +GlobSync.prototype._processSimple = function (prefix, index) { + // XXX review this. Shouldn't it be doing the mounting etc + // before doing stat? kinda weird? + var exists = this._stat(prefix) + + if (!this.matches[index]) + this.matches[index] = Object.create(null) + + // If it doesn't exist, then just mark the lack of results + if (!exists) + return + + if (prefix && isAbsolute(prefix) && !this.nomount) { + var trail = /[\/\\]$/.test(prefix) + if (prefix.charAt(0) === '/') { + prefix = path.join(this.root, prefix) + } else { + prefix = path.resolve(this.root, prefix) + if (trail) + prefix += '/' + } + } + + if (process.platform === 'win32') + prefix = prefix.replace(/\\/g, '/') + + // Mark this as a match + this._emitMatch(index, prefix) +} + +// Returns either 'DIR', 'FILE', or false +GlobSync.prototype._stat = function (f) { + var abs = this._makeAbs(f) + var needDir = f.slice(-1) === '/' + + if (f.length > this.maxLength) + return false + + if (!this.stat && ownProp(this.cache, abs)) { + var c = this.cache[abs] + + if (Array.isArray(c)) + c = 'DIR' + + // It exists, but maybe not how we need it + if (!needDir || c === 'DIR') + return c + + if (needDir && c === 'FILE') + return false + + // otherwise we have to stat, because maybe c=true + // if we know it exists, but not what it is. + } + + var exists + var stat = this.statCache[abs] + if (!stat) { + var lstat + try { + lstat = this.fs.lstatSync(abs) + } catch (er) { + if (er && (er.code === 'ENOENT' || er.code === 'ENOTDIR')) { + this.statCache[abs] = false + return false + } + } + + if (lstat && lstat.isSymbolicLink()) { + try { + stat = this.fs.statSync(abs) + } catch (er) { + stat = lstat + } + } else { + stat = lstat + } + } + + this.statCache[abs] = stat + + var c = true + if (stat) + c = stat.isDirectory() ? 'DIR' : 'FILE' + + this.cache[abs] = this.cache[abs] || c + + if (needDir && c === 'FILE') + return false + + return c +} + +GlobSync.prototype._mark = function (p) { + return common.mark(this, p) +} + +GlobSync.prototype._makeAbs = function (f) { + return common.makeAbs(this, f) +} \ No newline at end of file diff --git a/server/libs/archiver/archiverUtils/index.js b/server/libs/archiver/archiverUtils/index.js new file mode 100644 index 000000000..fb21d26da --- /dev/null +++ b/server/libs/archiver/archiverUtils/index.js @@ -0,0 +1,162 @@ +/** + * archiver-utils + * + * Copyright (c) 2015 Chris Talkington. + * Licensed under the MIT license. + * https://github.com/archiverjs/archiver-utils/blob/master/LICENSE + */ +var fs = require('graceful-fs'); +var path = require('path'); +// var lazystream = require('./lazystream'); +var lazystream = require('./lazystream') +var normalizePath = require('../normalize-path'); + +var Stream = require('stream').Stream; +var PassThrough = require('./readableStream').PassThrough; + +var utils = module.exports = {}; +utils.file = require('./file.js'); + +utils.collectStream = function (source, callback) { + var collection = []; + var size = 0; + + source.on('error', callback); + + source.on('data', function (chunk) { + collection.push(chunk); + size += chunk.length; + }); + + source.on('end', function () { + var buf = Buffer.alloc(size); + var offset = 0; + + collection.forEach(function (data) { + data.copy(buf, offset); + offset += data.length; + }); + + callback(null, buf); + }); +}; + +utils.dateify = function (dateish) { + dateish = dateish || new Date(); + + if (dateish instanceof Date) { + dateish = dateish; + } else if (typeof dateish === 'string') { + dateish = new Date(dateish); + } else { + dateish = new Date(); + } + + return dateish; +}; + +// this is slightly different from lodash version +utils.defaults = function (object, source) { + object = Object(object) + const sources = [source] + const objectProto = Object.prototype + const hasOwnProperty = objectProto.hasOwnProperty + sources.forEach((source) => { + if (source != null) { + source = Object(source) + for (const key in source) { + const value = object[key] + if (value === undefined || + (value == objectProto[key] && !hasOwnProperty.call(object, key))) { + object[key] = source[key] + } + } + } + }) + return object +}; + +utils.isStream = function (source) { + return source instanceof Stream; +}; + +utils.lazyReadStream = function (filepath) { + return new lazystream.Readable(function () { + return fs.createReadStream(filepath); + }); +}; + +utils.normalizeInputSource = function (source) { + if (source === null) { + return Buffer.alloc(0); + } else if (typeof source === 'string') { + return Buffer.from(source); + } else if (utils.isStream(source)) { + // Always pipe through a PassThrough stream to guarantee pausing the stream if it's already flowing, + // since it will only be processed in a (distant) future iteration of the event loop, and will lose + // data if already flowing now. + return source.pipe(new PassThrough()); + } + + return source; +}; + +utils.sanitizePath = function (filepath) { + return normalizePath(filepath, false).replace(/^\w+:/, '').replace(/^(\.\.\/|\/)+/, ''); +}; + +utils.trailingSlashIt = function (str) { + return str.slice(-1) !== '/' ? str + '/' : str; +}; + +utils.unixifyPath = function (filepath) { + return normalizePath(filepath, false).replace(/^\w+:/, ''); +}; + +utils.walkdir = function (dirpath, base, callback) { + var results = []; + + if (typeof base === 'function') { + callback = base; + base = dirpath; + } + + fs.readdir(dirpath, function (err, list) { + var i = 0; + var file; + var filepath; + + if (err) { + return callback(err); + } + + (function next() { + file = list[i++]; + + if (!file) { + return callback(null, results); + } + + filepath = path.join(dirpath, file); + + fs.stat(filepath, function (err, stats) { + results.push({ + path: filepath, + relative: path.relative(base, filepath).replace(/\\/g, '/'), + stats: stats + }); + + if (stats && stats.isDirectory()) { + utils.walkdir(filepath, base, function (err, res) { + res.forEach(function (dirEntry) { + results.push(dirEntry); + }); + next(); + }); + } else { + next(); + } + }); + })(); + }); +}; diff --git a/server/libs/archiver/archiverUtils/inflight/LICENSE b/server/libs/archiver/archiverUtils/inflight/LICENSE new file mode 100644 index 000000000..38123a014 --- /dev/null +++ b/server/libs/archiver/archiverUtils/inflight/LICENSE @@ -0,0 +1,15 @@ +The ISC License + +Copyright (c) Isaac Z. Schlueter + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR +IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. \ No newline at end of file diff --git a/server/libs/archiver/archiverUtils/inflight/index.js b/server/libs/archiver/archiverUtils/inflight/index.js new file mode 100644 index 000000000..cbf5388fc --- /dev/null +++ b/server/libs/archiver/archiverUtils/inflight/index.js @@ -0,0 +1,54 @@ +var wrappy = require('../wrappy') +var reqs = Object.create(null) +var once = require('../../../lodash.once') + +module.exports = wrappy(inflight) + +function inflight(key, cb) { + if (reqs[key]) { + reqs[key].push(cb) + return null + } else { + reqs[key] = [cb] + return makeres(key) + } +} + +function makeres(key) { + return once(function RES() { + var cbs = reqs[key] + var len = cbs.length + var args = slice(arguments) + + // XXX It's somewhat ambiguous whether a new callback added in this + // pass should be queued for later execution if something in the + // list of callbacks throws, or if it should just be discarded. + // However, it's such an edge case that it hardly matters, and either + // choice is likely as surprising as the other. + // As it happens, we do go ahead and schedule it for later execution. + try { + for (var i = 0; i < len; i++) { + cbs[i].apply(null, args) + } + } finally { + if (cbs.length > len) { + // added more in the interim. + // de-zalgo, just in case, but don't call again. + cbs.splice(0, len) + process.nextTick(function () { + RES.apply(null, args) + }) + } else { + delete reqs[key] + } + } + }) +} + +function slice(args) { + var length = args.length + var array = [] + + for (var i = 0; i < length; i++) array[i] = args[i] + return array +} \ No newline at end of file diff --git a/server/libs/archiver/archiverUtils/lazystream/LICENSE b/server/libs/archiver/archiverUtils/lazystream/LICENSE new file mode 100644 index 000000000..3d2b29d91 --- /dev/null +++ b/server/libs/archiver/archiverUtils/lazystream/LICENSE @@ -0,0 +1,22 @@ +Copyright (c) 2013 J. Pommerening, contributors. + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. diff --git a/server/libs/archiver/archiverUtils/lazystream/index.js b/server/libs/archiver/archiverUtils/lazystream/index.js new file mode 100644 index 000000000..cd18cd55d --- /dev/null +++ b/server/libs/archiver/archiverUtils/lazystream/index.js @@ -0,0 +1,57 @@ +// +// Source: https://github.com/jpommerening/node-lazystream +// + +var util = require('util'); +var PassThrough = require('./readable-stream/passthrough') + +module.exports = { + Readable: Readable, + Writable: Writable +}; + +util.inherits(Readable, PassThrough); +util.inherits(Writable, PassThrough); + +// Patch the given method of instance so that the callback +// is executed once, before the actual method is called the +// first time. +function beforeFirstCall(instance, method, callback) { + instance[method] = function () { + delete instance[method]; + callback.apply(this, arguments); + return this[method].apply(this, arguments); + }; +} + +function Readable(fn, options) { + if (!(this instanceof Readable)) + return new Readable(fn, options); + + PassThrough.call(this, options); + + beforeFirstCall(this, '_read', function () { + var source = fn.call(this, options); + var emit = this.emit.bind(this, 'error'); + source.on('error', emit); + source.pipe(this); + }); + + this.emit('readable'); +} + +function Writable(fn, options) { + if (!(this instanceof Writable)) + return new Writable(fn, options); + + PassThrough.call(this, options); + + beforeFirstCall(this, '_write', function () { + var destination = fn.call(this, options); + var emit = this.emit.bind(this, 'error'); + destination.on('error', emit); + this.pipe(destination); + }); + + this.emit('writable'); +} diff --git a/server/libs/archiver/archiverUtils/lazystream/readable-stream/lib/_stream_duplex.js b/server/libs/archiver/archiverUtils/lazystream/readable-stream/lib/_stream_duplex.js new file mode 100644 index 000000000..1b8f7a407 --- /dev/null +++ b/server/libs/archiver/archiverUtils/lazystream/readable-stream/lib/_stream_duplex.js @@ -0,0 +1,133 @@ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +// a duplex stream is just a stream that is both readable and writable. +// Since JS doesn't have multiple prototypal inheritance, this class +// prototypally inherits from Readable, and then parasitically from +// Writable. + +'use strict'; + +/**/ + +// var pna = require('process-nextick-args'); +var pna = process +/**/ + +/**/ +var objectKeys = Object.keys || function (obj) { + var keys = []; + for (var key in obj) { + keys.push(key); + } return keys; +}; +/**/ + +module.exports = Duplex; + +/**/ +var util = require('util') +// var util = Object.create(require('core-util-is')); +// util.inherits = require('inherits'); +/**/ + +var Readable = require('./_stream_readable'); +var Writable = require('./_stream_writable'); + +util.inherits(Duplex, Readable); + +{ + // avoid scope creep, the keys array can then be collected + var keys = objectKeys(Writable.prototype); + for (var v = 0; v < keys.length; v++) { + var method = keys[v]; + if (!Duplex.prototype[method]) Duplex.prototype[method] = Writable.prototype[method]; + } +} + +function Duplex(options) { + if (!(this instanceof Duplex)) return new Duplex(options); + + Readable.call(this, options); + Writable.call(this, options); + + if (options && options.readable === false) this.readable = false; + + if (options && options.writable === false) this.writable = false; + + this.allowHalfOpen = true; + if (options && options.allowHalfOpen === false) this.allowHalfOpen = false; + + this.once('end', onend); +} + +Object.defineProperty(Duplex.prototype, 'writableHighWaterMark', { + // making it explicit this property is not enumerable + // because otherwise some prototype manipulation in + // userland will fail + enumerable: false, + get: function () { + return this._writableState.highWaterMark; + } +}); + +// the no-half-open enforcer +function onend() { + // if we allow half-open state, or if the writable side ended, + // then we're ok. + if (this.allowHalfOpen || this._writableState.ended) return; + + // no more data can be written. + // But allow more writes to happen in this tick. + pna.nextTick(onEndNT, this); +} + +function onEndNT(self) { + self.end(); +} + +Object.defineProperty(Duplex.prototype, 'destroyed', { + get: function () { + if (this._readableState === undefined || this._writableState === undefined) { + return false; + } + return this._readableState.destroyed && this._writableState.destroyed; + }, + set: function (value) { + // we ignore the value if the stream + // has not been initialized yet + if (this._readableState === undefined || this._writableState === undefined) { + return; + } + + // backward compatibility, the user is explicitly + // managing destroyed + this._readableState.destroyed = value; + this._writableState.destroyed = value; + } +}); + +Duplex.prototype._destroy = function (err, cb) { + this.push(null); + this.end(); + + pna.nextTick(cb, err); +}; \ No newline at end of file diff --git a/server/libs/archiver/archiverUtils/lazystream/readable-stream/lib/_stream_passthrough.js b/server/libs/archiver/archiverUtils/lazystream/readable-stream/lib/_stream_passthrough.js new file mode 100644 index 000000000..d698b92d2 --- /dev/null +++ b/server/libs/archiver/archiverUtils/lazystream/readable-stream/lib/_stream_passthrough.js @@ -0,0 +1,47 @@ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +// a passthrough stream. +// basically just the most minimal sort of Transform stream. +// Every written chunk gets output as-is. + +'use strict'; + +module.exports = PassThrough; + +var Transform = require('./_stream_transform'); + +/**/ +var util = require('util') +// util.inherits = require('inherits'); +/**/ + +util.inherits(PassThrough, Transform); + +function PassThrough(options) { + if (!(this instanceof PassThrough)) return new PassThrough(options); + + Transform.call(this, options); +} + +PassThrough.prototype._transform = function (chunk, encoding, cb) { + cb(null, chunk); +}; \ No newline at end of file diff --git a/server/libs/archiver/archiverUtils/lazystream/readable-stream/lib/_stream_readable.js b/server/libs/archiver/archiverUtils/lazystream/readable-stream/lib/_stream_readable.js new file mode 100644 index 000000000..ec09a26e8 --- /dev/null +++ b/server/libs/archiver/archiverUtils/lazystream/readable-stream/lib/_stream_readable.js @@ -0,0 +1,1023 @@ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +'use strict'; + +/**/ + +// var pna = require('process-nextick-args'); +var pna = process +/**/ + +module.exports = Readable; + +/**/ +// var isArray = require('isarray'); +var isArray = Array.isArray +/**/ + +/**/ +var Duplex; +/**/ + +Readable.ReadableState = ReadableState; + +/**/ +var EE = require('events').EventEmitter; + +var EElistenerCount = function (emitter, type) { + return emitter.listeners(type).length; +}; +/**/ + +/**/ +var Stream = require('./internal/streams/stream'); +/**/ + +/**/ + +// var Buffer = require('safe-buffer').Buffer; +var Buffer = require('../../../safeBuffer').Buffer +var OurUint8Array = global.Uint8Array || function () { }; +function _uint8ArrayToBuffer(chunk) { + return Buffer.from(chunk); +} +function _isUint8Array(obj) { + return Buffer.isBuffer(obj) || obj instanceof OurUint8Array; +} + +/**/ + +/**/ +var util = require('util') +// var util = Object.create(require('core-util-is')); +// util.inherits = require('inherits'); +/**/ + +/**/ +var debugUtil = require('util'); +var debug = void 0; +if (debugUtil && debugUtil.debuglog) { + debug = debugUtil.debuglog('stream'); +} else { + debug = function () { }; +} +/**/ + +var BufferList = require('./internal/streams/BufferList'); +var destroyImpl = require('./internal/streams/destroy'); +var StringDecoder; + +util.inherits(Readable, Stream); + +var kProxyEvents = ['error', 'close', 'destroy', 'pause', 'resume']; + +function prependListener(emitter, event, fn) { + // Sadly this is not cacheable as some libraries bundle their own + // event emitter implementation with them. + if (typeof emitter.prependListener === 'function') return emitter.prependListener(event, fn); + + // This is a hack to make sure that our error handler is attached before any + // userland ones. NEVER DO THIS. This is here only because this code needs + // to continue to work with older versions of Node.js that do not include + // the prependListener() method. The goal is to eventually remove this hack. + if (!emitter._events || !emitter._events[event]) emitter.on(event, fn); else if (isArray(emitter._events[event])) emitter._events[event].unshift(fn); else emitter._events[event] = [fn, emitter._events[event]]; +} + +function ReadableState(options, stream) { + Duplex = Duplex || require('./_stream_duplex'); + + options = options || {}; + + // Duplex streams are both readable and writable, but share + // the same options object. + // However, some cases require setting options to different + // values for the readable and the writable sides of the duplex stream. + // These options can be provided separately as readableXXX and writableXXX. + var isDuplex = stream instanceof Duplex; + + // object stream flag. Used to make read(n) ignore n and to + // make all the buffer merging and length checks go away + this.objectMode = !!options.objectMode; + + if (isDuplex) this.objectMode = this.objectMode || !!options.readableObjectMode; + + // the point at which it stops calling _read() to fill the buffer + // Note: 0 is a valid value, means "don't call _read preemptively ever" + var hwm = options.highWaterMark; + var readableHwm = options.readableHighWaterMark; + var defaultHwm = this.objectMode ? 16 : 16 * 1024; + + if (hwm || hwm === 0) this.highWaterMark = hwm; else if (isDuplex && (readableHwm || readableHwm === 0)) this.highWaterMark = readableHwm; else this.highWaterMark = defaultHwm; + + // cast to ints. + this.highWaterMark = Math.floor(this.highWaterMark); + + // A linked list is used to store data chunks instead of an array because the + // linked list can remove elements from the beginning faster than + // array.shift() + this.buffer = new BufferList(); + this.length = 0; + this.pipes = null; + this.pipesCount = 0; + this.flowing = null; + this.ended = false; + this.endEmitted = false; + this.reading = false; + + // a flag to be able to tell if the event 'readable'/'data' is emitted + // immediately, or on a later tick. We set this to true at first, because + // any actions that shouldn't happen until "later" should generally also + // not happen before the first read call. + this.sync = true; + + // whenever we return null, then we set a flag to say + // that we're awaiting a 'readable' event emission. + this.needReadable = false; + this.emittedReadable = false; + this.readableListening = false; + this.resumeScheduled = false; + + // has it been destroyed + this.destroyed = false; + + // Crypto is kind of old and crusty. Historically, its default string + // encoding is 'binary' so we have to make this configurable. + // Everything else in the universe uses 'utf8', though. + this.defaultEncoding = options.defaultEncoding || 'utf8'; + + // the number of writers that are awaiting a drain event in .pipe()s + this.awaitDrain = 0; + + // if true, a maybeReadMore has been scheduled + this.readingMore = false; + + this.decoder = null; + this.encoding = null; + if (options.encoding) { + if (!StringDecoder) StringDecoder = require('string_decoder/').StringDecoder; + this.decoder = new StringDecoder(options.encoding); + this.encoding = options.encoding; + } +} + +function Readable(options) { + Duplex = Duplex || require('./_stream_duplex'); + + if (!(this instanceof Readable)) return new Readable(options); + + this._readableState = new ReadableState(options, this); + + // legacy + this.readable = true; + + if (options) { + if (typeof options.read === 'function') this._read = options.read; + + if (typeof options.destroy === 'function') this._destroy = options.destroy; + } + + Stream.call(this); +} + +Object.defineProperty(Readable.prototype, 'destroyed', { + get: function () { + if (this._readableState === undefined) { + return false; + } + return this._readableState.destroyed; + }, + set: function (value) { + // we ignore the value if the stream + // has not been initialized yet + if (!this._readableState) { + return; + } + + // backward compatibility, the user is explicitly + // managing destroyed + this._readableState.destroyed = value; + } +}); + +Readable.prototype.destroy = destroyImpl.destroy; +Readable.prototype._undestroy = destroyImpl.undestroy; +Readable.prototype._destroy = function (err, cb) { + this.push(null); + cb(err); +}; + +// Manually shove something into the read() buffer. +// This returns true if the highWaterMark has not been hit yet, +// similar to how Writable.write() returns true if you should +// write() some more. +Readable.prototype.push = function (chunk, encoding) { + var state = this._readableState; + var skipChunkCheck; + + if (!state.objectMode) { + if (typeof chunk === 'string') { + encoding = encoding || state.defaultEncoding; + if (encoding !== state.encoding) { + chunk = Buffer.from(chunk, encoding); + encoding = ''; + } + skipChunkCheck = true; + } + } else { + skipChunkCheck = true; + } + + return readableAddChunk(this, chunk, encoding, false, skipChunkCheck); +}; + +// Unshift should *always* be something directly out of read() +Readable.prototype.unshift = function (chunk) { + return readableAddChunk(this, chunk, null, true, false); +}; + +function readableAddChunk(stream, chunk, encoding, addToFront, skipChunkCheck) { + var state = stream._readableState; + if (chunk === null) { + state.reading = false; + onEofChunk(stream, state); + } else { + var er; + if (!skipChunkCheck) er = chunkInvalid(state, chunk); + if (er) { + stream.emit('error', er); + } else if (state.objectMode || chunk && chunk.length > 0) { + if (typeof chunk !== 'string' && !state.objectMode && Object.getPrototypeOf(chunk) !== Buffer.prototype) { + chunk = _uint8ArrayToBuffer(chunk); + } + + if (addToFront) { + if (state.endEmitted) stream.emit('error', new Error('stream.unshift() after end event')); else addChunk(stream, state, chunk, true); + } else if (state.ended) { + stream.emit('error', new Error('stream.push() after EOF')); + } else { + state.reading = false; + if (state.decoder && !encoding) { + chunk = state.decoder.write(chunk); + if (state.objectMode || chunk.length !== 0) addChunk(stream, state, chunk, false); else maybeReadMore(stream, state); + } else { + addChunk(stream, state, chunk, false); + } + } + } else if (!addToFront) { + state.reading = false; + } + } + + return needMoreData(state); +} + +function addChunk(stream, state, chunk, addToFront) { + if (state.flowing && state.length === 0 && !state.sync) { + stream.emit('data', chunk); + stream.read(0); + } else { + // update the buffer info. + state.length += state.objectMode ? 1 : chunk.length; + if (addToFront) state.buffer.unshift(chunk); else state.buffer.push(chunk); + + if (state.needReadable) emitReadable(stream); + } + maybeReadMore(stream, state); +} + +function chunkInvalid(state, chunk) { + var er; + if (!_isUint8Array(chunk) && typeof chunk !== 'string' && chunk !== undefined && !state.objectMode) { + er = new TypeError('Invalid non-string/buffer chunk'); + } + return er; +} + +// if it's past the high water mark, we can push in some more. +// Also, if we have no data yet, we can stand some +// more bytes. This is to work around cases where hwm=0, +// such as the repl. Also, if the push() triggered a +// readable event, and the user called read(largeNumber) such that +// needReadable was set, then we ought to push more, so that another +// 'readable' event will be triggered. +function needMoreData(state) { + return !state.ended && (state.needReadable || state.length < state.highWaterMark || state.length === 0); +} + +Readable.prototype.isPaused = function () { + return this._readableState.flowing === false; +}; + +// backwards compatibility. +Readable.prototype.setEncoding = function (enc) { + if (!StringDecoder) StringDecoder = require('string_decoder/').StringDecoder; + this._readableState.decoder = new StringDecoder(enc); + this._readableState.encoding = enc; + return this; +}; + +// Don't raise the hwm > 8MB +var MAX_HWM = 0x800000; +function computeNewHighWaterMark(n) { + if (n >= MAX_HWM) { + n = MAX_HWM; + } else { + // Get the next highest power of 2 to prevent increasing hwm excessively in + // tiny amounts + n--; + n |= n >>> 1; + n |= n >>> 2; + n |= n >>> 4; + n |= n >>> 8; + n |= n >>> 16; + n++; + } + return n; +} + +// This function is designed to be inlinable, so please take care when making +// changes to the function body. +function howMuchToRead(n, state) { + if (n <= 0 || state.length === 0 && state.ended) return 0; + if (state.objectMode) return 1; + if (n !== n) { + // Only flow one buffer at a time + if (state.flowing && state.length) return state.buffer.head.data.length; else return state.length; + } + // If we're asking for more than the current hwm, then raise the hwm. + if (n > state.highWaterMark) state.highWaterMark = computeNewHighWaterMark(n); + if (n <= state.length) return n; + // Don't have enough + if (!state.ended) { + state.needReadable = true; + return 0; + } + return state.length; +} + +// you can override either this method, or the async _read(n) below. +Readable.prototype.read = function (n) { + debug('read', n); + n = parseInt(n, 10); + var state = this._readableState; + var nOrig = n; + + if (n !== 0) state.emittedReadable = false; + + // if we're doing read(0) to trigger a readable event, but we + // already have a bunch of data in the buffer, then just trigger + // the 'readable' event and move on. + if (n === 0 && state.needReadable && (state.length >= state.highWaterMark || state.ended)) { + debug('read: emitReadable', state.length, state.ended); + if (state.length === 0 && state.ended) endReadable(this); else emitReadable(this); + return null; + } + + n = howMuchToRead(n, state); + + // if we've ended, and we're now clear, then finish it up. + if (n === 0 && state.ended) { + if (state.length === 0) endReadable(this); + return null; + } + + // All the actual chunk generation logic needs to be + // *below* the call to _read. The reason is that in certain + // synthetic stream cases, such as passthrough streams, _read + // may be a completely synchronous operation which may change + // the state of the read buffer, providing enough data when + // before there was *not* enough. + // + // So, the steps are: + // 1. Figure out what the state of things will be after we do + // a read from the buffer. + // + // 2. If that resulting state will trigger a _read, then call _read. + // Note that this may be asynchronous, or synchronous. Yes, it is + // deeply ugly to write APIs this way, but that still doesn't mean + // that the Readable class should behave improperly, as streams are + // designed to be sync/async agnostic. + // Take note if the _read call is sync or async (ie, if the read call + // has returned yet), so that we know whether or not it's safe to emit + // 'readable' etc. + // + // 3. Actually pull the requested chunks out of the buffer and return. + + // if we need a readable event, then we need to do some reading. + var doRead = state.needReadable; + debug('need readable', doRead); + + // if we currently have less than the highWaterMark, then also read some + if (state.length === 0 || state.length - n < state.highWaterMark) { + doRead = true; + debug('length less than watermark', doRead); + } + + // however, if we've ended, then there's no point, and if we're already + // reading, then it's unnecessary. + if (state.ended || state.reading) { + doRead = false; + debug('reading or ended', doRead); + } else if (doRead) { + debug('do read'); + state.reading = true; + state.sync = true; + // if the length is currently zero, then we *need* a readable event. + if (state.length === 0) state.needReadable = true; + // call internal read method + this._read(state.highWaterMark); + state.sync = false; + // If _read pushed data synchronously, then `reading` will be false, + // and we need to re-evaluate how much data we can return to the user. + if (!state.reading) n = howMuchToRead(nOrig, state); + } + + var ret; + if (n > 0) ret = fromList(n, state); else ret = null; + + if (ret === null) { + state.needReadable = true; + n = 0; + } else { + state.length -= n; + } + + if (state.length === 0) { + // If we have nothing in the buffer, then we want to know + // as soon as we *do* get something into the buffer. + if (!state.ended) state.needReadable = true; + + // If we tried to read() past the EOF, then emit end on the next tick. + if (nOrig !== n && state.ended) endReadable(this); + } + + if (ret !== null) this.emit('data', ret); + + return ret; +}; + +function onEofChunk(stream, state) { + if (state.ended) return; + if (state.decoder) { + var chunk = state.decoder.end(); + if (chunk && chunk.length) { + state.buffer.push(chunk); + state.length += state.objectMode ? 1 : chunk.length; + } + } + state.ended = true; + + // emit 'readable' now to make sure it gets picked up. + emitReadable(stream); +} + +// Don't emit readable right away in sync mode, because this can trigger +// another read() call => stack overflow. This way, it might trigger +// a nextTick recursion warning, but that's not so bad. +function emitReadable(stream) { + var state = stream._readableState; + state.needReadable = false; + if (!state.emittedReadable) { + debug('emitReadable', state.flowing); + state.emittedReadable = true; + if (state.sync) pna.nextTick(emitReadable_, stream); else emitReadable_(stream); + } +} + +function emitReadable_(stream) { + debug('emit readable'); + stream.emit('readable'); + flow(stream); +} + +// at this point, the user has presumably seen the 'readable' event, +// and called read() to consume some data. that may have triggered +// in turn another _read(n) call, in which case reading = true if +// it's in progress. +// However, if we're not ended, or reading, and the length < hwm, +// then go ahead and try to read some more preemptively. +function maybeReadMore(stream, state) { + if (!state.readingMore) { + state.readingMore = true; + pna.nextTick(maybeReadMore_, stream, state); + } +} + +function maybeReadMore_(stream, state) { + var len = state.length; + while (!state.reading && !state.flowing && !state.ended && state.length < state.highWaterMark) { + debug('maybeReadMore read 0'); + stream.read(0); + if (len === state.length) + // didn't get any data, stop spinning. + break; else len = state.length; + } + state.readingMore = false; +} + +// abstract method. to be overridden in specific implementation classes. +// call cb(er, data) where data is <= n in length. +// for virtual (non-string, non-buffer) streams, "length" is somewhat +// arbitrary, and perhaps not very meaningful. +Readable.prototype._read = function (n) { + this.emit('error', new Error('_read() is not implemented')); +}; + +Readable.prototype.pipe = function (dest, pipeOpts) { + var src = this; + var state = this._readableState; + + switch (state.pipesCount) { + case 0: + state.pipes = dest; + break; + case 1: + state.pipes = [state.pipes, dest]; + break; + default: + state.pipes.push(dest); + break; + } + state.pipesCount += 1; + debug('pipe count=%d opts=%j', state.pipesCount, pipeOpts); + + var doEnd = (!pipeOpts || pipeOpts.end !== false) && dest !== process.stdout && dest !== process.stderr; + + var endFn = doEnd ? onend : unpipe; + if (state.endEmitted) pna.nextTick(endFn); else src.once('end', endFn); + + dest.on('unpipe', onunpipe); + function onunpipe(readable, unpipeInfo) { + debug('onunpipe'); + if (readable === src) { + if (unpipeInfo && unpipeInfo.hasUnpiped === false) { + unpipeInfo.hasUnpiped = true; + cleanup(); + } + } + } + + function onend() { + debug('onend'); + dest.end(); + } + + // when the dest drains, it reduces the awaitDrain counter + // on the source. This would be more elegant with a .once() + // handler in flow(), but adding and removing repeatedly is + // too slow. + var ondrain = pipeOnDrain(src); + dest.on('drain', ondrain); + + var cleanedUp = false; + function cleanup() { + debug('cleanup'); + // cleanup event handlers once the pipe is broken + dest.removeListener('close', onclose); + dest.removeListener('finish', onfinish); + dest.removeListener('drain', ondrain); + dest.removeListener('error', onerror); + dest.removeListener('unpipe', onunpipe); + src.removeListener('end', onend); + src.removeListener('end', unpipe); + src.removeListener('data', ondata); + + cleanedUp = true; + + // if the reader is waiting for a drain event from this + // specific writer, then it would cause it to never start + // flowing again. + // So, if this is awaiting a drain, then we just call it now. + // If we don't know, then assume that we are waiting for one. + if (state.awaitDrain && (!dest._writableState || dest._writableState.needDrain)) ondrain(); + } + + // If the user pushes more data while we're writing to dest then we'll end up + // in ondata again. However, we only want to increase awaitDrain once because + // dest will only emit one 'drain' event for the multiple writes. + // => Introduce a guard on increasing awaitDrain. + var increasedAwaitDrain = false; + src.on('data', ondata); + function ondata(chunk) { + debug('ondata'); + increasedAwaitDrain = false; + var ret = dest.write(chunk); + if (false === ret && !increasedAwaitDrain) { + // If the user unpiped during `dest.write()`, it is possible + // to get stuck in a permanently paused state if that write + // also returned false. + // => Check whether `dest` is still a piping destination. + if ((state.pipesCount === 1 && state.pipes === dest || state.pipesCount > 1 && indexOf(state.pipes, dest) !== -1) && !cleanedUp) { + debug('false write response, pause', src._readableState.awaitDrain); + src._readableState.awaitDrain++; + increasedAwaitDrain = true; + } + src.pause(); + } + } + + // if the dest has an error, then stop piping into it. + // however, don't suppress the throwing behavior for this. + function onerror(er) { + debug('onerror', er); + unpipe(); + dest.removeListener('error', onerror); + if (EElistenerCount(dest, 'error') === 0) dest.emit('error', er); + } + + // Make sure our error handler is attached before userland ones. + prependListener(dest, 'error', onerror); + + // Both close and finish should trigger unpipe, but only once. + function onclose() { + dest.removeListener('finish', onfinish); + unpipe(); + } + dest.once('close', onclose); + function onfinish() { + debug('onfinish'); + dest.removeListener('close', onclose); + unpipe(); + } + dest.once('finish', onfinish); + + function unpipe() { + debug('unpipe'); + src.unpipe(dest); + } + + // tell the dest that it's being piped to + dest.emit('pipe', src); + + // start the flow if it hasn't been started already. + if (!state.flowing) { + debug('pipe resume'); + src.resume(); + } + + return dest; +}; + +function pipeOnDrain(src) { + return function () { + var state = src._readableState; + debug('pipeOnDrain', state.awaitDrain); + if (state.awaitDrain) state.awaitDrain--; + if (state.awaitDrain === 0 && EElistenerCount(src, 'data')) { + state.flowing = true; + flow(src); + } + }; +} + +Readable.prototype.unpipe = function (dest) { + var state = this._readableState; + var unpipeInfo = { hasUnpiped: false }; + + // if we're not piping anywhere, then do nothing. + if (state.pipesCount === 0) return this; + + // just one destination. most common case. + if (state.pipesCount === 1) { + // passed in one, but it's not the right one. + if (dest && dest !== state.pipes) return this; + + if (!dest) dest = state.pipes; + + // got a match. + state.pipes = null; + state.pipesCount = 0; + state.flowing = false; + if (dest) dest.emit('unpipe', this, unpipeInfo); + return this; + } + + // slow case. multiple pipe destinations. + + if (!dest) { + // remove all. + var dests = state.pipes; + var len = state.pipesCount; + state.pipes = null; + state.pipesCount = 0; + state.flowing = false; + + for (var i = 0; i < len; i++) { + dests[i].emit('unpipe', this, unpipeInfo); + } return this; + } + + // try to find the right one. + var index = indexOf(state.pipes, dest); + if (index === -1) return this; + + state.pipes.splice(index, 1); + state.pipesCount -= 1; + if (state.pipesCount === 1) state.pipes = state.pipes[0]; + + dest.emit('unpipe', this, unpipeInfo); + + return this; +}; + +// set up data events if they are asked for +// Ensure readable listeners eventually get something +Readable.prototype.on = function (ev, fn) { + var res = Stream.prototype.on.call(this, ev, fn); + + if (ev === 'data') { + // Start flowing on next tick if stream isn't explicitly paused + if (this._readableState.flowing !== false) this.resume(); + } else if (ev === 'readable') { + var state = this._readableState; + if (!state.endEmitted && !state.readableListening) { + state.readableListening = state.needReadable = true; + state.emittedReadable = false; + if (!state.reading) { + pna.nextTick(nReadingNextTick, this); + } else if (state.length) { + emitReadable(this); + } + } + } + + return res; +}; +Readable.prototype.addListener = Readable.prototype.on; + +function nReadingNextTick(self) { + debug('readable nexttick read 0'); + self.read(0); +} + +// pause() and resume() are remnants of the legacy readable stream API +// If the user uses them, then switch into old mode. +Readable.prototype.resume = function () { + var state = this._readableState; + if (!state.flowing) { + debug('resume'); + state.flowing = true; + resume(this, state); + } + return this; +}; + +function resume(stream, state) { + if (!state.resumeScheduled) { + state.resumeScheduled = true; + pna.nextTick(resume_, stream, state); + } +} + +function resume_(stream, state) { + if (!state.reading) { + debug('resume read 0'); + stream.read(0); + } + + state.resumeScheduled = false; + state.awaitDrain = 0; + stream.emit('resume'); + flow(stream); + if (state.flowing && !state.reading) stream.read(0); +} + +Readable.prototype.pause = function () { + debug('call pause flowing=%j', this._readableState.flowing); + if (false !== this._readableState.flowing) { + debug('pause'); + this._readableState.flowing = false; + this.emit('pause'); + } + return this; +}; + +function flow(stream) { + var state = stream._readableState; + debug('flow', state.flowing); + while (state.flowing && stream.read() !== null) { } +} + +// wrap an old-style stream as the async data source. +// This is *not* part of the readable stream interface. +// It is an ugly unfortunate mess of history. +Readable.prototype.wrap = function (stream) { + var _this = this; + + var state = this._readableState; + var paused = false; + + stream.on('end', function () { + debug('wrapped end'); + if (state.decoder && !state.ended) { + var chunk = state.decoder.end(); + if (chunk && chunk.length) _this.push(chunk); + } + + _this.push(null); + }); + + stream.on('data', function (chunk) { + debug('wrapped data'); + if (state.decoder) chunk = state.decoder.write(chunk); + + // don't skip over falsy values in objectMode + if (state.objectMode && (chunk === null || chunk === undefined)) return; else if (!state.objectMode && (!chunk || !chunk.length)) return; + + var ret = _this.push(chunk); + if (!ret) { + paused = true; + stream.pause(); + } + }); + + // proxy all the other methods. + // important when wrapping filters and duplexes. + for (var i in stream) { + if (this[i] === undefined && typeof stream[i] === 'function') { + this[i] = function (method) { + return function () { + return stream[method].apply(stream, arguments); + }; + }(i); + } + } + + // proxy certain important events. + for (var n = 0; n < kProxyEvents.length; n++) { + stream.on(kProxyEvents[n], this.emit.bind(this, kProxyEvents[n])); + } + + // when we try to consume some more bytes, simply unpause the + // underlying stream. + this._read = function (n) { + debug('wrapped _read', n); + if (paused) { + paused = false; + stream.resume(); + } + }; + + return this; +}; + +Object.defineProperty(Readable.prototype, 'readableHighWaterMark', { + // making it explicit this property is not enumerable + // because otherwise some prototype manipulation in + // userland will fail + enumerable: false, + get: function () { + return this._readableState.highWaterMark; + } +}); + +// exposed for testing purposes only. +Readable._fromList = fromList; + +// Pluck off n bytes from an array of buffers. +// Length is the combined lengths of all the buffers in the list. +// This function is designed to be inlinable, so please take care when making +// changes to the function body. +function fromList(n, state) { + // nothing buffered + if (state.length === 0) return null; + + var ret; + if (state.objectMode) ret = state.buffer.shift(); else if (!n || n >= state.length) { + // read it all, truncate the list + if (state.decoder) ret = state.buffer.join(''); else if (state.buffer.length === 1) ret = state.buffer.head.data; else ret = state.buffer.concat(state.length); + state.buffer.clear(); + } else { + // read part of list + ret = fromListPartial(n, state.buffer, state.decoder); + } + + return ret; +} + +// Extracts only enough buffered data to satisfy the amount requested. +// This function is designed to be inlinable, so please take care when making +// changes to the function body. +function fromListPartial(n, list, hasStrings) { + var ret; + if (n < list.head.data.length) { + // slice is the same for buffers and strings + ret = list.head.data.slice(0, n); + list.head.data = list.head.data.slice(n); + } else if (n === list.head.data.length) { + // first chunk is a perfect match + ret = list.shift(); + } else { + // result spans more than one buffer + ret = hasStrings ? copyFromBufferString(n, list) : copyFromBuffer(n, list); + } + return ret; +} + +// Copies a specified amount of characters from the list of buffered data +// chunks. +// This function is designed to be inlinable, so please take care when making +// changes to the function body. +function copyFromBufferString(n, list) { + var p = list.head; + var c = 1; + var ret = p.data; + n -= ret.length; + while (p = p.next) { + var str = p.data; + var nb = n > str.length ? str.length : n; + if (nb === str.length) ret += str; else ret += str.slice(0, n); + n -= nb; + if (n === 0) { + if (nb === str.length) { + ++c; + if (p.next) list.head = p.next; else list.head = list.tail = null; + } else { + list.head = p; + p.data = str.slice(nb); + } + break; + } + ++c; + } + list.length -= c; + return ret; +} + +// Copies a specified amount of bytes from the list of buffered data chunks. +// This function is designed to be inlinable, so please take care when making +// changes to the function body. +function copyFromBuffer(n, list) { + var ret = Buffer.allocUnsafe(n); + var p = list.head; + var c = 1; + p.data.copy(ret); + n -= p.data.length; + while (p = p.next) { + var buf = p.data; + var nb = n > buf.length ? buf.length : n; + buf.copy(ret, ret.length - n, 0, nb); + n -= nb; + if (n === 0) { + if (nb === buf.length) { + ++c; + if (p.next) list.head = p.next; else list.head = list.tail = null; + } else { + list.head = p; + p.data = buf.slice(nb); + } + break; + } + ++c; + } + list.length -= c; + return ret; +} + +function endReadable(stream) { + var state = stream._readableState; + + // If we get here before consuming all the bytes, then that is a + // bug in node. Should never happen. + if (state.length > 0) throw new Error('"endReadable()" called on non-empty stream'); + + if (!state.endEmitted) { + state.ended = true; + pna.nextTick(endReadableNT, state, stream); + } +} + +function endReadableNT(state, stream) { + // Check that we didn't get one last unshift. + if (!state.endEmitted && state.length === 0) { + state.endEmitted = true; + stream.readable = false; + stream.emit('end'); + } +} + +function indexOf(xs, x) { + for (var i = 0, l = xs.length; i < l; i++) { + if (xs[i] === x) return i; + } + return -1; +} \ No newline at end of file diff --git a/server/libs/archiver/archiverUtils/lazystream/readable-stream/lib/_stream_transform.js b/server/libs/archiver/archiverUtils/lazystream/readable-stream/lib/_stream_transform.js new file mode 100644 index 000000000..7c2eb6c7d --- /dev/null +++ b/server/libs/archiver/archiverUtils/lazystream/readable-stream/lib/_stream_transform.js @@ -0,0 +1,215 @@ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +// a transform stream is a readable/writable stream where you do +// something with the data. Sometimes it's called a "filter", +// but that's not a great name for it, since that implies a thing where +// some bits pass through, and others are simply ignored. (That would +// be a valid example of a transform, of course.) +// +// While the output is causally related to the input, it's not a +// necessarily symmetric or synchronous transformation. For example, +// a zlib stream might take multiple plain-text writes(), and then +// emit a single compressed chunk some time in the future. +// +// Here's how this works: +// +// The Transform stream has all the aspects of the readable and writable +// stream classes. When you write(chunk), that calls _write(chunk,cb) +// internally, and returns false if there's a lot of pending writes +// buffered up. When you call read(), that calls _read(n) until +// there's enough pending readable data buffered up. +// +// In a transform stream, the written data is placed in a buffer. When +// _read(n) is called, it transforms the queued up data, calling the +// buffered _write cb's as it consumes chunks. If consuming a single +// written chunk would result in multiple output chunks, then the first +// outputted bit calls the readcb, and subsequent chunks just go into +// the read buffer, and will cause it to emit 'readable' if necessary. +// +// This way, back-pressure is actually determined by the reading side, +// since _read has to be called to start processing a new chunk. However, +// a pathological inflate type of transform can cause excessive buffering +// here. For example, imagine a stream where every byte of input is +// interpreted as an integer from 0-255, and then results in that many +// bytes of output. Writing the 4 bytes {ff,ff,ff,ff} would result in +// 1kb of data being output. In this case, you could write a very small +// amount of input, and end up with a very large amount of output. In +// such a pathological inflating mechanism, there'd be no way to tell +// the system to stop doing the transform. A single 4MB write could +// cause the system to run out of memory. +// +// However, even in such a pathological case, only a single written chunk +// would be consumed, and then the rest would wait (un-transformed) until +// the results of the previous transformed chunk were consumed. + +'use strict'; + +module.exports = Transform; + +var Duplex = require('./_stream_duplex'); + +/**/ +var util = require('util') +// var util = Object.create(require('core-util-is')); +// util.inherits = require('inherits'); +/**/ + +util.inherits(Transform, Duplex); + +function afterTransform(er, data) { + var ts = this._transformState; + ts.transforming = false; + + var cb = ts.writecb; + + if (!cb) { + return this.emit('error', new Error('write callback called multiple times')); + } + + ts.writechunk = null; + ts.writecb = null; + + if (data != null) // single equals check for both `null` and `undefined` + this.push(data); + + cb(er); + + var rs = this._readableState; + rs.reading = false; + if (rs.needReadable || rs.length < rs.highWaterMark) { + this._read(rs.highWaterMark); + } +} + +function Transform(options) { + if (!(this instanceof Transform)) return new Transform(options); + + Duplex.call(this, options); + + this._transformState = { + afterTransform: afterTransform.bind(this), + needTransform: false, + transforming: false, + writecb: null, + writechunk: null, + writeencoding: null + }; + + // start out asking for a readable event once data is transformed. + this._readableState.needReadable = true; + + // we have implemented the _read method, and done the other things + // that Readable wants before the first _read call, so unset the + // sync guard flag. + this._readableState.sync = false; + + if (options) { + if (typeof options.transform === 'function') this._transform = options.transform; + + if (typeof options.flush === 'function') this._flush = options.flush; + } + + // When the writable side finishes, then flush out anything remaining. + this.on('prefinish', prefinish); +} + +function prefinish() { + var _this = this; + + if (typeof this._flush === 'function') { + this._flush(function (er, data) { + done(_this, er, data); + }); + } else { + done(this, null, null); + } +} + +Transform.prototype.push = function (chunk, encoding) { + this._transformState.needTransform = false; + return Duplex.prototype.push.call(this, chunk, encoding); +}; + +// This is the part where you do stuff! +// override this function in implementation classes. +// 'chunk' is an input chunk. +// +// Call `push(newChunk)` to pass along transformed output +// to the readable side. You may call 'push' zero or more times. +// +// Call `cb(err)` when you are done with this chunk. If you pass +// an error, then that'll put the hurt on the whole operation. If you +// never call cb(), then you'll never get another chunk. +Transform.prototype._transform = function (chunk, encoding, cb) { + throw new Error('_transform() is not implemented'); +}; + +Transform.prototype._write = function (chunk, encoding, cb) { + var ts = this._transformState; + ts.writecb = cb; + ts.writechunk = chunk; + ts.writeencoding = encoding; + if (!ts.transforming) { + var rs = this._readableState; + if (ts.needTransform || rs.needReadable || rs.length < rs.highWaterMark) this._read(rs.highWaterMark); + } +}; + +// Doesn't matter what the args are here. +// _transform does all the work. +// That we got here means that the readable side wants more data. +Transform.prototype._read = function (n) { + var ts = this._transformState; + + if (ts.writechunk !== null && ts.writecb && !ts.transforming) { + ts.transforming = true; + this._transform(ts.writechunk, ts.writeencoding, ts.afterTransform); + } else { + // mark that we need a transform, so that any data that comes in + // will get processed, now that we've asked for it. + ts.needTransform = true; + } +}; + +Transform.prototype._destroy = function (err, cb) { + var _this2 = this; + + Duplex.prototype._destroy.call(this, err, function (err2) { + cb(err2); + _this2.emit('close'); + }); +}; + +function done(stream, er, data) { + if (er) return stream.emit('error', er); + + if (data != null) // single equals check for both `null` and `undefined` + stream.push(data); + + // if there's nothing in the write buffer, then that means + // that nothing more will ever be provided + if (stream._writableState.length) throw new Error('Calling transform done when ws.length != 0'); + + if (stream._transformState.transforming) throw new Error('Calling transform done when still transforming'); + + return stream.push(null); +} \ No newline at end of file diff --git a/server/libs/archiver/archiverUtils/lazystream/readable-stream/lib/_stream_writable.js b/server/libs/archiver/archiverUtils/lazystream/readable-stream/lib/_stream_writable.js new file mode 100644 index 000000000..5acbde6ca --- /dev/null +++ b/server/libs/archiver/archiverUtils/lazystream/readable-stream/lib/_stream_writable.js @@ -0,0 +1,689 @@ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +// A bit simpler than readable streams. +// Implement an async ._write(chunk, encoding, cb), and it'll handle all +// the drain event emission and buffering. + +'use strict'; + +/**/ + +// var pna = require('process-nextick-args'); +var pna = process +/**/ + +module.exports = Writable; + +/* */ +function WriteReq(chunk, encoding, cb) { + this.chunk = chunk; + this.encoding = encoding; + this.callback = cb; + this.next = null; +} + +// It seems a linked list but it is not +// there will be only 2 of these for each stream +function CorkedRequest(state) { + var _this = this; + + this.next = null; + this.entry = null; + this.finish = function () { + onCorkedFinish(_this, state); + }; +} +/* */ + +/**/ +var asyncWrite = !process.browser && ['v0.10', 'v0.9.'].indexOf(process.version.slice(0, 5)) > -1 ? setImmediate : pna.nextTick; +/**/ + +/**/ +var Duplex; +/**/ + +Writable.WritableState = WritableState; + +/**/ +// var util = Object.create(require('core-util-is')); +// util.inherits = require('inherits'); +var util = require('util') +/**/ + +/**/ +var internalUtil = { + deprecate: util.deprecate +}; +/**/ + +/**/ +var Stream = require('./internal/streams/stream'); +/**/ + +/**/ + +var Buffer = require('../../../safeBuffer').Buffer; +var OurUint8Array = global.Uint8Array || function () { }; +function _uint8ArrayToBuffer(chunk) { + return Buffer.from(chunk); +} +function _isUint8Array(obj) { + return Buffer.isBuffer(obj) || obj instanceof OurUint8Array; +} + +/**/ + +var destroyImpl = require('./internal/streams/destroy'); + +util.inherits(Writable, Stream); + +function nop() { } + +function WritableState(options, stream) { + Duplex = Duplex || require('./_stream_duplex'); + + options = options || {}; + + // Duplex streams are both readable and writable, but share + // the same options object. + // However, some cases require setting options to different + // values for the readable and the writable sides of the duplex stream. + // These options can be provided separately as readableXXX and writableXXX. + var isDuplex = stream instanceof Duplex; + + // object stream flag to indicate whether or not this stream + // contains buffers or objects. + this.objectMode = !!options.objectMode; + + if (isDuplex) this.objectMode = this.objectMode || !!options.writableObjectMode; + + // the point at which write() starts returning false + // Note: 0 is a valid value, means that we always return false if + // the entire buffer is not flushed immediately on write() + var hwm = options.highWaterMark; + var writableHwm = options.writableHighWaterMark; + var defaultHwm = this.objectMode ? 16 : 16 * 1024; + + if (hwm || hwm === 0) this.highWaterMark = hwm; else if (isDuplex && (writableHwm || writableHwm === 0)) this.highWaterMark = writableHwm; else this.highWaterMark = defaultHwm; + + // cast to ints. + this.highWaterMark = Math.floor(this.highWaterMark); + + // if _final has been called + this.finalCalled = false; + + // drain event flag. + this.needDrain = false; + // at the start of calling end() + this.ending = false; + // when end() has been called, and returned + this.ended = false; + // when 'finish' is emitted + this.finished = false; + + // has it been destroyed + this.destroyed = false; + + // should we decode strings into buffers before passing to _write? + // this is here so that some node-core streams can optimize string + // handling at a lower level. + var noDecode = options.decodeStrings === false; + this.decodeStrings = !noDecode; + + // Crypto is kind of old and crusty. Historically, its default string + // encoding is 'binary' so we have to make this configurable. + // Everything else in the universe uses 'utf8', though. + this.defaultEncoding = options.defaultEncoding || 'utf8'; + + // not an actual buffer we keep track of, but a measurement + // of how much we're waiting to get pushed to some underlying + // socket or file. + this.length = 0; + + // a flag to see when we're in the middle of a write. + this.writing = false; + + // when true all writes will be buffered until .uncork() call + this.corked = 0; + + // a flag to be able to tell if the onwrite cb is called immediately, + // or on a later tick. We set this to true at first, because any + // actions that shouldn't happen until "later" should generally also + // not happen before the first write call. + this.sync = true; + + // a flag to know if we're processing previously buffered items, which + // may call the _write() callback in the same tick, so that we don't + // end up in an overlapped onwrite situation. + this.bufferProcessing = false; + + // the callback that's passed to _write(chunk,cb) + this.onwrite = function (er) { + onwrite(stream, er); + }; + + // the callback that the user supplies to write(chunk,encoding,cb) + this.writecb = null; + + // the amount that is being written when _write is called. + this.writelen = 0; + + this.bufferedRequest = null; + this.lastBufferedRequest = null; + + // number of pending user-supplied write callbacks + // this must be 0 before 'finish' can be emitted + this.pendingcb = 0; + + // emit prefinish if the only thing we're waiting for is _write cbs + // This is relevant for synchronous Transform streams + this.prefinished = false; + + // True if the error was already emitted and should not be thrown again + this.errorEmitted = false; + + // count buffered requests + this.bufferedRequestCount = 0; + + // allocate the first CorkedRequest, there is always + // one allocated and free to use, and we maintain at most two + this.corkedRequestsFree = new CorkedRequest(this); +} + +WritableState.prototype.getBuffer = function getBuffer() { + var current = this.bufferedRequest; + var out = []; + while (current) { + out.push(current); + current = current.next; + } + return out; +}; + +(function () { + try { + Object.defineProperty(WritableState.prototype, 'buffer', { + get: internalUtil.deprecate(function () { + return this.getBuffer(); + }, '_writableState.buffer is deprecated. Use _writableState.getBuffer ' + 'instead.', 'DEP0003') + }); + } catch (_) { } +})(); + +// Test _writableState for inheritance to account for Duplex streams, +// whose prototype chain only points to Readable. +var realHasInstance; +if (typeof Symbol === 'function' && Symbol.hasInstance && typeof Function.prototype[Symbol.hasInstance] === 'function') { + realHasInstance = Function.prototype[Symbol.hasInstance]; + Object.defineProperty(Writable, Symbol.hasInstance, { + value: function (object) { + if (realHasInstance.call(this, object)) return true; + if (this !== Writable) return false; + + return object && object._writableState instanceof WritableState; + } + }); +} else { + realHasInstance = function (object) { + return object instanceof this; + }; +} + +function Writable(options) { + Duplex = Duplex || require('./_stream_duplex'); + + // Writable ctor is applied to Duplexes, too. + // `realHasInstance` is necessary because using plain `instanceof` + // would return false, as no `_writableState` property is attached. + + // Trying to use the custom `instanceof` for Writable here will also break the + // Node.js LazyTransform implementation, which has a non-trivial getter for + // `_writableState` that would lead to infinite recursion. + if (!realHasInstance.call(Writable, this) && !(this instanceof Duplex)) { + return new Writable(options); + } + + this._writableState = new WritableState(options, this); + + // legacy. + this.writable = true; + + if (options) { + if (typeof options.write === 'function') this._write = options.write; + + if (typeof options.writev === 'function') this._writev = options.writev; + + if (typeof options.destroy === 'function') this._destroy = options.destroy; + + if (typeof options.final === 'function') this._final = options.final; + } + + Stream.call(this); +} + +// Otherwise people can pipe Writable streams, which is just wrong. +Writable.prototype.pipe = function () { + this.emit('error', new Error('Cannot pipe, not readable')); +}; + +function writeAfterEnd(stream, cb) { + var er = new Error('write after end'); + // TODO: defer error events consistently everywhere, not just the cb + stream.emit('error', er); + pna.nextTick(cb, er); +} + +// Checks that a user-supplied chunk is valid, especially for the particular +// mode the stream is in. Currently this means that `null` is never accepted +// and undefined/non-string values are only allowed in object mode. +function validChunk(stream, state, chunk, cb) { + var valid = true; + var er = false; + + if (chunk === null) { + er = new TypeError('May not write null values to stream'); + } else if (typeof chunk !== 'string' && chunk !== undefined && !state.objectMode) { + er = new TypeError('Invalid non-string/buffer chunk'); + } + if (er) { + stream.emit('error', er); + pna.nextTick(cb, er); + valid = false; + } + return valid; +} + +Writable.prototype.write = function (chunk, encoding, cb) { + var state = this._writableState; + var ret = false; + var isBuf = !state.objectMode && _isUint8Array(chunk); + + if (isBuf && !Buffer.isBuffer(chunk)) { + chunk = _uint8ArrayToBuffer(chunk); + } + + if (typeof encoding === 'function') { + cb = encoding; + encoding = null; + } + + if (isBuf) encoding = 'buffer'; else if (!encoding) encoding = state.defaultEncoding; + + if (typeof cb !== 'function') cb = nop; + + if (state.ended) writeAfterEnd(this, cb); else if (isBuf || validChunk(this, state, chunk, cb)) { + state.pendingcb++; + ret = writeOrBuffer(this, state, isBuf, chunk, encoding, cb); + } + + return ret; +}; + +Writable.prototype.cork = function () { + var state = this._writableState; + + state.corked++; +}; + +Writable.prototype.uncork = function () { + var state = this._writableState; + + if (state.corked) { + state.corked--; + + if (!state.writing && !state.corked && !state.finished && !state.bufferProcessing && state.bufferedRequest) clearBuffer(this, state); + } +}; + +Writable.prototype.setDefaultEncoding = function setDefaultEncoding(encoding) { + // node::ParseEncoding() requires lower case. + if (typeof encoding === 'string') encoding = encoding.toLowerCase(); + if (!(['hex', 'utf8', 'utf-8', 'ascii', 'binary', 'base64', 'ucs2', 'ucs-2', 'utf16le', 'utf-16le', 'raw'].indexOf((encoding + '').toLowerCase()) > -1)) throw new TypeError('Unknown encoding: ' + encoding); + this._writableState.defaultEncoding = encoding; + return this; +}; + +function decodeChunk(state, chunk, encoding) { + if (!state.objectMode && state.decodeStrings !== false && typeof chunk === 'string') { + chunk = Buffer.from(chunk, encoding); + } + return chunk; +} + +Object.defineProperty(Writable.prototype, 'writableHighWaterMark', { + // making it explicit this property is not enumerable + // because otherwise some prototype manipulation in + // userland will fail + enumerable: false, + get: function () { + return this._writableState.highWaterMark; + } +}); + +// if we're already writing something, then just put this +// in the queue, and wait our turn. Otherwise, call _write +// If we return false, then we need a drain event, so set that flag. +function writeOrBuffer(stream, state, isBuf, chunk, encoding, cb) { + if (!isBuf) { + var newChunk = decodeChunk(state, chunk, encoding); + if (chunk !== newChunk) { + isBuf = true; + encoding = 'buffer'; + chunk = newChunk; + } + } + var len = state.objectMode ? 1 : chunk.length; + + state.length += len; + + var ret = state.length < state.highWaterMark; + // we must ensure that previous needDrain will not be reset to false. + if (!ret) state.needDrain = true; + + if (state.writing || state.corked) { + var last = state.lastBufferedRequest; + state.lastBufferedRequest = { + chunk: chunk, + encoding: encoding, + isBuf: isBuf, + callback: cb, + next: null + }; + if (last) { + last.next = state.lastBufferedRequest; + } else { + state.bufferedRequest = state.lastBufferedRequest; + } + state.bufferedRequestCount += 1; + } else { + doWrite(stream, state, false, len, chunk, encoding, cb); + } + + return ret; +} + +function doWrite(stream, state, writev, len, chunk, encoding, cb) { + state.writelen = len; + state.writecb = cb; + state.writing = true; + state.sync = true; + if (writev) stream._writev(chunk, state.onwrite); else stream._write(chunk, encoding, state.onwrite); + state.sync = false; +} + +function onwriteError(stream, state, sync, er, cb) { + --state.pendingcb; + + if (sync) { + // defer the callback if we are being called synchronously + // to avoid piling up things on the stack + pna.nextTick(cb, er); + // this can emit finish, and it will always happen + // after error + pna.nextTick(finishMaybe, stream, state); + stream._writableState.errorEmitted = true; + stream.emit('error', er); + } else { + // the caller expect this to happen before if + // it is async + cb(er); + stream._writableState.errorEmitted = true; + stream.emit('error', er); + // this can emit finish, but finish must + // always follow error + finishMaybe(stream, state); + } +} + +function onwriteStateUpdate(state) { + state.writing = false; + state.writecb = null; + state.length -= state.writelen; + state.writelen = 0; +} + +function onwrite(stream, er) { + var state = stream._writableState; + var sync = state.sync; + var cb = state.writecb; + + onwriteStateUpdate(state); + + if (er) onwriteError(stream, state, sync, er, cb); else { + // Check if we're actually ready to finish, but don't emit yet + var finished = needFinish(state); + + if (!finished && !state.corked && !state.bufferProcessing && state.bufferedRequest) { + clearBuffer(stream, state); + } + + if (sync) { + /**/ + asyncWrite(afterWrite, stream, state, finished, cb); + /**/ + } else { + afterWrite(stream, state, finished, cb); + } + } +} + +function afterWrite(stream, state, finished, cb) { + if (!finished) onwriteDrain(stream, state); + state.pendingcb--; + cb(); + finishMaybe(stream, state); +} + +// Must force callback to be called on nextTick, so that we don't +// emit 'drain' before the write() consumer gets the 'false' return +// value, and has a chance to attach a 'drain' listener. +function onwriteDrain(stream, state) { + if (state.length === 0 && state.needDrain) { + state.needDrain = false; + stream.emit('drain'); + } +} + +// if there's something in the buffer waiting, then process it +function clearBuffer(stream, state) { + state.bufferProcessing = true; + var entry = state.bufferedRequest; + + if (stream._writev && entry && entry.next) { + // Fast case, write everything using _writev() + var l = state.bufferedRequestCount; + var buffer = new Array(l); + var holder = state.corkedRequestsFree; + holder.entry = entry; + + var count = 0; + var allBuffers = true; + while (entry) { + buffer[count] = entry; + if (!entry.isBuf) allBuffers = false; + entry = entry.next; + count += 1; + } + buffer.allBuffers = allBuffers; + + doWrite(stream, state, true, state.length, buffer, '', holder.finish); + + // doWrite is almost always async, defer these to save a bit of time + // as the hot path ends with doWrite + state.pendingcb++; + state.lastBufferedRequest = null; + if (holder.next) { + state.corkedRequestsFree = holder.next; + holder.next = null; + } else { + state.corkedRequestsFree = new CorkedRequest(state); + } + state.bufferedRequestCount = 0; + } else { + // Slow case, write chunks one-by-one + while (entry) { + var chunk = entry.chunk; + var encoding = entry.encoding; + var cb = entry.callback; + var len = state.objectMode ? 1 : chunk.length; + + doWrite(stream, state, false, len, chunk, encoding, cb); + entry = entry.next; + state.bufferedRequestCount--; + // if we didn't call the onwrite immediately, then + // it means that we need to wait until it does. + // also, that means that the chunk and cb are currently + // being processed, so move the buffer counter past them. + if (state.writing) { + break; + } + } + + if (entry === null) state.lastBufferedRequest = null; + } + + state.bufferedRequest = entry; + state.bufferProcessing = false; +} + +Writable.prototype._write = function (chunk, encoding, cb) { + cb(new Error('_write() is not implemented')); +}; + +Writable.prototype._writev = null; + +Writable.prototype.end = function (chunk, encoding, cb) { + var state = this._writableState; + + if (typeof chunk === 'function') { + cb = chunk; + chunk = null; + encoding = null; + } else if (typeof encoding === 'function') { + cb = encoding; + encoding = null; + } + + if (chunk !== null && chunk !== undefined) this.write(chunk, encoding); + + // .end() fully uncorks + if (state.corked) { + state.corked = 1; + this.uncork(); + } + + // ignore unnecessary end() calls. + if (!state.ending && !state.finished) endWritable(this, state, cb); +}; + +function needFinish(state) { + return state.ending && state.length === 0 && state.bufferedRequest === null && !state.finished && !state.writing; +} +function callFinal(stream, state) { + stream._final(function (err) { + state.pendingcb--; + if (err) { + stream.emit('error', err); + } + state.prefinished = true; + stream.emit('prefinish'); + finishMaybe(stream, state); + }); +} +function prefinish(stream, state) { + if (!state.prefinished && !state.finalCalled) { + if (typeof stream._final === 'function') { + state.pendingcb++; + state.finalCalled = true; + pna.nextTick(callFinal, stream, state); + } else { + state.prefinished = true; + stream.emit('prefinish'); + } + } +} + +function finishMaybe(stream, state) { + var need = needFinish(state); + if (need) { + prefinish(stream, state); + if (state.pendingcb === 0) { + state.finished = true; + stream.emit('finish'); + } + } + return need; +} + +function endWritable(stream, state, cb) { + state.ending = true; + finishMaybe(stream, state); + if (cb) { + if (state.finished) pna.nextTick(cb); else stream.once('finish', cb); + } + state.ended = true; + stream.writable = false; +} + +function onCorkedFinish(corkReq, state, err) { + var entry = corkReq.entry; + corkReq.entry = null; + while (entry) { + var cb = entry.callback; + state.pendingcb--; + cb(err); + entry = entry.next; + } + if (state.corkedRequestsFree) { + state.corkedRequestsFree.next = corkReq; + } else { + state.corkedRequestsFree = corkReq; + } +} + +Object.defineProperty(Writable.prototype, 'destroyed', { + get: function () { + if (this._writableState === undefined) { + return false; + } + return this._writableState.destroyed; + }, + set: function (value) { + // we ignore the value if the stream + // has not been initialized yet + if (!this._writableState) { + return; + } + + // backward compatibility, the user is explicitly + // managing destroyed + this._writableState.destroyed = value; + } +}); + +Writable.prototype.destroy = destroyImpl.destroy; +Writable.prototype._undestroy = destroyImpl.undestroy; +Writable.prototype._destroy = function (err, cb) { + this.end(); + cb(err); +}; \ No newline at end of file diff --git a/server/libs/archiver/archiverUtils/lazystream/readable-stream/lib/internal/streams/BufferList.js b/server/libs/archiver/archiverUtils/lazystream/readable-stream/lib/internal/streams/BufferList.js new file mode 100644 index 000000000..405fadf4c --- /dev/null +++ b/server/libs/archiver/archiverUtils/lazystream/readable-stream/lib/internal/streams/BufferList.js @@ -0,0 +1,79 @@ +'use strict'; + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +var Buffer = require('../../../../../safeBuffer').Buffer; +var util = require('util'); + +function copyBuffer(src, target, offset) { + src.copy(target, offset); +} + +module.exports = function () { + function BufferList() { + _classCallCheck(this, BufferList); + + this.head = null; + this.tail = null; + this.length = 0; + } + + BufferList.prototype.push = function push(v) { + var entry = { data: v, next: null }; + if (this.length > 0) this.tail.next = entry; else this.head = entry; + this.tail = entry; + ++this.length; + }; + + BufferList.prototype.unshift = function unshift(v) { + var entry = { data: v, next: this.head }; + if (this.length === 0) this.tail = entry; + this.head = entry; + ++this.length; + }; + + BufferList.prototype.shift = function shift() { + if (this.length === 0) return; + var ret = this.head.data; + if (this.length === 1) this.head = this.tail = null; else this.head = this.head.next; + --this.length; + return ret; + }; + + BufferList.prototype.clear = function clear() { + this.head = this.tail = null; + this.length = 0; + }; + + BufferList.prototype.join = function join(s) { + if (this.length === 0) return ''; + var p = this.head; + var ret = '' + p.data; + while (p = p.next) { + ret += s + p.data; + } return ret; + }; + + BufferList.prototype.concat = function concat(n) { + if (this.length === 0) return Buffer.alloc(0); + if (this.length === 1) return this.head.data; + var ret = Buffer.allocUnsafe(n >>> 0); + var p = this.head; + var i = 0; + while (p) { + copyBuffer(p.data, ret, i); + i += p.data.length; + p = p.next; + } + return ret; + }; + + return BufferList; +}(); + +if (util && util.inspect && util.inspect.custom) { + module.exports.prototype[util.inspect.custom] = function () { + var obj = util.inspect({ length: this.length }); + return this.constructor.name + ' ' + obj; + }; +} \ No newline at end of file diff --git a/server/libs/archiver/archiverUtils/lazystream/readable-stream/lib/internal/streams/destroy.js b/server/libs/archiver/archiverUtils/lazystream/readable-stream/lib/internal/streams/destroy.js new file mode 100644 index 000000000..a9ab4dcf0 --- /dev/null +++ b/server/libs/archiver/archiverUtils/lazystream/readable-stream/lib/internal/streams/destroy.js @@ -0,0 +1,75 @@ +'use strict'; + +/**/ + +// var pna = require('process-nextick-args'); +var pna = process +/**/ + +// undocumented cb() API, needed for core, not for public API +function destroy(err, cb) { + var _this = this; + + var readableDestroyed = this._readableState && this._readableState.destroyed; + var writableDestroyed = this._writableState && this._writableState.destroyed; + + if (readableDestroyed || writableDestroyed) { + if (cb) { + cb(err); + } else if (err && (!this._writableState || !this._writableState.errorEmitted)) { + pna.nextTick(emitErrorNT, this, err); + } + return this; + } + + // we set destroyed to true before firing error callbacks in order + // to make it re-entrance safe in case destroy() is called within callbacks + + if (this._readableState) { + this._readableState.destroyed = true; + } + + // if this is a duplex stream mark the writable part as destroyed as well + if (this._writableState) { + this._writableState.destroyed = true; + } + + this._destroy(err || null, function (err) { + if (!cb && err) { + pna.nextTick(emitErrorNT, _this, err); + if (_this._writableState) { + _this._writableState.errorEmitted = true; + } + } else if (cb) { + cb(err); + } + }); + + return this; +} + +function undestroy() { + if (this._readableState) { + this._readableState.destroyed = false; + this._readableState.reading = false; + this._readableState.ended = false; + this._readableState.endEmitted = false; + } + + if (this._writableState) { + this._writableState.destroyed = false; + this._writableState.ended = false; + this._writableState.ending = false; + this._writableState.finished = false; + this._writableState.errorEmitted = false; + } +} + +function emitErrorNT(self, err) { + self.emit('error', err); +} + +module.exports = { + destroy: destroy, + undestroy: undestroy +}; \ No newline at end of file diff --git a/server/libs/archiver/archiverUtils/lazystream/readable-stream/lib/internal/streams/stream-browser.js b/server/libs/archiver/archiverUtils/lazystream/readable-stream/lib/internal/streams/stream-browser.js new file mode 100644 index 000000000..9332a3fda --- /dev/null +++ b/server/libs/archiver/archiverUtils/lazystream/readable-stream/lib/internal/streams/stream-browser.js @@ -0,0 +1 @@ +module.exports = require('events').EventEmitter; diff --git a/server/libs/archiver/archiverUtils/lazystream/readable-stream/lib/internal/streams/stream.js b/server/libs/archiver/archiverUtils/lazystream/readable-stream/lib/internal/streams/stream.js new file mode 100644 index 000000000..ce2ad5b6e --- /dev/null +++ b/server/libs/archiver/archiverUtils/lazystream/readable-stream/lib/internal/streams/stream.js @@ -0,0 +1 @@ +module.exports = require('stream'); diff --git a/server/libs/archiver/archiverUtils/lazystream/readable-stream/passthrough.js b/server/libs/archiver/archiverUtils/lazystream/readable-stream/passthrough.js new file mode 100644 index 000000000..ffd791d7f --- /dev/null +++ b/server/libs/archiver/archiverUtils/lazystream/readable-stream/passthrough.js @@ -0,0 +1 @@ +module.exports = require('./readable').PassThrough diff --git a/server/libs/archiver/archiverUtils/lazystream/readable-stream/readable.js b/server/libs/archiver/archiverUtils/lazystream/readable-stream/readable.js new file mode 100644 index 000000000..ec89ec533 --- /dev/null +++ b/server/libs/archiver/archiverUtils/lazystream/readable-stream/readable.js @@ -0,0 +1,19 @@ +var Stream = require('stream'); +if (process.env.READABLE_STREAM === 'disable' && Stream) { + module.exports = Stream; + exports = module.exports = Stream.Readable; + exports.Readable = Stream.Readable; + exports.Writable = Stream.Writable; + exports.Duplex = Stream.Duplex; + exports.Transform = Stream.Transform; + exports.PassThrough = Stream.PassThrough; + exports.Stream = Stream; +} else { + exports = module.exports = require('./lib/_stream_readable.js'); + exports.Stream = Stream || exports; + exports.Readable = exports; + exports.Writable = require('./lib/_stream_writable.js'); + exports.Duplex = require('./lib/_stream_duplex.js'); + exports.Transform = require('./lib/_stream_transform.js'); + exports.PassThrough = require('./lib/_stream_passthrough.js'); +} diff --git a/server/libs/archiver/archiverUtils/lodash.difference/LICENSE b/server/libs/archiver/archiverUtils/lodash.difference/LICENSE new file mode 100644 index 000000000..e0c69d560 --- /dev/null +++ b/server/libs/archiver/archiverUtils/lodash.difference/LICENSE @@ -0,0 +1,47 @@ +Copyright jQuery Foundation and other contributors + +Based on Underscore.js, copyright Jeremy Ashkenas, +DocumentCloud and Investigative Reporters & Editors + +This software consists of voluntary contributions made by many +individuals. For exact contribution history, see the revision history +available at https://github.com/lodash/lodash + +The following license applies to all parts of this software except as +documented below: + +==== + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +==== + +Copyright and related rights for sample code are waived via CC0. Sample +code is defined as all source code displayed within the prose of the +documentation. + +CC0: http://creativecommons.org/publicdomain/zero/1.0/ + +==== + +Files located in the node_modules and vendor directories are externally +maintained libraries used by this software which have their own +licenses; we recommend you read them, as their terms may differ from the +terms above. diff --git a/server/libs/archiver/archiverUtils/lodash.difference/index.js b/server/libs/archiver/archiverUtils/lodash.difference/index.js new file mode 100644 index 000000000..1759e666a --- /dev/null +++ b/server/libs/archiver/archiverUtils/lodash.difference/index.js @@ -0,0 +1,1170 @@ +/** + * lodash (Custom Build) + * Build: `lodash modularize exports="npm" -o ./` + * Copyright jQuery Foundation and other contributors + * Released under MIT license + * Based on Underscore.js 1.8.3 + * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors + */ + +/** Used as the size to enable large array optimizations. */ +var LARGE_ARRAY_SIZE = 200; + +/** Used to stand-in for `undefined` hash values. */ +var HASH_UNDEFINED = '__lodash_hash_undefined__'; + +/** Used as references for various `Number` constants. */ +var MAX_SAFE_INTEGER = 9007199254740991; + +/** `Object#toString` result references. */ +var argsTag = '[object Arguments]', + funcTag = '[object Function]', + genTag = '[object GeneratorFunction]'; + +/** + * Used to match `RegExp` + * [syntax characters](http://ecma-international.org/ecma-262/7.0/#sec-patterns). + */ +var reRegExpChar = /[\\^$.*+?()[\]{}|]/g; + +/** Used to detect host constructors (Safari). */ +var reIsHostCtor = /^\[object .+?Constructor\]$/; + +/** Detect free variable `global` from Node.js. */ +var freeGlobal = typeof global == 'object' && global && global.Object === Object && global; + +/** Detect free variable `self`. */ +var freeSelf = typeof self == 'object' && self && self.Object === Object && self; + +/** Used as a reference to the global object. */ +var root = freeGlobal || freeSelf || Function('return this')(); + +/** + * A faster alternative to `Function#apply`, this function invokes `func` + * with the `this` binding of `thisArg` and the arguments of `args`. + * + * @private + * @param {Function} func The function to invoke. + * @param {*} thisArg The `this` binding of `func`. + * @param {Array} args The arguments to invoke `func` with. + * @returns {*} Returns the result of `func`. + */ +function apply(func, thisArg, args) { + switch (args.length) { + case 0: return func.call(thisArg); + case 1: return func.call(thisArg, args[0]); + case 2: return func.call(thisArg, args[0], args[1]); + case 3: return func.call(thisArg, args[0], args[1], args[2]); + } + return func.apply(thisArg, args); +} + +/** + * A specialized version of `_.includes` for arrays without support for + * specifying an index to search from. + * + * @private + * @param {Array} [array] The array to inspect. + * @param {*} target The value to search for. + * @returns {boolean} Returns `true` if `target` is found, else `false`. + */ +function arrayIncludes(array, value) { + var length = array ? array.length : 0; + return !!length && baseIndexOf(array, value, 0) > -1; +} + +/** + * This function is like `arrayIncludes` except that it accepts a comparator. + * + * @private + * @param {Array} [array] The array to inspect. + * @param {*} target The value to search for. + * @param {Function} comparator The comparator invoked per element. + * @returns {boolean} Returns `true` if `target` is found, else `false`. + */ +function arrayIncludesWith(array, value, comparator) { + var index = -1, + length = array ? array.length : 0; + + while (++index < length) { + if (comparator(value, array[index])) { + return true; + } + } + return false; +} + +/** + * A specialized version of `_.map` for arrays without support for iteratee + * shorthands. + * + * @private + * @param {Array} [array] The array to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @returns {Array} Returns the new mapped array. + */ +function arrayMap(array, iteratee) { + var index = -1, + length = array ? array.length : 0, + result = Array(length); + + while (++index < length) { + result[index] = iteratee(array[index], index, array); + } + return result; +} + +/** + * Appends the elements of `values` to `array`. + * + * @private + * @param {Array} array The array to modify. + * @param {Array} values The values to append. + * @returns {Array} Returns `array`. + */ +function arrayPush(array, values) { + var index = -1, + length = values.length, + offset = array.length; + + while (++index < length) { + array[offset + index] = values[index]; + } + return array; +} + +/** + * The base implementation of `_.findIndex` and `_.findLastIndex` without + * support for iteratee shorthands. + * + * @private + * @param {Array} array The array to inspect. + * @param {Function} predicate The function invoked per iteration. + * @param {number} fromIndex The index to search from. + * @param {boolean} [fromRight] Specify iterating from right to left. + * @returns {number} Returns the index of the matched value, else `-1`. + */ +function baseFindIndex(array, predicate, fromIndex, fromRight) { + var length = array.length, + index = fromIndex + (fromRight ? 1 : -1); + + while ((fromRight ? index-- : ++index < length)) { + if (predicate(array[index], index, array)) { + return index; + } + } + return -1; +} + +/** + * The base implementation of `_.indexOf` without `fromIndex` bounds checks. + * + * @private + * @param {Array} array The array to inspect. + * @param {*} value The value to search for. + * @param {number} fromIndex The index to search from. + * @returns {number} Returns the index of the matched value, else `-1`. + */ +function baseIndexOf(array, value, fromIndex) { + if (value !== value) { + return baseFindIndex(array, baseIsNaN, fromIndex); + } + var index = fromIndex - 1, + length = array.length; + + while (++index < length) { + if (array[index] === value) { + return index; + } + } + return -1; +} + +/** + * The base implementation of `_.isNaN` without support for number objects. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is `NaN`, else `false`. + */ +function baseIsNaN(value) { + return value !== value; +} + +/** + * The base implementation of `_.unary` without support for storing metadata. + * + * @private + * @param {Function} func The function to cap arguments for. + * @returns {Function} Returns the new capped function. + */ +function baseUnary(func) { + return function (value) { + return func(value); + }; +} + +/** + * Checks if a cache value for `key` exists. + * + * @private + * @param {Object} cache The cache to query. + * @param {string} key The key of the entry to check. + * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. + */ +function cacheHas(cache, key) { + return cache.has(key); +} + +/** + * Gets the value at `key` of `object`. + * + * @private + * @param {Object} [object] The object to query. + * @param {string} key The key of the property to get. + * @returns {*} Returns the property value. + */ +function getValue(object, key) { + return object == null ? undefined : object[key]; +} + +/** + * Checks if `value` is a host object in IE < 9. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a host object, else `false`. + */ +function isHostObject(value) { + // Many host objects are `Object` objects that can coerce to strings + // despite having improperly defined `toString` methods. + var result = false; + if (value != null && typeof value.toString != 'function') { + try { + result = !!(value + ''); + } catch (e) { } + } + return result; +} + +/** Used for built-in method references. */ +var arrayProto = Array.prototype, + funcProto = Function.prototype, + objectProto = Object.prototype; + +/** Used to detect overreaching core-js shims. */ +var coreJsData = root['__core-js_shared__']; + +/** Used to detect methods masquerading as native. */ +var maskSrcKey = (function () { + var uid = /[^.]+$/.exec(coreJsData && coreJsData.keys && coreJsData.keys.IE_PROTO || ''); + return uid ? ('Symbol(src)_1.' + uid) : ''; +}()); + +/** Used to resolve the decompiled source of functions. */ +var funcToString = funcProto.toString; + +/** Used to check objects for own properties. */ +var hasOwnProperty = objectProto.hasOwnProperty; + +/** + * Used to resolve the + * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring) + * of values. + */ +var objectToString = objectProto.toString; + +/** Used to detect if a method is native. */ +var reIsNative = RegExp('^' + + funcToString.call(hasOwnProperty).replace(reRegExpChar, '\\$&') + .replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$' +); + +/** Built-in value references. */ +var Symbol = root.Symbol, + propertyIsEnumerable = objectProto.propertyIsEnumerable, + splice = arrayProto.splice, + spreadableSymbol = Symbol ? Symbol.isConcatSpreadable : undefined; + +/* Built-in method references for those with the same name as other `lodash` methods. */ +var nativeMax = Math.max; + +/* Built-in method references that are verified to be native. */ +var Map = getNative(root, 'Map'), + nativeCreate = getNative(Object, 'create'); + +/** + * Creates a hash object. + * + * @private + * @constructor + * @param {Array} [entries] The key-value pairs to cache. + */ +function Hash(entries) { + var index = -1, + length = entries ? entries.length : 0; + + this.clear(); + while (++index < length) { + var entry = entries[index]; + this.set(entry[0], entry[1]); + } +} + +/** + * Removes all key-value entries from the hash. + * + * @private + * @name clear + * @memberOf Hash + */ +function hashClear() { + this.__data__ = nativeCreate ? nativeCreate(null) : {}; +} + +/** + * Removes `key` and its value from the hash. + * + * @private + * @name delete + * @memberOf Hash + * @param {Object} hash The hash to modify. + * @param {string} key The key of the value to remove. + * @returns {boolean} Returns `true` if the entry was removed, else `false`. + */ +function hashDelete(key) { + return this.has(key) && delete this.__data__[key]; +} + +/** + * Gets the hash value for `key`. + * + * @private + * @name get + * @memberOf Hash + * @param {string} key The key of the value to get. + * @returns {*} Returns the entry value. + */ +function hashGet(key) { + var data = this.__data__; + if (nativeCreate) { + var result = data[key]; + return result === HASH_UNDEFINED ? undefined : result; + } + return hasOwnProperty.call(data, key) ? data[key] : undefined; +} + +/** + * Checks if a hash value for `key` exists. + * + * @private + * @name has + * @memberOf Hash + * @param {string} key The key of the entry to check. + * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. + */ +function hashHas(key) { + var data = this.__data__; + return nativeCreate ? data[key] !== undefined : hasOwnProperty.call(data, key); +} + +/** + * Sets the hash `key` to `value`. + * + * @private + * @name set + * @memberOf Hash + * @param {string} key The key of the value to set. + * @param {*} value The value to set. + * @returns {Object} Returns the hash instance. + */ +function hashSet(key, value) { + var data = this.__data__; + data[key] = (nativeCreate && value === undefined) ? HASH_UNDEFINED : value; + return this; +} + +// Add methods to `Hash`. +Hash.prototype.clear = hashClear; +Hash.prototype['delete'] = hashDelete; +Hash.prototype.get = hashGet; +Hash.prototype.has = hashHas; +Hash.prototype.set = hashSet; + +/** + * Creates an list cache object. + * + * @private + * @constructor + * @param {Array} [entries] The key-value pairs to cache. + */ +function ListCache(entries) { + var index = -1, + length = entries ? entries.length : 0; + + this.clear(); + while (++index < length) { + var entry = entries[index]; + this.set(entry[0], entry[1]); + } +} + +/** + * Removes all key-value entries from the list cache. + * + * @private + * @name clear + * @memberOf ListCache + */ +function listCacheClear() { + this.__data__ = []; +} + +/** + * Removes `key` and its value from the list cache. + * + * @private + * @name delete + * @memberOf ListCache + * @param {string} key The key of the value to remove. + * @returns {boolean} Returns `true` if the entry was removed, else `false`. + */ +function listCacheDelete(key) { + var data = this.__data__, + index = assocIndexOf(data, key); + + if (index < 0) { + return false; + } + var lastIndex = data.length - 1; + if (index == lastIndex) { + data.pop(); + } else { + splice.call(data, index, 1); + } + return true; +} + +/** + * Gets the list cache value for `key`. + * + * @private + * @name get + * @memberOf ListCache + * @param {string} key The key of the value to get. + * @returns {*} Returns the entry value. + */ +function listCacheGet(key) { + var data = this.__data__, + index = assocIndexOf(data, key); + + return index < 0 ? undefined : data[index][1]; +} + +/** + * Checks if a list cache value for `key` exists. + * + * @private + * @name has + * @memberOf ListCache + * @param {string} key The key of the entry to check. + * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. + */ +function listCacheHas(key) { + return assocIndexOf(this.__data__, key) > -1; +} + +/** + * Sets the list cache `key` to `value`. + * + * @private + * @name set + * @memberOf ListCache + * @param {string} key The key of the value to set. + * @param {*} value The value to set. + * @returns {Object} Returns the list cache instance. + */ +function listCacheSet(key, value) { + var data = this.__data__, + index = assocIndexOf(data, key); + + if (index < 0) { + data.push([key, value]); + } else { + data[index][1] = value; + } + return this; +} + +// Add methods to `ListCache`. +ListCache.prototype.clear = listCacheClear; +ListCache.prototype['delete'] = listCacheDelete; +ListCache.prototype.get = listCacheGet; +ListCache.prototype.has = listCacheHas; +ListCache.prototype.set = listCacheSet; + +/** + * Creates a map cache object to store key-value pairs. + * + * @private + * @constructor + * @param {Array} [entries] The key-value pairs to cache. + */ +function MapCache(entries) { + var index = -1, + length = entries ? entries.length : 0; + + this.clear(); + while (++index < length) { + var entry = entries[index]; + this.set(entry[0], entry[1]); + } +} + +/** + * Removes all key-value entries from the map. + * + * @private + * @name clear + * @memberOf MapCache + */ +function mapCacheClear() { + this.__data__ = { + 'hash': new Hash, + 'map': new (Map || ListCache), + 'string': new Hash + }; +} + +/** + * Removes `key` and its value from the map. + * + * @private + * @name delete + * @memberOf MapCache + * @param {string} key The key of the value to remove. + * @returns {boolean} Returns `true` if the entry was removed, else `false`. + */ +function mapCacheDelete(key) { + return getMapData(this, key)['delete'](key); +} + +/** + * Gets the map value for `key`. + * + * @private + * @name get + * @memberOf MapCache + * @param {string} key The key of the value to get. + * @returns {*} Returns the entry value. + */ +function mapCacheGet(key) { + return getMapData(this, key).get(key); +} + +/** + * Checks if a map value for `key` exists. + * + * @private + * @name has + * @memberOf MapCache + * @param {string} key The key of the entry to check. + * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. + */ +function mapCacheHas(key) { + return getMapData(this, key).has(key); +} + +/** + * Sets the map `key` to `value`. + * + * @private + * @name set + * @memberOf MapCache + * @param {string} key The key of the value to set. + * @param {*} value The value to set. + * @returns {Object} Returns the map cache instance. + */ +function mapCacheSet(key, value) { + getMapData(this, key).set(key, value); + return this; +} + +// Add methods to `MapCache`. +MapCache.prototype.clear = mapCacheClear; +MapCache.prototype['delete'] = mapCacheDelete; +MapCache.prototype.get = mapCacheGet; +MapCache.prototype.has = mapCacheHas; +MapCache.prototype.set = mapCacheSet; + +/** + * + * Creates an array cache object to store unique values. + * + * @private + * @constructor + * @param {Array} [values] The values to cache. + */ +function SetCache(values) { + var index = -1, + length = values ? values.length : 0; + + this.__data__ = new MapCache; + while (++index < length) { + this.add(values[index]); + } +} + +/** + * Adds `value` to the array cache. + * + * @private + * @name add + * @memberOf SetCache + * @alias push + * @param {*} value The value to cache. + * @returns {Object} Returns the cache instance. + */ +function setCacheAdd(value) { + this.__data__.set(value, HASH_UNDEFINED); + return this; +} + +/** + * Checks if `value` is in the array cache. + * + * @private + * @name has + * @memberOf SetCache + * @param {*} value The value to search for. + * @returns {number} Returns `true` if `value` is found, else `false`. + */ +function setCacheHas(value) { + return this.__data__.has(value); +} + +// Add methods to `SetCache`. +SetCache.prototype.add = SetCache.prototype.push = setCacheAdd; +SetCache.prototype.has = setCacheHas; + +/** + * Gets the index at which the `key` is found in `array` of key-value pairs. + * + * @private + * @param {Array} array The array to inspect. + * @param {*} key The key to search for. + * @returns {number} Returns the index of the matched value, else `-1`. + */ +function assocIndexOf(array, key) { + var length = array.length; + while (length--) { + if (eq(array[length][0], key)) { + return length; + } + } + return -1; +} + +/** + * The base implementation of methods like `_.difference` without support + * for excluding multiple arrays or iteratee shorthands. + * + * @private + * @param {Array} array The array to inspect. + * @param {Array} values The values to exclude. + * @param {Function} [iteratee] The iteratee invoked per element. + * @param {Function} [comparator] The comparator invoked per element. + * @returns {Array} Returns the new array of filtered values. + */ +function baseDifference(array, values, iteratee, comparator) { + var index = -1, + includes = arrayIncludes, + isCommon = true, + length = array.length, + result = [], + valuesLength = values.length; + + if (!length) { + return result; + } + if (iteratee) { + values = arrayMap(values, baseUnary(iteratee)); + } + if (comparator) { + includes = arrayIncludesWith; + isCommon = false; + } + else if (values.length >= LARGE_ARRAY_SIZE) { + includes = cacheHas; + isCommon = false; + values = new SetCache(values); + } + outer: + while (++index < length) { + var value = array[index], + computed = iteratee ? iteratee(value) : value; + + value = (comparator || value !== 0) ? value : 0; + if (isCommon && computed === computed) { + var valuesIndex = valuesLength; + while (valuesIndex--) { + if (values[valuesIndex] === computed) { + continue outer; + } + } + result.push(value); + } + else if (!includes(values, computed, comparator)) { + result.push(value); + } + } + return result; +} + +/** + * The base implementation of `_.flatten` with support for restricting flattening. + * + * @private + * @param {Array} array The array to flatten. + * @param {number} depth The maximum recursion depth. + * @param {boolean} [predicate=isFlattenable] The function invoked per iteration. + * @param {boolean} [isStrict] Restrict to values that pass `predicate` checks. + * @param {Array} [result=[]] The initial result value. + * @returns {Array} Returns the new flattened array. + */ +function baseFlatten(array, depth, predicate, isStrict, result) { + var index = -1, + length = array.length; + + predicate || (predicate = isFlattenable); + result || (result = []); + + while (++index < length) { + var value = array[index]; + if (depth > 0 && predicate(value)) { + if (depth > 1) { + // Recursively flatten arrays (susceptible to call stack limits). + baseFlatten(value, depth - 1, predicate, isStrict, result); + } else { + arrayPush(result, value); + } + } else if (!isStrict) { + result[result.length] = value; + } + } + return result; +} + +/** + * The base implementation of `_.isNative` without bad shim checks. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a native function, + * else `false`. + */ +function baseIsNative(value) { + if (!isObject(value) || isMasked(value)) { + return false; + } + var pattern = (isFunction(value) || isHostObject(value)) ? reIsNative : reIsHostCtor; + return pattern.test(toSource(value)); +} + +/** + * The base implementation of `_.rest` which doesn't validate or coerce arguments. + * + * @private + * @param {Function} func The function to apply a rest parameter to. + * @param {number} [start=func.length-1] The start position of the rest parameter. + * @returns {Function} Returns the new function. + */ +function baseRest(func, start) { + start = nativeMax(start === undefined ? (func.length - 1) : start, 0); + return function () { + var args = arguments, + index = -1, + length = nativeMax(args.length - start, 0), + array = Array(length); + + while (++index < length) { + array[index] = args[start + index]; + } + index = -1; + var otherArgs = Array(start + 1); + while (++index < start) { + otherArgs[index] = args[index]; + } + otherArgs[start] = array; + return apply(func, this, otherArgs); + }; +} + +/** + * Gets the data for `map`. + * + * @private + * @param {Object} map The map to query. + * @param {string} key The reference key. + * @returns {*} Returns the map data. + */ +function getMapData(map, key) { + var data = map.__data__; + return isKeyable(key) + ? data[typeof key == 'string' ? 'string' : 'hash'] + : data.map; +} + +/** + * Gets the native function at `key` of `object`. + * + * @private + * @param {Object} object The object to query. + * @param {string} key The key of the method to get. + * @returns {*} Returns the function if it's native, else `undefined`. + */ +function getNative(object, key) { + var value = getValue(object, key); + return baseIsNative(value) ? value : undefined; +} + +/** + * Checks if `value` is a flattenable `arguments` object or array. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is flattenable, else `false`. + */ +function isFlattenable(value) { + return isArray(value) || isArguments(value) || + !!(spreadableSymbol && value && value[spreadableSymbol]); +} + +/** + * Checks if `value` is suitable for use as unique object key. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is suitable, else `false`. + */ +function isKeyable(value) { + var type = typeof value; + return (type == 'string' || type == 'number' || type == 'symbol' || type == 'boolean') + ? (value !== '__proto__') + : (value === null); +} + +/** + * Checks if `func` has its source masked. + * + * @private + * @param {Function} func The function to check. + * @returns {boolean} Returns `true` if `func` is masked, else `false`. + */ +function isMasked(func) { + return !!maskSrcKey && (maskSrcKey in func); +} + +/** + * Converts `func` to its source code. + * + * @private + * @param {Function} func The function to process. + * @returns {string} Returns the source code. + */ +function toSource(func) { + if (func != null) { + try { + return funcToString.call(func); + } catch (e) { } + try { + return (func + ''); + } catch (e) { } + } + return ''; +} + +/** + * Creates an array of `array` values not included in the other given arrays + * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) + * for equality comparisons. The order of result values is determined by the + * order they occur in the first array. + * + * **Note:** Unlike `_.pullAll`, this method returns a new array. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Array + * @param {Array} array The array to inspect. + * @param {...Array} [values] The values to exclude. + * @returns {Array} Returns the new array of filtered values. + * @see _.without, _.xor + * @example + * + * _.difference([2, 1], [2, 3]); + * // => [1] + */ +var difference = baseRest(function (array, values) { + return isArrayLikeObject(array) + ? baseDifference(array, baseFlatten(values, 1, isArrayLikeObject, true)) + : []; +}); + +/** + * Performs a + * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) + * comparison between two values to determine if they are equivalent. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @returns {boolean} Returns `true` if the values are equivalent, else `false`. + * @example + * + * var object = { 'a': 1 }; + * var other = { 'a': 1 }; + * + * _.eq(object, object); + * // => true + * + * _.eq(object, other); + * // => false + * + * _.eq('a', 'a'); + * // => true + * + * _.eq('a', Object('a')); + * // => false + * + * _.eq(NaN, NaN); + * // => true + */ +function eq(value, other) { + return value === other || (value !== value && other !== other); +} + +/** + * Checks if `value` is likely an `arguments` object. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an `arguments` object, + * else `false`. + * @example + * + * _.isArguments(function() { return arguments; }()); + * // => true + * + * _.isArguments([1, 2, 3]); + * // => false + */ +function isArguments(value) { + // Safari 8.1 makes `arguments.callee` enumerable in strict mode. + return isArrayLikeObject(value) && hasOwnProperty.call(value, 'callee') && + (!propertyIsEnumerable.call(value, 'callee') || objectToString.call(value) == argsTag); +} + +/** + * Checks if `value` is classified as an `Array` object. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an array, else `false`. + * @example + * + * _.isArray([1, 2, 3]); + * // => true + * + * _.isArray(document.body.children); + * // => false + * + * _.isArray('abc'); + * // => false + * + * _.isArray(_.noop); + * // => false + */ +var isArray = Array.isArray; + +/** + * Checks if `value` is array-like. A value is considered array-like if it's + * not a function and has a `value.length` that's an integer greater than or + * equal to `0` and less than or equal to `Number.MAX_SAFE_INTEGER`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is array-like, else `false`. + * @example + * + * _.isArrayLike([1, 2, 3]); + * // => true + * + * _.isArrayLike(document.body.children); + * // => true + * + * _.isArrayLike('abc'); + * // => true + * + * _.isArrayLike(_.noop); + * // => false + */ +function isArrayLike(value) { + return value != null && isLength(value.length) && !isFunction(value); +} + +/** + * This method is like `_.isArrayLike` except that it also checks if `value` + * is an object. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an array-like object, + * else `false`. + * @example + * + * _.isArrayLikeObject([1, 2, 3]); + * // => true + * + * _.isArrayLikeObject(document.body.children); + * // => true + * + * _.isArrayLikeObject('abc'); + * // => false + * + * _.isArrayLikeObject(_.noop); + * // => false + */ +function isArrayLikeObject(value) { + return isObjectLike(value) && isArrayLike(value); +} + +/** + * Checks if `value` is classified as a `Function` object. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a function, else `false`. + * @example + * + * _.isFunction(_); + * // => true + * + * _.isFunction(/abc/); + * // => false + */ +function isFunction(value) { + // The use of `Object#toString` avoids issues with the `typeof` operator + // in Safari 8-9 which returns 'object' for typed array and other constructors. + var tag = isObject(value) ? objectToString.call(value) : ''; + return tag == funcTag || tag == genTag; +} + +/** + * Checks if `value` is a valid array-like length. + * + * **Note:** This method is loosely based on + * [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a valid length, else `false`. + * @example + * + * _.isLength(3); + * // => true + * + * _.isLength(Number.MIN_VALUE); + * // => false + * + * _.isLength(Infinity); + * // => false + * + * _.isLength('3'); + * // => false + */ +function isLength(value) { + return typeof value == 'number' && + value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER; +} + +/** + * Checks if `value` is the + * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types) + * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`) + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an object, else `false`. + * @example + * + * _.isObject({}); + * // => true + * + * _.isObject([1, 2, 3]); + * // => true + * + * _.isObject(_.noop); + * // => true + * + * _.isObject(null); + * // => false + */ +function isObject(value) { + var type = typeof value; + return !!value && (type == 'object' || type == 'function'); +} + +/** + * Checks if `value` is object-like. A value is object-like if it's not `null` + * and has a `typeof` result of "object". + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is object-like, else `false`. + * @example + * + * _.isObjectLike({}); + * // => true + * + * _.isObjectLike([1, 2, 3]); + * // => true + * + * _.isObjectLike(_.noop); + * // => false + * + * _.isObjectLike(null); + * // => false + */ +function isObjectLike(value) { + return !!value && typeof value == 'object'; +} + +module.exports = difference; diff --git a/server/libs/archiver/archiverUtils/lodash.flatten/LICENSE b/server/libs/archiver/archiverUtils/lodash.flatten/LICENSE new file mode 100644 index 000000000..e0c69d560 --- /dev/null +++ b/server/libs/archiver/archiverUtils/lodash.flatten/LICENSE @@ -0,0 +1,47 @@ +Copyright jQuery Foundation and other contributors + +Based on Underscore.js, copyright Jeremy Ashkenas, +DocumentCloud and Investigative Reporters & Editors + +This software consists of voluntary contributions made by many +individuals. For exact contribution history, see the revision history +available at https://github.com/lodash/lodash + +The following license applies to all parts of this software except as +documented below: + +==== + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +==== + +Copyright and related rights for sample code are waived via CC0. Sample +code is defined as all source code displayed within the prose of the +documentation. + +CC0: http://creativecommons.org/publicdomain/zero/1.0/ + +==== + +Files located in the node_modules and vendor directories are externally +maintained libraries used by this software which have their own +licenses; we recommend you read them, as their terms may differ from the +terms above. diff --git a/server/libs/archiver/archiverUtils/lodash.flatten/index.js b/server/libs/archiver/archiverUtils/lodash.flatten/index.js new file mode 100644 index 000000000..f136d71e9 --- /dev/null +++ b/server/libs/archiver/archiverUtils/lodash.flatten/index.js @@ -0,0 +1,349 @@ +/** + * lodash (Custom Build) + * Build: `lodash modularize exports="npm" -o ./` + * Copyright jQuery Foundation and other contributors + * Released under MIT license + * Based on Underscore.js 1.8.3 + * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors + */ + +/** Used as references for various `Number` constants. */ +var MAX_SAFE_INTEGER = 9007199254740991; + +/** `Object#toString` result references. */ +var argsTag = '[object Arguments]', + funcTag = '[object Function]', + genTag = '[object GeneratorFunction]'; + +/** Detect free variable `global` from Node.js. */ +var freeGlobal = typeof global == 'object' && global && global.Object === Object && global; + +/** Detect free variable `self`. */ +var freeSelf = typeof self == 'object' && self && self.Object === Object && self; + +/** Used as a reference to the global object. */ +var root = freeGlobal || freeSelf || Function('return this')(); + +/** + * Appends the elements of `values` to `array`. + * + * @private + * @param {Array} array The array to modify. + * @param {Array} values The values to append. + * @returns {Array} Returns `array`. + */ +function arrayPush(array, values) { + var index = -1, + length = values.length, + offset = array.length; + + while (++index < length) { + array[offset + index] = values[index]; + } + return array; +} + +/** Used for built-in method references. */ +var objectProto = Object.prototype; + +/** Used to check objects for own properties. */ +var hasOwnProperty = objectProto.hasOwnProperty; + +/** + * Used to resolve the + * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring) + * of values. + */ +var objectToString = objectProto.toString; + +/** Built-in value references. */ +var Symbol = root.Symbol, + propertyIsEnumerable = objectProto.propertyIsEnumerable, + spreadableSymbol = Symbol ? Symbol.isConcatSpreadable : undefined; + +/** + * The base implementation of `_.flatten` with support for restricting flattening. + * + * @private + * @param {Array} array The array to flatten. + * @param {number} depth The maximum recursion depth. + * @param {boolean} [predicate=isFlattenable] The function invoked per iteration. + * @param {boolean} [isStrict] Restrict to values that pass `predicate` checks. + * @param {Array} [result=[]] The initial result value. + * @returns {Array} Returns the new flattened array. + */ +function baseFlatten(array, depth, predicate, isStrict, result) { + var index = -1, + length = array.length; + + predicate || (predicate = isFlattenable); + result || (result = []); + + while (++index < length) { + var value = array[index]; + if (depth > 0 && predicate(value)) { + if (depth > 1) { + // Recursively flatten arrays (susceptible to call stack limits). + baseFlatten(value, depth - 1, predicate, isStrict, result); + } else { + arrayPush(result, value); + } + } else if (!isStrict) { + result[result.length] = value; + } + } + return result; +} + +/** + * Checks if `value` is a flattenable `arguments` object or array. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is flattenable, else `false`. + */ +function isFlattenable(value) { + return isArray(value) || isArguments(value) || + !!(spreadableSymbol && value && value[spreadableSymbol]); +} + +/** + * Flattens `array` a single level deep. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Array + * @param {Array} array The array to flatten. + * @returns {Array} Returns the new flattened array. + * @example + * + * _.flatten([1, [2, [3, [4]], 5]]); + * // => [1, 2, [3, [4]], 5] + */ +function flatten(array) { + var length = array ? array.length : 0; + return length ? baseFlatten(array, 1) : []; +} + +/** + * Checks if `value` is likely an `arguments` object. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an `arguments` object, + * else `false`. + * @example + * + * _.isArguments(function() { return arguments; }()); + * // => true + * + * _.isArguments([1, 2, 3]); + * // => false + */ +function isArguments(value) { + // Safari 8.1 makes `arguments.callee` enumerable in strict mode. + return isArrayLikeObject(value) && hasOwnProperty.call(value, 'callee') && + (!propertyIsEnumerable.call(value, 'callee') || objectToString.call(value) == argsTag); +} + +/** + * Checks if `value` is classified as an `Array` object. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an array, else `false`. + * @example + * + * _.isArray([1, 2, 3]); + * // => true + * + * _.isArray(document.body.children); + * // => false + * + * _.isArray('abc'); + * // => false + * + * _.isArray(_.noop); + * // => false + */ +var isArray = Array.isArray; + +/** + * Checks if `value` is array-like. A value is considered array-like if it's + * not a function and has a `value.length` that's an integer greater than or + * equal to `0` and less than or equal to `Number.MAX_SAFE_INTEGER`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is array-like, else `false`. + * @example + * + * _.isArrayLike([1, 2, 3]); + * // => true + * + * _.isArrayLike(document.body.children); + * // => true + * + * _.isArrayLike('abc'); + * // => true + * + * _.isArrayLike(_.noop); + * // => false + */ +function isArrayLike(value) { + return value != null && isLength(value.length) && !isFunction(value); +} + +/** + * This method is like `_.isArrayLike` except that it also checks if `value` + * is an object. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an array-like object, + * else `false`. + * @example + * + * _.isArrayLikeObject([1, 2, 3]); + * // => true + * + * _.isArrayLikeObject(document.body.children); + * // => true + * + * _.isArrayLikeObject('abc'); + * // => false + * + * _.isArrayLikeObject(_.noop); + * // => false + */ +function isArrayLikeObject(value) { + return isObjectLike(value) && isArrayLike(value); +} + +/** + * Checks if `value` is classified as a `Function` object. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a function, else `false`. + * @example + * + * _.isFunction(_); + * // => true + * + * _.isFunction(/abc/); + * // => false + */ +function isFunction(value) { + // The use of `Object#toString` avoids issues with the `typeof` operator + // in Safari 8-9 which returns 'object' for typed array and other constructors. + var tag = isObject(value) ? objectToString.call(value) : ''; + return tag == funcTag || tag == genTag; +} + +/** + * Checks if `value` is a valid array-like length. + * + * **Note:** This method is loosely based on + * [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a valid length, else `false`. + * @example + * + * _.isLength(3); + * // => true + * + * _.isLength(Number.MIN_VALUE); + * // => false + * + * _.isLength(Infinity); + * // => false + * + * _.isLength('3'); + * // => false + */ +function isLength(value) { + return typeof value == 'number' && + value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER; +} + +/** + * Checks if `value` is the + * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types) + * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`) + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an object, else `false`. + * @example + * + * _.isObject({}); + * // => true + * + * _.isObject([1, 2, 3]); + * // => true + * + * _.isObject(_.noop); + * // => true + * + * _.isObject(null); + * // => false + */ +function isObject(value) { + var type = typeof value; + return !!value && (type == 'object' || type == 'function'); +} + +/** + * Checks if `value` is object-like. A value is object-like if it's not `null` + * and has a `typeof` result of "object". + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is object-like, else `false`. + * @example + * + * _.isObjectLike({}); + * // => true + * + * _.isObjectLike([1, 2, 3]); + * // => true + * + * _.isObjectLike(_.noop); + * // => false + * + * _.isObjectLike(null); + * // => false + */ +function isObjectLike(value) { + return !!value && typeof value == 'object'; +} + +module.exports = flatten; diff --git a/server/libs/archiver/archiverUtils/lodash.isplainobject/LICENSE b/server/libs/archiver/archiverUtils/lodash.isplainobject/LICENSE new file mode 100644 index 000000000..e0c69d560 --- /dev/null +++ b/server/libs/archiver/archiverUtils/lodash.isplainobject/LICENSE @@ -0,0 +1,47 @@ +Copyright jQuery Foundation and other contributors + +Based on Underscore.js, copyright Jeremy Ashkenas, +DocumentCloud and Investigative Reporters & Editors + +This software consists of voluntary contributions made by many +individuals. For exact contribution history, see the revision history +available at https://github.com/lodash/lodash + +The following license applies to all parts of this software except as +documented below: + +==== + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +==== + +Copyright and related rights for sample code are waived via CC0. Sample +code is defined as all source code displayed within the prose of the +documentation. + +CC0: http://creativecommons.org/publicdomain/zero/1.0/ + +==== + +Files located in the node_modules and vendor directories are externally +maintained libraries used by this software which have their own +licenses; we recommend you read them, as their terms may differ from the +terms above. diff --git a/server/libs/archiver/archiverUtils/lodash.isplainobject/index.js b/server/libs/archiver/archiverUtils/lodash.isplainobject/index.js new file mode 100644 index 000000000..dbcca26f0 --- /dev/null +++ b/server/libs/archiver/archiverUtils/lodash.isplainobject/index.js @@ -0,0 +1,139 @@ +/** + * lodash (Custom Build) + * Build: `lodash modularize exports="npm" -o ./` + * Copyright jQuery Foundation and other contributors + * Released under MIT license + * Based on Underscore.js 1.8.3 + * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors + */ + +/** `Object#toString` result references. */ +var objectTag = '[object Object]'; + +/** + * Checks if `value` is a host object in IE < 9. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a host object, else `false`. + */ +function isHostObject(value) { + // Many host objects are `Object` objects that can coerce to strings + // despite having improperly defined `toString` methods. + var result = false; + if (value != null && typeof value.toString != 'function') { + try { + result = !!(value + ''); + } catch (e) { } + } + return result; +} + +/** + * Creates a unary function that invokes `func` with its argument transformed. + * + * @private + * @param {Function} func The function to wrap. + * @param {Function} transform The argument transform. + * @returns {Function} Returns the new function. + */ +function overArg(func, transform) { + return function (arg) { + return func(transform(arg)); + }; +} + +/** Used for built-in method references. */ +var funcProto = Function.prototype, + objectProto = Object.prototype; + +/** Used to resolve the decompiled source of functions. */ +var funcToString = funcProto.toString; + +/** Used to check objects for own properties. */ +var hasOwnProperty = objectProto.hasOwnProperty; + +/** Used to infer the `Object` constructor. */ +var objectCtorString = funcToString.call(Object); + +/** + * Used to resolve the + * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring) + * of values. + */ +var objectToString = objectProto.toString; + +/** Built-in value references. */ +var getPrototype = overArg(Object.getPrototypeOf, Object); + +/** + * Checks if `value` is object-like. A value is object-like if it's not `null` + * and has a `typeof` result of "object". + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is object-like, else `false`. + * @example + * + * _.isObjectLike({}); + * // => true + * + * _.isObjectLike([1, 2, 3]); + * // => true + * + * _.isObjectLike(_.noop); + * // => false + * + * _.isObjectLike(null); + * // => false + */ +function isObjectLike(value) { + return !!value && typeof value == 'object'; +} + +/** + * Checks if `value` is a plain object, that is, an object created by the + * `Object` constructor or one with a `[[Prototype]]` of `null`. + * + * @static + * @memberOf _ + * @since 0.8.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a plain object, else `false`. + * @example + * + * function Foo() { + * this.a = 1; + * } + * + * _.isPlainObject(new Foo); + * // => false + * + * _.isPlainObject([1, 2, 3]); + * // => false + * + * _.isPlainObject({ 'x': 0, 'y': 0 }); + * // => true + * + * _.isPlainObject(Object.create(null)); + * // => true + */ +function isPlainObject(value) { + if (!isObjectLike(value) || + objectToString.call(value) != objectTag || isHostObject(value)) { + return false; + } + var proto = getPrototype(value); + if (proto === null) { + return true; + } + var Ctor = hasOwnProperty.call(proto, 'constructor') && proto.constructor; + return (typeof Ctor == 'function' && + Ctor instanceof Ctor && funcToString.call(Ctor) == objectCtorString); +} + +module.exports = isPlainObject; diff --git a/server/libs/archiver/archiverUtils/lodash.union/LICENSE b/server/libs/archiver/archiverUtils/lodash.union/LICENSE new file mode 100644 index 000000000..e0c69d560 --- /dev/null +++ b/server/libs/archiver/archiverUtils/lodash.union/LICENSE @@ -0,0 +1,47 @@ +Copyright jQuery Foundation and other contributors + +Based on Underscore.js, copyright Jeremy Ashkenas, +DocumentCloud and Investigative Reporters & Editors + +This software consists of voluntary contributions made by many +individuals. For exact contribution history, see the revision history +available at https://github.com/lodash/lodash + +The following license applies to all parts of this software except as +documented below: + +==== + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +==== + +Copyright and related rights for sample code are waived via CC0. Sample +code is defined as all source code displayed within the prose of the +documentation. + +CC0: http://creativecommons.org/publicdomain/zero/1.0/ + +==== + +Files located in the node_modules and vendor directories are externally +maintained libraries used by this software which have their own +licenses; we recommend you read them, as their terms may differ from the +terms above. diff --git a/server/libs/archiver/archiverUtils/lodash.union/index.js b/server/libs/archiver/archiverUtils/lodash.union/index.js new file mode 100644 index 000000000..d299a0b46 --- /dev/null +++ b/server/libs/archiver/archiverUtils/lodash.union/index.js @@ -0,0 +1,1181 @@ +/** + * lodash (Custom Build) + * Build: `lodash modularize exports="npm" -o ./` + * Copyright jQuery Foundation and other contributors + * Released under MIT license + * Based on Underscore.js 1.8.3 + * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors + */ + +/** Used as the size to enable large array optimizations. */ +var LARGE_ARRAY_SIZE = 200; + +/** Used to stand-in for `undefined` hash values. */ +var HASH_UNDEFINED = '__lodash_hash_undefined__'; + +/** Used as references for various `Number` constants. */ +var INFINITY = 1 / 0, + MAX_SAFE_INTEGER = 9007199254740991; + +/** `Object#toString` result references. */ +var argsTag = '[object Arguments]', + funcTag = '[object Function]', + genTag = '[object GeneratorFunction]'; + +/** + * Used to match `RegExp` + * [syntax characters](http://ecma-international.org/ecma-262/7.0/#sec-patterns). + */ +var reRegExpChar = /[\\^$.*+?()[\]{}|]/g; + +/** Used to detect host constructors (Safari). */ +var reIsHostCtor = /^\[object .+?Constructor\]$/; + +/** Detect free variable `global` from Node.js. */ +var freeGlobal = typeof global == 'object' && global && global.Object === Object && global; + +/** Detect free variable `self`. */ +var freeSelf = typeof self == 'object' && self && self.Object === Object && self; + +/** Used as a reference to the global object. */ +var root = freeGlobal || freeSelf || Function('return this')(); + +/** + * A faster alternative to `Function#apply`, this function invokes `func` + * with the `this` binding of `thisArg` and the arguments of `args`. + * + * @private + * @param {Function} func The function to invoke. + * @param {*} thisArg The `this` binding of `func`. + * @param {Array} args The arguments to invoke `func` with. + * @returns {*} Returns the result of `func`. + */ +function apply(func, thisArg, args) { + switch (args.length) { + case 0: return func.call(thisArg); + case 1: return func.call(thisArg, args[0]); + case 2: return func.call(thisArg, args[0], args[1]); + case 3: return func.call(thisArg, args[0], args[1], args[2]); + } + return func.apply(thisArg, args); +} + +/** + * A specialized version of `_.includes` for arrays without support for + * specifying an index to search from. + * + * @private + * @param {Array} [array] The array to inspect. + * @param {*} target The value to search for. + * @returns {boolean} Returns `true` if `target` is found, else `false`. + */ +function arrayIncludes(array, value) { + var length = array ? array.length : 0; + return !!length && baseIndexOf(array, value, 0) > -1; +} + +/** + * This function is like `arrayIncludes` except that it accepts a comparator. + * + * @private + * @param {Array} [array] The array to inspect. + * @param {*} target The value to search for. + * @param {Function} comparator The comparator invoked per element. + * @returns {boolean} Returns `true` if `target` is found, else `false`. + */ +function arrayIncludesWith(array, value, comparator) { + var index = -1, + length = array ? array.length : 0; + + while (++index < length) { + if (comparator(value, array[index])) { + return true; + } + } + return false; +} + +/** + * Appends the elements of `values` to `array`. + * + * @private + * @param {Array} array The array to modify. + * @param {Array} values The values to append. + * @returns {Array} Returns `array`. + */ +function arrayPush(array, values) { + var index = -1, + length = values.length, + offset = array.length; + + while (++index < length) { + array[offset + index] = values[index]; + } + return array; +} + +/** + * The base implementation of `_.findIndex` and `_.findLastIndex` without + * support for iteratee shorthands. + * + * @private + * @param {Array} array The array to inspect. + * @param {Function} predicate The function invoked per iteration. + * @param {number} fromIndex The index to search from. + * @param {boolean} [fromRight] Specify iterating from right to left. + * @returns {number} Returns the index of the matched value, else `-1`. + */ +function baseFindIndex(array, predicate, fromIndex, fromRight) { + var length = array.length, + index = fromIndex + (fromRight ? 1 : -1); + + while ((fromRight ? index-- : ++index < length)) { + if (predicate(array[index], index, array)) { + return index; + } + } + return -1; +} + +/** + * The base implementation of `_.indexOf` without `fromIndex` bounds checks. + * + * @private + * @param {Array} array The array to inspect. + * @param {*} value The value to search for. + * @param {number} fromIndex The index to search from. + * @returns {number} Returns the index of the matched value, else `-1`. + */ +function baseIndexOf(array, value, fromIndex) { + if (value !== value) { + return baseFindIndex(array, baseIsNaN, fromIndex); + } + var index = fromIndex - 1, + length = array.length; + + while (++index < length) { + if (array[index] === value) { + return index; + } + } + return -1; +} + +/** + * The base implementation of `_.isNaN` without support for number objects. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is `NaN`, else `false`. + */ +function baseIsNaN(value) { + return value !== value; +} + +/** + * Checks if a cache value for `key` exists. + * + * @private + * @param {Object} cache The cache to query. + * @param {string} key The key of the entry to check. + * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. + */ +function cacheHas(cache, key) { + return cache.has(key); +} + +/** + * Gets the value at `key` of `object`. + * + * @private + * @param {Object} [object] The object to query. + * @param {string} key The key of the property to get. + * @returns {*} Returns the property value. + */ +function getValue(object, key) { + return object == null ? undefined : object[key]; +} + +/** + * Checks if `value` is a host object in IE < 9. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a host object, else `false`. + */ +function isHostObject(value) { + // Many host objects are `Object` objects that can coerce to strings + // despite having improperly defined `toString` methods. + var result = false; + if (value != null && typeof value.toString != 'function') { + try { + result = !!(value + ''); + } catch (e) { } + } + return result; +} + +/** + * Converts `set` to an array of its values. + * + * @private + * @param {Object} set The set to convert. + * @returns {Array} Returns the values. + */ +function setToArray(set) { + var index = -1, + result = Array(set.size); + + set.forEach(function (value) { + result[++index] = value; + }); + return result; +} + +/** Used for built-in method references. */ +var arrayProto = Array.prototype, + funcProto = Function.prototype, + objectProto = Object.prototype; + +/** Used to detect overreaching core-js shims. */ +var coreJsData = root['__core-js_shared__']; + +/** Used to detect methods masquerading as native. */ +var maskSrcKey = (function () { + var uid = /[^.]+$/.exec(coreJsData && coreJsData.keys && coreJsData.keys.IE_PROTO || ''); + return uid ? ('Symbol(src)_1.' + uid) : ''; +}()); + +/** Used to resolve the decompiled source of functions. */ +var funcToString = funcProto.toString; + +/** Used to check objects for own properties. */ +var hasOwnProperty = objectProto.hasOwnProperty; + +/** + * Used to resolve the + * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring) + * of values. + */ +var objectToString = objectProto.toString; + +/** Used to detect if a method is native. */ +var reIsNative = RegExp('^' + + funcToString.call(hasOwnProperty).replace(reRegExpChar, '\\$&') + .replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$' +); + +/** Built-in value references. */ +var Symbol = root.Symbol, + propertyIsEnumerable = objectProto.propertyIsEnumerable, + splice = arrayProto.splice, + spreadableSymbol = Symbol ? Symbol.isConcatSpreadable : undefined; + +/* Built-in method references for those with the same name as other `lodash` methods. */ +var nativeMax = Math.max; + +/* Built-in method references that are verified to be native. */ +var Map = getNative(root, 'Map'), + Set = getNative(root, 'Set'), + nativeCreate = getNative(Object, 'create'); + +/** + * Creates a hash object. + * + * @private + * @constructor + * @param {Array} [entries] The key-value pairs to cache. + */ +function Hash(entries) { + var index = -1, + length = entries ? entries.length : 0; + + this.clear(); + while (++index < length) { + var entry = entries[index]; + this.set(entry[0], entry[1]); + } +} + +/** + * Removes all key-value entries from the hash. + * + * @private + * @name clear + * @memberOf Hash + */ +function hashClear() { + this.__data__ = nativeCreate ? nativeCreate(null) : {}; +} + +/** + * Removes `key` and its value from the hash. + * + * @private + * @name delete + * @memberOf Hash + * @param {Object} hash The hash to modify. + * @param {string} key The key of the value to remove. + * @returns {boolean} Returns `true` if the entry was removed, else `false`. + */ +function hashDelete(key) { + return this.has(key) && delete this.__data__[key]; +} + +/** + * Gets the hash value for `key`. + * + * @private + * @name get + * @memberOf Hash + * @param {string} key The key of the value to get. + * @returns {*} Returns the entry value. + */ +function hashGet(key) { + var data = this.__data__; + if (nativeCreate) { + var result = data[key]; + return result === HASH_UNDEFINED ? undefined : result; + } + return hasOwnProperty.call(data, key) ? data[key] : undefined; +} + +/** + * Checks if a hash value for `key` exists. + * + * @private + * @name has + * @memberOf Hash + * @param {string} key The key of the entry to check. + * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. + */ +function hashHas(key) { + var data = this.__data__; + return nativeCreate ? data[key] !== undefined : hasOwnProperty.call(data, key); +} + +/** + * Sets the hash `key` to `value`. + * + * @private + * @name set + * @memberOf Hash + * @param {string} key The key of the value to set. + * @param {*} value The value to set. + * @returns {Object} Returns the hash instance. + */ +function hashSet(key, value) { + var data = this.__data__; + data[key] = (nativeCreate && value === undefined) ? HASH_UNDEFINED : value; + return this; +} + +// Add methods to `Hash`. +Hash.prototype.clear = hashClear; +Hash.prototype['delete'] = hashDelete; +Hash.prototype.get = hashGet; +Hash.prototype.has = hashHas; +Hash.prototype.set = hashSet; + +/** + * Creates an list cache object. + * + * @private + * @constructor + * @param {Array} [entries] The key-value pairs to cache. + */ +function ListCache(entries) { + var index = -1, + length = entries ? entries.length : 0; + + this.clear(); + while (++index < length) { + var entry = entries[index]; + this.set(entry[0], entry[1]); + } +} + +/** + * Removes all key-value entries from the list cache. + * + * @private + * @name clear + * @memberOf ListCache + */ +function listCacheClear() { + this.__data__ = []; +} + +/** + * Removes `key` and its value from the list cache. + * + * @private + * @name delete + * @memberOf ListCache + * @param {string} key The key of the value to remove. + * @returns {boolean} Returns `true` if the entry was removed, else `false`. + */ +function listCacheDelete(key) { + var data = this.__data__, + index = assocIndexOf(data, key); + + if (index < 0) { + return false; + } + var lastIndex = data.length - 1; + if (index == lastIndex) { + data.pop(); + } else { + splice.call(data, index, 1); + } + return true; +} + +/** + * Gets the list cache value for `key`. + * + * @private + * @name get + * @memberOf ListCache + * @param {string} key The key of the value to get. + * @returns {*} Returns the entry value. + */ +function listCacheGet(key) { + var data = this.__data__, + index = assocIndexOf(data, key); + + return index < 0 ? undefined : data[index][1]; +} + +/** + * Checks if a list cache value for `key` exists. + * + * @private + * @name has + * @memberOf ListCache + * @param {string} key The key of the entry to check. + * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. + */ +function listCacheHas(key) { + return assocIndexOf(this.__data__, key) > -1; +} + +/** + * Sets the list cache `key` to `value`. + * + * @private + * @name set + * @memberOf ListCache + * @param {string} key The key of the value to set. + * @param {*} value The value to set. + * @returns {Object} Returns the list cache instance. + */ +function listCacheSet(key, value) { + var data = this.__data__, + index = assocIndexOf(data, key); + + if (index < 0) { + data.push([key, value]); + } else { + data[index][1] = value; + } + return this; +} + +// Add methods to `ListCache`. +ListCache.prototype.clear = listCacheClear; +ListCache.prototype['delete'] = listCacheDelete; +ListCache.prototype.get = listCacheGet; +ListCache.prototype.has = listCacheHas; +ListCache.prototype.set = listCacheSet; + +/** + * Creates a map cache object to store key-value pairs. + * + * @private + * @constructor + * @param {Array} [entries] The key-value pairs to cache. + */ +function MapCache(entries) { + var index = -1, + length = entries ? entries.length : 0; + + this.clear(); + while (++index < length) { + var entry = entries[index]; + this.set(entry[0], entry[1]); + } +} + +/** + * Removes all key-value entries from the map. + * + * @private + * @name clear + * @memberOf MapCache + */ +function mapCacheClear() { + this.__data__ = { + 'hash': new Hash, + 'map': new (Map || ListCache), + 'string': new Hash + }; +} + +/** + * Removes `key` and its value from the map. + * + * @private + * @name delete + * @memberOf MapCache + * @param {string} key The key of the value to remove. + * @returns {boolean} Returns `true` if the entry was removed, else `false`. + */ +function mapCacheDelete(key) { + return getMapData(this, key)['delete'](key); +} + +/** + * Gets the map value for `key`. + * + * @private + * @name get + * @memberOf MapCache + * @param {string} key The key of the value to get. + * @returns {*} Returns the entry value. + */ +function mapCacheGet(key) { + return getMapData(this, key).get(key); +} + +/** + * Checks if a map value for `key` exists. + * + * @private + * @name has + * @memberOf MapCache + * @param {string} key The key of the entry to check. + * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. + */ +function mapCacheHas(key) { + return getMapData(this, key).has(key); +} + +/** + * Sets the map `key` to `value`. + * + * @private + * @name set + * @memberOf MapCache + * @param {string} key The key of the value to set. + * @param {*} value The value to set. + * @returns {Object} Returns the map cache instance. + */ +function mapCacheSet(key, value) { + getMapData(this, key).set(key, value); + return this; +} + +// Add methods to `MapCache`. +MapCache.prototype.clear = mapCacheClear; +MapCache.prototype['delete'] = mapCacheDelete; +MapCache.prototype.get = mapCacheGet; +MapCache.prototype.has = mapCacheHas; +MapCache.prototype.set = mapCacheSet; + +/** + * + * Creates an array cache object to store unique values. + * + * @private + * @constructor + * @param {Array} [values] The values to cache. + */ +function SetCache(values) { + var index = -1, + length = values ? values.length : 0; + + this.__data__ = new MapCache; + while (++index < length) { + this.add(values[index]); + } +} + +/** + * Adds `value` to the array cache. + * + * @private + * @name add + * @memberOf SetCache + * @alias push + * @param {*} value The value to cache. + * @returns {Object} Returns the cache instance. + */ +function setCacheAdd(value) { + this.__data__.set(value, HASH_UNDEFINED); + return this; +} + +/** + * Checks if `value` is in the array cache. + * + * @private + * @name has + * @memberOf SetCache + * @param {*} value The value to search for. + * @returns {number} Returns `true` if `value` is found, else `false`. + */ +function setCacheHas(value) { + return this.__data__.has(value); +} + +// Add methods to `SetCache`. +SetCache.prototype.add = SetCache.prototype.push = setCacheAdd; +SetCache.prototype.has = setCacheHas; + +/** + * Gets the index at which the `key` is found in `array` of key-value pairs. + * + * @private + * @param {Array} array The array to inspect. + * @param {*} key The key to search for. + * @returns {number} Returns the index of the matched value, else `-1`. + */ +function assocIndexOf(array, key) { + var length = array.length; + while (length--) { + if (eq(array[length][0], key)) { + return length; + } + } + return -1; +} + +/** + * The base implementation of `_.flatten` with support for restricting flattening. + * + * @private + * @param {Array} array The array to flatten. + * @param {number} depth The maximum recursion depth. + * @param {boolean} [predicate=isFlattenable] The function invoked per iteration. + * @param {boolean} [isStrict] Restrict to values that pass `predicate` checks. + * @param {Array} [result=[]] The initial result value. + * @returns {Array} Returns the new flattened array. + */ +function baseFlatten(array, depth, predicate, isStrict, result) { + var index = -1, + length = array.length; + + predicate || (predicate = isFlattenable); + result || (result = []); + + while (++index < length) { + var value = array[index]; + if (depth > 0 && predicate(value)) { + if (depth > 1) { + // Recursively flatten arrays (susceptible to call stack limits). + baseFlatten(value, depth - 1, predicate, isStrict, result); + } else { + arrayPush(result, value); + } + } else if (!isStrict) { + result[result.length] = value; + } + } + return result; +} + +/** + * The base implementation of `_.isNative` without bad shim checks. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a native function, + * else `false`. + */ +function baseIsNative(value) { + if (!isObject(value) || isMasked(value)) { + return false; + } + var pattern = (isFunction(value) || isHostObject(value)) ? reIsNative : reIsHostCtor; + return pattern.test(toSource(value)); +} + +/** + * The base implementation of `_.rest` which doesn't validate or coerce arguments. + * + * @private + * @param {Function} func The function to apply a rest parameter to. + * @param {number} [start=func.length-1] The start position of the rest parameter. + * @returns {Function} Returns the new function. + */ +function baseRest(func, start) { + start = nativeMax(start === undefined ? (func.length - 1) : start, 0); + return function () { + var args = arguments, + index = -1, + length = nativeMax(args.length - start, 0), + array = Array(length); + + while (++index < length) { + array[index] = args[start + index]; + } + index = -1; + var otherArgs = Array(start + 1); + while (++index < start) { + otherArgs[index] = args[index]; + } + otherArgs[start] = array; + return apply(func, this, otherArgs); + }; +} + +/** + * The base implementation of `_.uniqBy` without support for iteratee shorthands. + * + * @private + * @param {Array} array The array to inspect. + * @param {Function} [iteratee] The iteratee invoked per element. + * @param {Function} [comparator] The comparator invoked per element. + * @returns {Array} Returns the new duplicate free array. + */ +function baseUniq(array, iteratee, comparator) { + var index = -1, + includes = arrayIncludes, + length = array.length, + isCommon = true, + result = [], + seen = result; + + if (comparator) { + isCommon = false; + includes = arrayIncludesWith; + } + else if (length >= LARGE_ARRAY_SIZE) { + var set = iteratee ? null : createSet(array); + if (set) { + return setToArray(set); + } + isCommon = false; + includes = cacheHas; + seen = new SetCache; + } + else { + seen = iteratee ? [] : result; + } + outer: + while (++index < length) { + var value = array[index], + computed = iteratee ? iteratee(value) : value; + + value = (comparator || value !== 0) ? value : 0; + if (isCommon && computed === computed) { + var seenIndex = seen.length; + while (seenIndex--) { + if (seen[seenIndex] === computed) { + continue outer; + } + } + if (iteratee) { + seen.push(computed); + } + result.push(value); + } + else if (!includes(seen, computed, comparator)) { + if (seen !== result) { + seen.push(computed); + } + result.push(value); + } + } + return result; +} + +/** + * Creates a set object of `values`. + * + * @private + * @param {Array} values The values to add to the set. + * @returns {Object} Returns the new set. + */ +var createSet = !(Set && (1 / setToArray(new Set([, -0]))[1]) == INFINITY) ? noop : function (values) { + return new Set(values); +}; + +/** + * Gets the data for `map`. + * + * @private + * @param {Object} map The map to query. + * @param {string} key The reference key. + * @returns {*} Returns the map data. + */ +function getMapData(map, key) { + var data = map.__data__; + return isKeyable(key) + ? data[typeof key == 'string' ? 'string' : 'hash'] + : data.map; +} + +/** + * Gets the native function at `key` of `object`. + * + * @private + * @param {Object} object The object to query. + * @param {string} key The key of the method to get. + * @returns {*} Returns the function if it's native, else `undefined`. + */ +function getNative(object, key) { + var value = getValue(object, key); + return baseIsNative(value) ? value : undefined; +} + +/** + * Checks if `value` is a flattenable `arguments` object or array. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is flattenable, else `false`. + */ +function isFlattenable(value) { + return isArray(value) || isArguments(value) || + !!(spreadableSymbol && value && value[spreadableSymbol]); +} + +/** + * Checks if `value` is suitable for use as unique object key. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is suitable, else `false`. + */ +function isKeyable(value) { + var type = typeof value; + return (type == 'string' || type == 'number' || type == 'symbol' || type == 'boolean') + ? (value !== '__proto__') + : (value === null); +} + +/** + * Checks if `func` has its source masked. + * + * @private + * @param {Function} func The function to check. + * @returns {boolean} Returns `true` if `func` is masked, else `false`. + */ +function isMasked(func) { + return !!maskSrcKey && (maskSrcKey in func); +} + +/** + * Converts `func` to its source code. + * + * @private + * @param {Function} func The function to process. + * @returns {string} Returns the source code. + */ +function toSource(func) { + if (func != null) { + try { + return funcToString.call(func); + } catch (e) { } + try { + return (func + ''); + } catch (e) { } + } + return ''; +} + +/** + * Creates an array of unique values, in order, from all given arrays using + * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) + * for equality comparisons. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Array + * @param {...Array} [arrays] The arrays to inspect. + * @returns {Array} Returns the new array of combined values. + * @example + * + * _.union([2], [1, 2]); + * // => [2, 1] + */ +var union = baseRest(function (arrays) { + return baseUniq(baseFlatten(arrays, 1, isArrayLikeObject, true)); +}); + +/** + * Performs a + * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) + * comparison between two values to determine if they are equivalent. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @returns {boolean} Returns `true` if the values are equivalent, else `false`. + * @example + * + * var object = { 'a': 1 }; + * var other = { 'a': 1 }; + * + * _.eq(object, object); + * // => true + * + * _.eq(object, other); + * // => false + * + * _.eq('a', 'a'); + * // => true + * + * _.eq('a', Object('a')); + * // => false + * + * _.eq(NaN, NaN); + * // => true + */ +function eq(value, other) { + return value === other || (value !== value && other !== other); +} + +/** + * Checks if `value` is likely an `arguments` object. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an `arguments` object, + * else `false`. + * @example + * + * _.isArguments(function() { return arguments; }()); + * // => true + * + * _.isArguments([1, 2, 3]); + * // => false + */ +function isArguments(value) { + // Safari 8.1 makes `arguments.callee` enumerable in strict mode. + return isArrayLikeObject(value) && hasOwnProperty.call(value, 'callee') && + (!propertyIsEnumerable.call(value, 'callee') || objectToString.call(value) == argsTag); +} + +/** + * Checks if `value` is classified as an `Array` object. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an array, else `false`. + * @example + * + * _.isArray([1, 2, 3]); + * // => true + * + * _.isArray(document.body.children); + * // => false + * + * _.isArray('abc'); + * // => false + * + * _.isArray(_.noop); + * // => false + */ +var isArray = Array.isArray; + +/** + * Checks if `value` is array-like. A value is considered array-like if it's + * not a function and has a `value.length` that's an integer greater than or + * equal to `0` and less than or equal to `Number.MAX_SAFE_INTEGER`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is array-like, else `false`. + * @example + * + * _.isArrayLike([1, 2, 3]); + * // => true + * + * _.isArrayLike(document.body.children); + * // => true + * + * _.isArrayLike('abc'); + * // => true + * + * _.isArrayLike(_.noop); + * // => false + */ +function isArrayLike(value) { + return value != null && isLength(value.length) && !isFunction(value); +} + +/** + * This method is like `_.isArrayLike` except that it also checks if `value` + * is an object. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an array-like object, + * else `false`. + * @example + * + * _.isArrayLikeObject([1, 2, 3]); + * // => true + * + * _.isArrayLikeObject(document.body.children); + * // => true + * + * _.isArrayLikeObject('abc'); + * // => false + * + * _.isArrayLikeObject(_.noop); + * // => false + */ +function isArrayLikeObject(value) { + return isObjectLike(value) && isArrayLike(value); +} + +/** + * Checks if `value` is classified as a `Function` object. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a function, else `false`. + * @example + * + * _.isFunction(_); + * // => true + * + * _.isFunction(/abc/); + * // => false + */ +function isFunction(value) { + // The use of `Object#toString` avoids issues with the `typeof` operator + // in Safari 8-9 which returns 'object' for typed array and other constructors. + var tag = isObject(value) ? objectToString.call(value) : ''; + return tag == funcTag || tag == genTag; +} + +/** + * Checks if `value` is a valid array-like length. + * + * **Note:** This method is loosely based on + * [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a valid length, else `false`. + * @example + * + * _.isLength(3); + * // => true + * + * _.isLength(Number.MIN_VALUE); + * // => false + * + * _.isLength(Infinity); + * // => false + * + * _.isLength('3'); + * // => false + */ +function isLength(value) { + return typeof value == 'number' && + value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER; +} + +/** + * Checks if `value` is the + * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types) + * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`) + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an object, else `false`. + * @example + * + * _.isObject({}); + * // => true + * + * _.isObject([1, 2, 3]); + * // => true + * + * _.isObject(_.noop); + * // => true + * + * _.isObject(null); + * // => false + */ +function isObject(value) { + var type = typeof value; + return !!value && (type == 'object' || type == 'function'); +} + +/** + * Checks if `value` is object-like. A value is object-like if it's not `null` + * and has a `typeof` result of "object". + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is object-like, else `false`. + * @example + * + * _.isObjectLike({}); + * // => true + * + * _.isObjectLike([1, 2, 3]); + * // => true + * + * _.isObjectLike(_.noop); + * // => false + * + * _.isObjectLike(null); + * // => false + */ +function isObjectLike(value) { + return !!value && typeof value == 'object'; +} + +/** + * This method returns `undefined`. + * + * @static + * @memberOf _ + * @since 2.3.0 + * @category Util + * @example + * + * _.times(2, _.noop); + * // => [undefined, undefined] + */ +function noop() { + // No operation performed. +} + +module.exports = union; diff --git a/server/libs/archiver/archiverUtils/minimatch/LICENSE b/server/libs/archiver/archiverUtils/minimatch/LICENSE new file mode 100644 index 000000000..4b258d19e --- /dev/null +++ b/server/libs/archiver/archiverUtils/minimatch/LICENSE @@ -0,0 +1,15 @@ +The ISC License + +Copyright (c) 2011-2022 Isaac Z. Schlueter and Contributors + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR +IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. \ No newline at end of file diff --git a/server/libs/archiver/archiverUtils/minimatch/index.js b/server/libs/archiver/archiverUtils/minimatch/index.js new file mode 100644 index 000000000..c9fe5de73 --- /dev/null +++ b/server/libs/archiver/archiverUtils/minimatch/index.js @@ -0,0 +1,909 @@ +const minimatch = module.exports = (p, pattern, options = {}) => { + assertValidPattern(pattern) + + // shortcut: comments match nothing. + if (!options.nocomment && pattern.charAt(0) === '#') { + return false + } + + return new Minimatch(pattern, options).match(p) +} + +module.exports = minimatch + +const isWindows = typeof process === 'object' && + process && + process.platform === 'win32' +const path = isWindows ? { sep: '\\' } : { sep: '/' } +minimatch.sep = path.sep + +const GLOBSTAR = Symbol('globstar **') +minimatch.GLOBSTAR = GLOBSTAR +const expand = require('../braceExpansion') + +const plTypes = { + '!': { open: '(?:(?!(?:', close: '))[^/]*?)' }, + '?': { open: '(?:', close: ')?' }, + '+': { open: '(?:', close: ')+' }, + '*': { open: '(?:', close: ')*' }, + '@': { open: '(?:', close: ')' } +} + +// any single thing other than / +// don't need to escape / when using new RegExp() +const qmark = '[^/]' + +// * => any number of characters +const star = qmark + '*?' + +// ** when dots are allowed. Anything goes, except .. and . +// not (^ or / followed by one or two dots followed by $ or /), +// followed by anything, any number of times. +const twoStarDot = '(?:(?!(?:\\\/|^)(?:\\.{1,2})($|\\\/)).)*?' + +// not a ^ or / followed by a dot, +// followed by anything, any number of times. +const twoStarNoDot = '(?:(?!(?:\\\/|^)\\.).)*?' + +// "abc" -> { a:true, b:true, c:true } +const charSet = s => s.split('').reduce((set, c) => { + set[c] = true + return set +}, {}) + +// characters that need to be escaped in RegExp. +const reSpecials = charSet('().*{}+?[]^$\\!') + +// characters that indicate we have to add the pattern start +const addPatternStartSet = charSet('[.(') + +// normalizes slashes. +const slashSplit = /\/+/ + +minimatch.filter = (pattern, options = {}) => + (p, i, list) => minimatch(p, pattern, options) + +const ext = (a, b = {}) => { + const t = {} + Object.keys(a).forEach(k => t[k] = a[k]) + Object.keys(b).forEach(k => t[k] = b[k]) + return t +} + +minimatch.defaults = def => { + if (!def || typeof def !== 'object' || !Object.keys(def).length) { + return minimatch + } + + const orig = minimatch + + const m = (p, pattern, options) => orig(p, pattern, ext(def, options)) + m.Minimatch = class Minimatch extends orig.Minimatch { + constructor(pattern, options) { + super(pattern, ext(def, options)) + } + } + m.Minimatch.defaults = options => orig.defaults(ext(def, options)).Minimatch + m.filter = (pattern, options) => orig.filter(pattern, ext(def, options)) + m.defaults = options => orig.defaults(ext(def, options)) + m.makeRe = (pattern, options) => orig.makeRe(pattern, ext(def, options)) + m.braceExpand = (pattern, options) => orig.braceExpand(pattern, ext(def, options)) + m.match = (list, pattern, options) => orig.match(list, pattern, ext(def, options)) + + return m +} + + + + + +// Brace expansion: +// a{b,c}d -> abd acd +// a{b,}c -> abc ac +// a{0..3}d -> a0d a1d a2d a3d +// a{b,c{d,e}f}g -> abg acdfg acefg +// a{b,c}d{e,f}g -> abdeg acdeg abdeg abdfg +// +// Invalid sets are not expanded. +// a{2..}b -> a{2..}b +// a{b}c -> a{b}c +minimatch.braceExpand = (pattern, options) => braceExpand(pattern, options) + +const braceExpand = (pattern, options = {}) => { + assertValidPattern(pattern) + + // Thanks to Yeting Li for + // improving this regexp to avoid a ReDOS vulnerability. + if (options.nobrace || !/\{(?:(?!\{).)*\}/.test(pattern)) { + // shortcut. no need to expand. + return [pattern] + } + + return expand(pattern) +} + +const MAX_PATTERN_LENGTH = 1024 * 64 +const assertValidPattern = pattern => { + if (typeof pattern !== 'string') { + throw new TypeError('invalid pattern') + } + + if (pattern.length > MAX_PATTERN_LENGTH) { + throw new TypeError('pattern is too long') + } +} + +// parse a component of the expanded set. +// At this point, no pattern may contain "/" in it +// so we're going to return a 2d array, where each entry is the full +// pattern, split on '/', and then turned into a regular expression. +// A regexp is made at the end which joins each array with an +// escaped /, and another full one which joins each regexp with |. +// +// Following the lead of Bash 4.1, note that "**" only has special meaning +// when it is the *only* thing in a path portion. Otherwise, any series +// of * is equivalent to a single *. Globstar behavior is enabled by +// default, and can be disabled by setting options.noglobstar. +const SUBPARSE = Symbol('subparse') + +minimatch.makeRe = (pattern, options) => + new Minimatch(pattern, options || {}).makeRe() + +minimatch.match = (list, pattern, options = {}) => { + const mm = new Minimatch(pattern, options) + list = list.filter(f => mm.match(f)) + if (mm.options.nonull && !list.length) { + list.push(pattern) + } + return list +} + +// replace stuff like \* with * +const globUnescape = s => s.replace(/\\(.)/g, '$1') +const regExpEscape = s => s.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&') + +class Minimatch { + constructor(pattern, options) { + assertValidPattern(pattern) + + if (!options) options = {} + + this.options = options + this.set = [] + this.pattern = pattern + this.windowsPathsNoEscape = !!options.windowsPathsNoEscape || + options.allowWindowsEscape === false + if (this.windowsPathsNoEscape) { + this.pattern = this.pattern.replace(/\\/g, '/') + } + this.regexp = null + this.negate = false + this.comment = false + this.empty = false + this.partial = !!options.partial + + // make the set of regexps etc. + this.make() + } + + debug() { } + + make() { + const pattern = this.pattern + const options = this.options + + // empty patterns and comments match nothing. + if (!options.nocomment && pattern.charAt(0) === '#') { + this.comment = true + return + } + if (!pattern) { + this.empty = true + return + } + + // step 1: figure out negation, etc. + this.parseNegate() + + // step 2: expand braces + let set = this.globSet = this.braceExpand() + + if (options.debug) this.debug = (...args) => console.error(...args) + + this.debug(this.pattern, set) + + // step 3: now we have a set, so turn each one into a series of path-portion + // matching patterns. + // These will be regexps, except in the case of "**", which is + // set to the GLOBSTAR object for globstar behavior, + // and will not contain any / characters + set = this.globParts = set.map(s => s.split(slashSplit)) + + this.debug(this.pattern, set) + + // glob --> regexps + set = set.map((s, si, set) => s.map(this.parse, this)) + + this.debug(this.pattern, set) + + // filter out everything that didn't compile properly. + set = set.filter(s => s.indexOf(false) === -1) + + this.debug(this.pattern, set) + + this.set = set + } + + parseNegate() { + if (this.options.nonegate) return + + const pattern = this.pattern + let negate = false + let negateOffset = 0 + + for (let i = 0; i < pattern.length && pattern.charAt(i) === '!'; i++) { + negate = !negate + negateOffset++ + } + + if (negateOffset) this.pattern = pattern.substr(negateOffset) + this.negate = negate + } + + // set partial to true to test if, for example, + // "/a/b" matches the start of "/*/b/*/d" + // Partial means, if you run out of file before you run + // out of pattern, then that's fine, as long as all + // the parts match. + matchOne(file, pattern, partial) { + var options = this.options + + this.debug('matchOne', + { 'this': this, file: file, pattern: pattern }) + + this.debug('matchOne', file.length, pattern.length) + + for (var fi = 0, + pi = 0, + fl = file.length, + pl = pattern.length + ; (fi < fl) && (pi < pl) + ; fi++, pi++) { + this.debug('matchOne loop') + var p = pattern[pi] + var f = file[fi] + + this.debug(pattern, p, f) + + // should be impossible. + // some invalid regexp stuff in the set. + /* istanbul ignore if */ + if (p === false) return false + + if (p === GLOBSTAR) { + this.debug('GLOBSTAR', [pattern, p, f]) + + // "**" + // a/**/b/**/c would match the following: + // a/b/x/y/z/c + // a/x/y/z/b/c + // a/b/x/b/x/c + // a/b/c + // To do this, take the rest of the pattern after + // the **, and see if it would match the file remainder. + // If so, return success. + // If not, the ** "swallows" a segment, and try again. + // This is recursively awful. + // + // a/**/b/**/c matching a/b/x/y/z/c + // - a matches a + // - doublestar + // - matchOne(b/x/y/z/c, b/**/c) + // - b matches b + // - doublestar + // - matchOne(x/y/z/c, c) -> no + // - matchOne(y/z/c, c) -> no + // - matchOne(z/c, c) -> no + // - matchOne(c, c) yes, hit + var fr = fi + var pr = pi + 1 + if (pr === pl) { + this.debug('** at the end') + // a ** at the end will just swallow the rest. + // We have found a match. + // however, it will not swallow /.x, unless + // options.dot is set. + // . and .. are *never* matched by **, for explosively + // exponential reasons. + for (; fi < fl; fi++) { + if (file[fi] === '.' || file[fi] === '..' || + (!options.dot && file[fi].charAt(0) === '.')) return false + } + return true + } + + // ok, let's see if we can swallow whatever we can. + while (fr < fl) { + var swallowee = file[fr] + + this.debug('\nglobstar while', file, fr, pattern, pr, swallowee) + + // XXX remove this slice. Just pass the start index. + if (this.matchOne(file.slice(fr), pattern.slice(pr), partial)) { + this.debug('globstar found match!', fr, fl, swallowee) + // found a match. + return true + } else { + // can't swallow "." or ".." ever. + // can only swallow ".foo" when explicitly asked. + if (swallowee === '.' || swallowee === '..' || + (!options.dot && swallowee.charAt(0) === '.')) { + this.debug('dot detected!', file, fr, pattern, pr) + break + } + + // ** swallows a segment, and continue. + this.debug('globstar swallow a segment, and continue') + fr++ + } + } + + // no match was found. + // However, in partial mode, we can't say this is necessarily over. + // If there's more *pattern* left, then + /* istanbul ignore if */ + if (partial) { + // ran out of file + this.debug('\n>>> no match, partial?', file, fr, pattern, pr) + if (fr === fl) return true + } + return false + } + + // something other than ** + // non-magic patterns just have to match exactly + // patterns with magic have been turned into regexps. + var hit + if (typeof p === 'string') { + hit = f === p + this.debug('string match', p, f, hit) + } else { + hit = f.match(p) + this.debug('pattern match', p, f, hit) + } + + if (!hit) return false + } + + // Note: ending in / means that we'll get a final "" + // at the end of the pattern. This can only match a + // corresponding "" at the end of the file. + // If the file ends in /, then it can only match a + // a pattern that ends in /, unless the pattern just + // doesn't have any more for it. But, a/b/ should *not* + // match "a/b/*", even though "" matches against the + // [^/]*? pattern, except in partial mode, where it might + // simply not be reached yet. + // However, a/b/ should still satisfy a/* + + // now either we fell off the end of the pattern, or we're done. + if (fi === fl && pi === pl) { + // ran out of pattern and filename at the same time. + // an exact hit! + return true + } else if (fi === fl) { + // ran out of file, but still had pattern left. + // this is ok if we're doing the match as part of + // a glob fs traversal. + return partial + } else /* istanbul ignore else */ if (pi === pl) { + // ran out of pattern, still have file left. + // this is only acceptable if we're on the very last + // empty segment of a file with a trailing slash. + // a/* should match a/b/ + return (fi === fl - 1) && (file[fi] === '') + } + + // should be unreachable. + /* istanbul ignore next */ + throw new Error('wtf?') + } + + braceExpand() { + return braceExpand(this.pattern, this.options) + } + + parse(pattern, isSub) { + assertValidPattern(pattern) + + const options = this.options + + // shortcuts + if (pattern === '**') { + if (!options.noglobstar) + return GLOBSTAR + else + pattern = '*' + } + if (pattern === '') return '' + + let re = '' + let hasMagic = !!options.nocase + let escaping = false + // ? => one single character + const patternListStack = [] + const negativeLists = [] + let stateChar + let inClass = false + let reClassStart = -1 + let classStart = -1 + let cs + let pl + let sp + // . and .. never match anything that doesn't start with ., + // even when options.dot is set. + const patternStart = pattern.charAt(0) === '.' ? '' // anything + // not (start or / followed by . or .. followed by / or end) + : options.dot ? '(?!(?:^|\\\/)\\.{1,2}(?:$|\\\/))' + : '(?!\\.)' + + const clearStateChar = () => { + if (stateChar) { + // we had some state-tracking character + // that wasn't consumed by this pass. + switch (stateChar) { + case '*': + re += star + hasMagic = true + break + case '?': + re += qmark + hasMagic = true + break + default: + re += '\\' + stateChar + break + } + this.debug('clearStateChar %j %j', stateChar, re) + stateChar = false + } + } + + for (let i = 0, c; (i < pattern.length) && (c = pattern.charAt(i)); i++) { + this.debug('%s\t%s %s %j', pattern, i, re, c) + + // skip over any that are escaped. + if (escaping) { + /* istanbul ignore next - completely not allowed, even escaped. */ + if (c === '/') { + return false + } + + if (reSpecials[c]) { + re += '\\' + } + re += c + escaping = false + continue + } + + switch (c) { + /* istanbul ignore next */ + case '/': { + // Should already be path-split by now. + return false + } + + case '\\': + clearStateChar() + escaping = true + continue + + // the various stateChar values + // for the "extglob" stuff. + case '?': + case '*': + case '+': + case '@': + case '!': + this.debug('%s\t%s %s %j <-- stateChar', pattern, i, re, c) + + // all of those are literals inside a class, except that + // the glob [!a] means [^a] in regexp + if (inClass) { + this.debug(' in class') + if (c === '!' && i === classStart + 1) c = '^' + re += c + continue + } + + // if we already have a stateChar, then it means + // that there was something like ** or +? in there. + // Handle the stateChar, then proceed with this one. + this.debug('call clearStateChar %j', stateChar) + clearStateChar() + stateChar = c + // if extglob is disabled, then +(asdf|foo) isn't a thing. + // just clear the statechar *now*, rather than even diving into + // the patternList stuff. + if (options.noext) clearStateChar() + continue + + case '(': + if (inClass) { + re += '(' + continue + } + + if (!stateChar) { + re += '\\(' + continue + } + + patternListStack.push({ + type: stateChar, + start: i - 1, + reStart: re.length, + open: plTypes[stateChar].open, + close: plTypes[stateChar].close + }) + // negation is (?:(?!js)[^/]*) + re += stateChar === '!' ? '(?:(?!(?:' : '(?:' + this.debug('plType %j %j', stateChar, re) + stateChar = false + continue + + case ')': + if (inClass || !patternListStack.length) { + re += '\\)' + continue + } + + clearStateChar() + hasMagic = true + pl = patternListStack.pop() + // negation is (?:(?!js)[^/]*) + // The others are (?:) + re += pl.close + if (pl.type === '!') { + negativeLists.push(pl) + } + pl.reEnd = re.length + continue + + case '|': + if (inClass || !patternListStack.length) { + re += '\\|' + continue + } + + clearStateChar() + re += '|' + continue + + // these are mostly the same in regexp and glob + case '[': + // swallow any state-tracking char before the [ + clearStateChar() + + if (inClass) { + re += '\\' + c + continue + } + + inClass = true + classStart = i + reClassStart = re.length + re += c + continue + + case ']': + // a right bracket shall lose its special + // meaning and represent itself in + // a bracket expression if it occurs + // first in the list. -- POSIX.2 2.8.3.2 + if (i === classStart + 1 || !inClass) { + re += '\\' + c + continue + } + + // handle the case where we left a class open. + // "[z-a]" is valid, equivalent to "\[z-a\]" + // split where the last [ was, make sure we don't have + // an invalid re. if so, re-walk the contents of the + // would-be class to re-translate any characters that + // were passed through as-is + // TODO: It would probably be faster to determine this + // without a try/catch and a new RegExp, but it's tricky + // to do safely. For now, this is safe and works. + cs = pattern.substring(classStart + 1, i) + try { + RegExp('[' + cs + ']') + } catch (er) { + // not a valid class! + sp = this.parse(cs, SUBPARSE) + re = re.substr(0, reClassStart) + '\\[' + sp[0] + '\\]' + hasMagic = hasMagic || sp[1] + inClass = false + continue + } + + // finish up the class. + hasMagic = true + inClass = false + re += c + continue + + default: + // swallow any state char that wasn't consumed + clearStateChar() + + if (reSpecials[c] && !(c === '^' && inClass)) { + re += '\\' + } + + re += c + break + + } // switch + } // for + + // handle the case where we left a class open. + // "[abc" is valid, equivalent to "\[abc" + if (inClass) { + // split where the last [ was, and escape it + // this is a huge pita. We now have to re-walk + // the contents of the would-be class to re-translate + // any characters that were passed through as-is + cs = pattern.substr(classStart + 1) + sp = this.parse(cs, SUBPARSE) + re = re.substr(0, reClassStart) + '\\[' + sp[0] + hasMagic = hasMagic || sp[1] + } + + // handle the case where we had a +( thing at the *end* + // of the pattern. + // each pattern list stack adds 3 chars, and we need to go through + // and escape any | chars that were passed through as-is for the regexp. + // Go through and escape them, taking care not to double-escape any + // | chars that were already escaped. + for (pl = patternListStack.pop(); pl; pl = patternListStack.pop()) { + let tail + tail = re.slice(pl.reStart + pl.open.length) + this.debug('setting tail', re, pl) + // maybe some even number of \, then maybe 1 \, followed by a | + tail = tail.replace(/((?:\\{2}){0,64})(\\?)\|/g, (_, $1, $2) => { + /* istanbul ignore else - should already be done */ + if (!$2) { + // the | isn't already escaped, so escape it. + $2 = '\\' + } + + // need to escape all those slashes *again*, without escaping the + // one that we need for escaping the | character. As it works out, + // escaping an even number of slashes can be done by simply repeating + // it exactly after itself. That's why this trick works. + // + // I am sorry that you have to see this. + return $1 + $1 + $2 + '|' + }) + + this.debug('tail=%j\n %s', tail, tail, pl, re) + const t = pl.type === '*' ? star + : pl.type === '?' ? qmark + : '\\' + pl.type + + hasMagic = true + re = re.slice(0, pl.reStart) + t + '\\(' + tail + } + + // handle trailing things that only matter at the very end. + clearStateChar() + if (escaping) { + // trailing \\ + re += '\\\\' + } + + // only need to apply the nodot start if the re starts with + // something that could conceivably capture a dot + const addPatternStart = addPatternStartSet[re.charAt(0)] + + // Hack to work around lack of negative lookbehind in JS + // A pattern like: *.!(x).!(y|z) needs to ensure that a name + // like 'a.xyz.yz' doesn't match. So, the first negative + // lookahead, has to look ALL the way ahead, to the end of + // the pattern. + for (let n = negativeLists.length - 1; n > -1; n--) { + const nl = negativeLists[n] + + const nlBefore = re.slice(0, nl.reStart) + const nlFirst = re.slice(nl.reStart, nl.reEnd - 8) + let nlAfter = re.slice(nl.reEnd) + const nlLast = re.slice(nl.reEnd - 8, nl.reEnd) + nlAfter + + // Handle nested stuff like *(*.js|!(*.json)), where open parens + // mean that we should *not* include the ) in the bit that is considered + // "after" the negated section. + const openParensBefore = nlBefore.split('(').length - 1 + let cleanAfter = nlAfter + for (let i = 0; i < openParensBefore; i++) { + cleanAfter = cleanAfter.replace(/\)[+*?]?/, '') + } + nlAfter = cleanAfter + + const dollar = nlAfter === '' && isSub !== SUBPARSE ? '$' : '' + re = nlBefore + nlFirst + nlAfter + dollar + nlLast + } + + // if the re is not "" at this point, then we need to make sure + // it doesn't match against an empty path part. + // Otherwise a/* will match a/, which it should not. + if (re !== '' && hasMagic) { + re = '(?=.)' + re + } + + if (addPatternStart) { + re = patternStart + re + } + + // parsing just a piece of a larger pattern. + if (isSub === SUBPARSE) { + return [re, hasMagic] + } + + // skip the regexp for non-magical patterns + // unescape anything in it, though, so that it'll be + // an exact match against a file etc. + if (!hasMagic) { + return globUnescape(pattern) + } + + const flags = options.nocase ? 'i' : '' + try { + return Object.assign(new RegExp('^' + re + '$', flags), { + _glob: pattern, + _src: re, + }) + } catch (er) /* istanbul ignore next - should be impossible */ { + // If it was an invalid regular expression, then it can't match + // anything. This trick looks for a character after the end of + // the string, which is of course impossible, except in multi-line + // mode, but it's not a /m regex. + return new RegExp('$.') + } + } + + makeRe() { + if (this.regexp || this.regexp === false) return this.regexp + + // at this point, this.set is a 2d array of partial + // pattern strings, or "**". + // + // It's better to use .match(). This function shouldn't + // be used, really, but it's pretty convenient sometimes, + // when you just want to work with a regex. + const set = this.set + + if (!set.length) { + this.regexp = false + return this.regexp + } + const options = this.options + + const twoStar = options.noglobstar ? star + : options.dot ? twoStarDot + : twoStarNoDot + const flags = options.nocase ? 'i' : '' + + // coalesce globstars and regexpify non-globstar patterns + // if it's the only item, then we just do one twoStar + // if it's the first, and there are more, prepend (\/|twoStar\/)? to next + // if it's the last, append (\/twoStar|) to previous + // if it's in the middle, append (\/|\/twoStar\/) to previous + // then filter out GLOBSTAR symbols + let re = set.map(pattern => { + pattern = pattern.map(p => + typeof p === 'string' ? regExpEscape(p) + : p === GLOBSTAR ? GLOBSTAR + : p._src + ).reduce((set, p) => { + if (!(set[set.length - 1] === GLOBSTAR && p === GLOBSTAR)) { + set.push(p) + } + return set + }, []) + pattern.forEach((p, i) => { + if (p !== GLOBSTAR || pattern[i - 1] === GLOBSTAR) { + return + } + if (i === 0) { + if (pattern.length > 1) { + pattern[i + 1] = '(?:\\\/|' + twoStar + '\\\/)?' + pattern[i + 1] + } else { + pattern[i] = twoStar + } + } else if (i === pattern.length - 1) { + pattern[i - 1] += '(?:\\\/|' + twoStar + ')?' + } else { + pattern[i - 1] += '(?:\\\/|\\\/' + twoStar + '\\\/)' + pattern[i + 1] + pattern[i + 1] = GLOBSTAR + } + }) + return pattern.filter(p => p !== GLOBSTAR).join('/') + }).join('|') + + // must match entire pattern + // ending in a * or ** will make it less strict. + re = '^(?:' + re + ')$' + + // can match anything, as long as it's not this. + if (this.negate) re = '^(?!' + re + ').*$' + + try { + this.regexp = new RegExp(re, flags) + } catch (ex) /* istanbul ignore next - should be impossible */ { + this.regexp = false + } + return this.regexp + } + + match(f, partial = this.partial) { + this.debug('match', f, this.pattern) + // short-circuit in the case of busted things. + // comments, etc. + if (this.comment) return false + if (this.empty) return f === '' + + if (f === '/' && partial) return true + + const options = this.options + + // windows: need to use /, not \ + if (path.sep !== '/') { + f = f.split(path.sep).join('/') + } + + // treat the test path as a set of pathparts. + f = f.split(slashSplit) + this.debug(this.pattern, 'split', f) + + // just ONE of the pattern sets in this.set needs to match + // in order for it to be valid. If negating, then just one + // match means that we have failed. + // Either way, return on the first hit. + + const set = this.set + this.debug(this.pattern, 'set', set) + + // Find the basename of the path by looking for the last non-empty segment + let filename + for (let i = f.length - 1; i >= 0; i--) { + filename = f[i] + if (filename) break + } + + for (let i = 0; i < set.length; i++) { + const pattern = set[i] + let file = f + if (options.matchBase && pattern.length === 1) { + file = [filename] + } + const hit = this.matchOne(file, pattern, partial) + if (hit) { + if (options.flipNegate) return true + return !this.negate + } + } + + // didn't get any hits. this is success if it's a negative + // pattern, failure otherwise. + if (options.flipNegate) return false + return this.negate + } + + static defaults(def) { + return minimatch.defaults(def).Minimatch + } +} + +minimatch.Minimatch = Minimatch \ No newline at end of file diff --git a/server/libs/archiver/archiverUtils/readableStream/LICENSE b/server/libs/archiver/archiverUtils/readableStream/LICENSE new file mode 100644 index 000000000..5fcbe0192 --- /dev/null +++ b/server/libs/archiver/archiverUtils/readableStream/LICENSE @@ -0,0 +1,47 @@ +Node.js is licensed for use as follows: + +""" +Copyright Node.js contributors. All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to +deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +sell copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +IN THE SOFTWARE. +""" + +This license applies to parts of Node.js originating from the +https://github.com/joyent/node repository: + +""" +Copyright Joyent, Inc. and other Node contributors. All rights reserved. +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to +deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +sell copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +IN THE SOFTWARE. +""" \ No newline at end of file diff --git a/server/libs/archiver/archiverUtils/readableStream/_stream_duplex.js b/server/libs/archiver/archiverUtils/readableStream/_stream_duplex.js new file mode 100644 index 000000000..105eebbd1 --- /dev/null +++ b/server/libs/archiver/archiverUtils/readableStream/_stream_duplex.js @@ -0,0 +1,3 @@ +'use strict' // Keep this file as an alias for the full stream module. + +module.exports = require('./stream').Duplex diff --git a/server/libs/archiver/archiverUtils/readableStream/_stream_passthrough.js b/server/libs/archiver/archiverUtils/readableStream/_stream_passthrough.js new file mode 100644 index 000000000..31358e6d1 --- /dev/null +++ b/server/libs/archiver/archiverUtils/readableStream/_stream_passthrough.js @@ -0,0 +1,3 @@ +'use strict' // Keep this file as an alias for the full stream module. + +module.exports = require('./stream').PassThrough diff --git a/server/libs/archiver/archiverUtils/readableStream/_stream_readable.js b/server/libs/archiver/archiverUtils/readableStream/_stream_readable.js new file mode 100644 index 000000000..abd53db4c --- /dev/null +++ b/server/libs/archiver/archiverUtils/readableStream/_stream_readable.js @@ -0,0 +1,3 @@ +'use strict' // Keep this file as an alias for the full stream module. + +module.exports = require('./stream').Readable diff --git a/server/libs/archiver/archiverUtils/readableStream/_stream_transform.js b/server/libs/archiver/archiverUtils/readableStream/_stream_transform.js new file mode 100644 index 000000000..98ea33824 --- /dev/null +++ b/server/libs/archiver/archiverUtils/readableStream/_stream_transform.js @@ -0,0 +1,3 @@ +'use strict' // Keep this file as an alias for the full stream module. + +module.exports = require('./stream').Transform diff --git a/server/libs/archiver/archiverUtils/readableStream/_stream_writable.js b/server/libs/archiver/archiverUtils/readableStream/_stream_writable.js new file mode 100644 index 000000000..07204c429 --- /dev/null +++ b/server/libs/archiver/archiverUtils/readableStream/_stream_writable.js @@ -0,0 +1,3 @@ +'use strict' // Keep this file as an alias for the full stream module. + +module.exports = require('./stream').Writable diff --git a/server/libs/archiver/archiverUtils/readableStream/index.js b/server/libs/archiver/archiverUtils/readableStream/index.js new file mode 100644 index 000000000..ddef82d40 --- /dev/null +++ b/server/libs/archiver/archiverUtils/readableStream/index.js @@ -0,0 +1,67 @@ +'use strict' + +const Stream = require('stream') + +if (Stream && process.env.READABLE_STREAM === 'disable') { + const promises = Stream.promises // Explicit export naming is needed for ESM + + module.exports._uint8ArrayToBuffer = Stream._uint8ArrayToBuffer + module.exports._isUint8Array = Stream._isUint8Array + module.exports.isDisturbed = Stream.isDisturbed + module.exports.isErrored = Stream.isErrored + module.exports.isReadable = Stream.isReadable + module.exports.Readable = Stream.Readable + module.exports.Writable = Stream.Writable + module.exports.Duplex = Stream.Duplex + module.exports.Transform = Stream.Transform + module.exports.PassThrough = Stream.PassThrough + module.exports.addAbortSignal = Stream.addAbortSignal + module.exports.finished = Stream.finished + module.exports.destroy = Stream.destroy + module.exports.pipeline = Stream.pipeline + module.exports.compose = Stream.compose + Object.defineProperty(Stream, 'promises', { + configurable: true, + enumerable: true, + + get() { + return promises + } + }) + module.exports.Stream = Stream.Stream +} else { + const CustomStream = require('./stream') + + const promises = require('./stream/promises') + + const originalDestroy = CustomStream.Readable.destroy + module.exports = CustomStream.Readable // Explicit export naming is needed for ESM + + module.exports._uint8ArrayToBuffer = CustomStream._uint8ArrayToBuffer + module.exports._isUint8Array = CustomStream._isUint8Array + module.exports.isDisturbed = CustomStream.isDisturbed + module.exports.isErrored = CustomStream.isErrored + module.exports.isReadable = CustomStream.isReadable + module.exports.Readable = CustomStream.Readable + module.exports.Writable = CustomStream.Writable + module.exports.Duplex = CustomStream.Duplex + module.exports.Transform = CustomStream.Transform + module.exports.PassThrough = CustomStream.PassThrough + module.exports.addAbortSignal = CustomStream.addAbortSignal + module.exports.finished = CustomStream.finished + module.exports.destroy = CustomStream.destroy + module.exports.destroy = originalDestroy + module.exports.pipeline = CustomStream.pipeline + module.exports.compose = CustomStream.compose + Object.defineProperty(CustomStream, 'promises', { + configurable: true, + enumerable: true, + + get() { + return promises + } + }) + module.exports.Stream = CustomStream.Stream +} // Allow default importing + +module.exports.default = module.exports diff --git a/server/libs/archiver/archiverUtils/readableStream/internal/streams/add-abort-signal.js b/server/libs/archiver/archiverUtils/readableStream/internal/streams/add-abort-signal.js new file mode 100644 index 000000000..8d5a840f7 --- /dev/null +++ b/server/libs/archiver/archiverUtils/readableStream/internal/streams/add-abort-signal.js @@ -0,0 +1,52 @@ +'use strict' + +const { AbortError, codes } = require('../../ours/errors') + +const eos = require('./end-of-stream') + +const { ERR_INVALID_ARG_TYPE } = codes // This method is inlined here for readable-stream +// It also does not allow for signal to not exist on the stream +// https://github.com/nodejs/node/pull/36061#discussion_r533718029 + +const validateAbortSignal = (signal, name) => { + if (typeof signal !== 'object' || !('aborted' in signal)) { + throw new ERR_INVALID_ARG_TYPE(name, 'AbortSignal', signal) + } +} + +function isNodeStream(obj) { + return !!(obj && typeof obj.pipe === 'function') +} + +module.exports.addAbortSignal = function addAbortSignal(signal, stream) { + validateAbortSignal(signal, 'signal') + + if (!isNodeStream(stream)) { + throw new ERR_INVALID_ARG_TYPE('stream', 'stream.Stream', stream) + } + + return module.exports.addAbortSignalNoValidate(signal, stream) +} + +module.exports.addAbortSignalNoValidate = function (signal, stream) { + if (typeof signal !== 'object' || !('aborted' in signal)) { + return stream + } + + const onAbort = () => { + stream.destroy( + new AbortError(undefined, { + cause: signal.reason + }) + ) + } + + if (signal.aborted) { + onAbort() + } else { + signal.addEventListener('abort', onAbort) + eos(stream, () => signal.removeEventListener('abort', onAbort)) + } + + return stream +} diff --git a/server/libs/archiver/archiverUtils/readableStream/internal/streams/buffer_list.js b/server/libs/archiver/archiverUtils/readableStream/internal/streams/buffer_list.js new file mode 100644 index 000000000..6a37442ba --- /dev/null +++ b/server/libs/archiver/archiverUtils/readableStream/internal/streams/buffer_list.js @@ -0,0 +1,178 @@ +'use strict' + +const { StringPrototypeSlice, SymbolIterator, TypedArrayPrototypeSet, Uint8Array } = require('../../ours/primordials') + +const { inspect } = require('../../ours/util') + +module.exports = class BufferList { + constructor() { + this.head = null + this.tail = null + this.length = 0 + } + + push(v) { + const entry = { + data: v, + next: null + } + if (this.length > 0) this.tail.next = entry + else this.head = entry + this.tail = entry + ++this.length + } + + unshift(v) { + const entry = { + data: v, + next: this.head + } + if (this.length === 0) this.tail = entry + this.head = entry + ++this.length + } + + shift() { + if (this.length === 0) return + const ret = this.head.data + if (this.length === 1) this.head = this.tail = null + else this.head = this.head.next + --this.length + return ret + } + + clear() { + this.head = this.tail = null + this.length = 0 + } + + join(s) { + if (this.length === 0) return '' + let p = this.head + let ret = '' + p.data + + while ((p = p.next) !== null) ret += s + p.data + + return ret + } + + concat(n) { + if (this.length === 0) return Buffer.alloc(0) + const ret = Buffer.allocUnsafe(n >>> 0) + let p = this.head + let i = 0 + + while (p) { + TypedArrayPrototypeSet(ret, p.data, i) + i += p.data.length + p = p.next + } + + return ret + } // Consumes a specified amount of bytes or characters from the buffered data. + + consume(n, hasStrings) { + const data = this.head.data + + if (n < data.length) { + // `slice` is the same for buffers and strings. + const slice = data.slice(0, n) + this.head.data = data.slice(n) + return slice + } + + if (n === data.length) { + // First chunk is a perfect match. + return this.shift() + } // Result spans more than one buffer. + + return hasStrings ? this._getString(n) : this._getBuffer(n) + } + + first() { + return this.head.data + } + + *[SymbolIterator]() { + for (let p = this.head; p; p = p.next) { + yield p.data + } + } // Consumes a specified amount of characters from the buffered data. + + _getString(n) { + let ret = '' + let p = this.head + let c = 0 + + do { + const str = p.data + + if (n > str.length) { + ret += str + n -= str.length + } else { + if (n === str.length) { + ret += str + ++c + if (p.next) this.head = p.next + else this.head = this.tail = null + } else { + ret += StringPrototypeSlice(str, 0, n) + this.head = p + p.data = StringPrototypeSlice(str, n) + } + + break + } + + ++c + } while ((p = p.next) !== null) + + this.length -= c + return ret + } // Consumes a specified amount of bytes from the buffered data. + + _getBuffer(n) { + const ret = Buffer.allocUnsafe(n) + const retLen = n + let p = this.head + let c = 0 + + do { + const buf = p.data + + if (n > buf.length) { + TypedArrayPrototypeSet(ret, buf, retLen - n) + n -= buf.length + } else { + if (n === buf.length) { + TypedArrayPrototypeSet(ret, buf, retLen - n) + ++c + if (p.next) this.head = p.next + else this.head = this.tail = null + } else { + TypedArrayPrototypeSet(ret, new Uint8Array(buf.buffer, buf.byteOffset, n), retLen - n) + this.head = p + p.data = buf.slice(n) + } + + break + } + + ++c + } while ((p = p.next) !== null) + + this.length -= c + return ret + } // Make sure the linked list only shows the minimal necessary information. + + [Symbol.for('nodejs.util.inspect.custom')](_, options) { + return inspect(this, { + ...options, + // Only inspect one level. + depth: 0, + // It should not recurse. + customInspect: false + }) + } +} diff --git a/server/libs/archiver/archiverUtils/readableStream/internal/streams/compose.js b/server/libs/archiver/archiverUtils/readableStream/internal/streams/compose.js new file mode 100644 index 000000000..0a2e810a3 --- /dev/null +++ b/server/libs/archiver/archiverUtils/readableStream/internal/streams/compose.js @@ -0,0 +1,161 @@ +'use strict' + +const { pipeline } = require('./pipeline') + +const Duplex = require('./duplex') + +const { destroyer } = require('./destroy') + +const { isNodeStream, isReadable, isWritable } = require('./utils') + +const { + AbortError, + codes: { ERR_INVALID_ARG_VALUE, ERR_MISSING_ARGS } +} = require('../../ours/errors') + +module.exports = function compose(...streams) { + if (streams.length === 0) { + throw new ERR_MISSING_ARGS('streams') + } + + if (streams.length === 1) { + return Duplex.from(streams[0]) + } + + const orgStreams = [...streams] + + if (typeof streams[0] === 'function') { + streams[0] = Duplex.from(streams[0]) + } + + if (typeof streams[streams.length - 1] === 'function') { + const idx = streams.length - 1 + streams[idx] = Duplex.from(streams[idx]) + } + + for (let n = 0; n < streams.length; ++n) { + if (!isNodeStream(streams[n])) { + // TODO(ronag): Add checks for non streams. + continue + } + + if (n < streams.length - 1 && !isReadable(streams[n])) { + throw new ERR_INVALID_ARG_VALUE(`streams[${n}]`, orgStreams[n], 'must be readable') + } + + if (n > 0 && !isWritable(streams[n])) { + throw new ERR_INVALID_ARG_VALUE(`streams[${n}]`, orgStreams[n], 'must be writable') + } + } + + let ondrain + let onfinish + let onreadable + let onclose + let d + + function onfinished(err) { + const cb = onclose + onclose = null + + if (cb) { + cb(err) + } else if (err) { + d.destroy(err) + } else if (!readable && !writable) { + d.destroy() + } + } + + const head = streams[0] + const tail = pipeline(streams, onfinished) + const writable = !!isWritable(head) + const readable = !!isReadable(tail) // TODO(ronag): Avoid double buffering. + // Implement Writable/Readable/Duplex traits. + // See, https://github.com/nodejs/node/pull/33515. + + d = new Duplex({ + // TODO (ronag): highWaterMark? + writableObjectMode: !!(head !== null && head !== undefined && head.writableObjectMode), + readableObjectMode: !!(tail !== null && tail !== undefined && tail.writableObjectMode), + writable, + readable + }) + + if (writable) { + d._write = function (chunk, encoding, callback) { + if (head.write(chunk, encoding)) { + callback() + } else { + ondrain = callback + } + } + + d._final = function (callback) { + head.end() + onfinish = callback + } + + head.on('drain', function () { + if (ondrain) { + const cb = ondrain + ondrain = null + cb() + } + }) + tail.on('finish', function () { + if (onfinish) { + const cb = onfinish + onfinish = null + cb() + } + }) + } + + if (readable) { + tail.on('readable', function () { + if (onreadable) { + const cb = onreadable + onreadable = null + cb() + } + }) + tail.on('end', function () { + d.push(null) + }) + + d._read = function () { + while (true) { + const buf = tail.read() + + if (buf === null) { + onreadable = d._read + return + } + + if (!d.push(buf)) { + return + } + } + } + } + + d._destroy = function (err, callback) { + if (!err && onclose !== null) { + err = new AbortError() + } + + onreadable = null + ondrain = null + onfinish = null + + if (onclose === null) { + callback(err) + } else { + onclose = callback + destroyer(tail, err) + } + } + + return d +} diff --git a/server/libs/archiver/archiverUtils/readableStream/internal/streams/destroy.js b/server/libs/archiver/archiverUtils/readableStream/internal/streams/destroy.js new file mode 100644 index 000000000..7eeda1361 --- /dev/null +++ b/server/libs/archiver/archiverUtils/readableStream/internal/streams/destroy.js @@ -0,0 +1,332 @@ +'use strict' + +const { + aggregateTwoErrors, + codes: { ERR_MULTIPLE_CALLBACK }, + AbortError +} = require('../../ours/errors') + +const { Symbol } = require('../../ours/primordials') + +const { kDestroyed, isDestroyed, isFinished, isServerRequest } = require('./utils') + +const kDestroy = Symbol('kDestroy') +const kConstruct = Symbol('kConstruct') + +function checkError(err, w, r) { + if (err) { + // Avoid V8 leak, https://github.com/nodejs/node/pull/34103#issuecomment-652002364 + err.stack // eslint-disable-line no-unused-expressions + + if (w && !w.errored) { + w.errored = err + } + + if (r && !r.errored) { + r.errored = err + } + } +} // Backwards compat. cb() is undocumented and unused in core but +// unfortunately might be used by modules. + +function destroy(err, cb) { + const r = this._readableState + const w = this._writableState // With duplex streams we use the writable side for state. + + const s = w || r + + if ((w && w.destroyed) || (r && r.destroyed)) { + if (typeof cb === 'function') { + cb() + } + + return this + } // We set destroyed to true before firing error callbacks in order + // to make it re-entrance safe in case destroy() is called within callbacks + + checkError(err, w, r) + + if (w) { + w.destroyed = true + } + + if (r) { + r.destroyed = true + } // If still constructing then defer calling _destroy. + + if (!s.constructed) { + this.once(kDestroy, function (er) { + _destroy(this, aggregateTwoErrors(er, err), cb) + }) + } else { + _destroy(this, err, cb) + } + + return this +} + +function _destroy(self, err, cb) { + let called = false + + function onDestroy(err) { + if (called) { + return + } + + called = true + const r = self._readableState + const w = self._writableState + checkError(err, w, r) + + if (w) { + w.closed = true + } + + if (r) { + r.closed = true + } + + if (typeof cb === 'function') { + cb(err) + } + + if (err) { + process.nextTick(emitErrorCloseNT, self, err) + } else { + process.nextTick(emitCloseNT, self) + } + } + + try { + self._destroy(err || null, onDestroy) + } catch (err) { + onDestroy(err) + } +} + +function emitErrorCloseNT(self, err) { + emitErrorNT(self, err) + emitCloseNT(self) +} + +function emitCloseNT(self) { + const r = self._readableState + const w = self._writableState + + if (w) { + w.closeEmitted = true + } + + if (r) { + r.closeEmitted = true + } + + if ((w && w.emitClose) || (r && r.emitClose)) { + self.emit('close') + } +} + +function emitErrorNT(self, err) { + const r = self._readableState + const w = self._writableState + + if ((w && w.errorEmitted) || (r && r.errorEmitted)) { + return + } + + if (w) { + w.errorEmitted = true + } + + if (r) { + r.errorEmitted = true + } + + self.emit('error', err) +} + +function undestroy() { + const r = this._readableState + const w = this._writableState + + if (r) { + r.constructed = true + r.closed = false + r.closeEmitted = false + r.destroyed = false + r.errored = null + r.errorEmitted = false + r.reading = false + r.ended = r.readable === false + r.endEmitted = r.readable === false + } + + if (w) { + w.constructed = true + w.destroyed = false + w.closed = false + w.closeEmitted = false + w.errored = null + w.errorEmitted = false + w.finalCalled = false + w.prefinished = false + w.ended = w.writable === false + w.ending = w.writable === false + w.finished = w.writable === false + } +} + +function errorOrDestroy(stream, err, sync) { + // We have tests that rely on errors being emitted + // in the same tick, so changing this is semver major. + // For now when you opt-in to autoDestroy we allow + // the error to be emitted nextTick. In a future + // semver major update we should change the default to this. + const r = stream._readableState + const w = stream._writableState + + if ((w && w.destroyed) || (r && r.destroyed)) { + return this + } + + if ((r && r.autoDestroy) || (w && w.autoDestroy)) stream.destroy(err) + else if (err) { + // Avoid V8 leak, https://github.com/nodejs/node/pull/34103#issuecomment-652002364 + err.stack // eslint-disable-line no-unused-expressions + + if (w && !w.errored) { + w.errored = err + } + + if (r && !r.errored) { + r.errored = err + } + + if (sync) { + process.nextTick(emitErrorNT, stream, err) + } else { + emitErrorNT(stream, err) + } + } +} + +function construct(stream, cb) { + if (typeof stream._construct !== 'function') { + return + } + + const r = stream._readableState + const w = stream._writableState + + if (r) { + r.constructed = false + } + + if (w) { + w.constructed = false + } + + stream.once(kConstruct, cb) + + if (stream.listenerCount(kConstruct) > 1) { + // Duplex + return + } + + process.nextTick(constructNT, stream) +} + +function constructNT(stream) { + let called = false + + function onConstruct(err) { + if (called) { + errorOrDestroy(stream, err !== null && err !== undefined ? err : new ERR_MULTIPLE_CALLBACK()) + return + } + + called = true + const r = stream._readableState + const w = stream._writableState + const s = w || r + + if (r) { + r.constructed = true + } + + if (w) { + w.constructed = true + } + + if (s.destroyed) { + stream.emit(kDestroy, err) + } else if (err) { + errorOrDestroy(stream, err, true) + } else { + process.nextTick(emitConstructNT, stream) + } + } + + try { + stream._construct(onConstruct) + } catch (err) { + onConstruct(err) + } +} + +function emitConstructNT(stream) { + stream.emit(kConstruct) +} + +function isRequest(stream) { + return stream && stream.setHeader && typeof stream.abort === 'function' +} + +function emitCloseLegacy(stream) { + stream.emit('close') +} + +function emitErrorCloseLegacy(stream, err) { + stream.emit('error', err) + process.nextTick(emitCloseLegacy, stream) +} // Normalize destroy for legacy. + +function destroyer(stream, err) { + if (!stream || isDestroyed(stream)) { + return + } + + if (!err && !isFinished(stream)) { + err = new AbortError() + } // TODO: Remove isRequest branches. + + if (isServerRequest(stream)) { + stream.socket = null + stream.destroy(err) + } else if (isRequest(stream)) { + stream.abort() + } else if (isRequest(stream.req)) { + stream.req.abort() + } else if (typeof stream.destroy === 'function') { + stream.destroy(err) + } else if (typeof stream.close === 'function') { + // TODO: Don't lose err? + stream.close() + } else if (err) { + process.nextTick(emitErrorCloseLegacy, stream) + } else { + process.nextTick(emitCloseLegacy, stream) + } + + if (!stream.destroyed) { + stream[kDestroyed] = true + } +} + +module.exports = { + construct, + destroyer, + destroy, + undestroy, + errorOrDestroy +} diff --git a/server/libs/archiver/archiverUtils/readableStream/internal/streams/duplex.js b/server/libs/archiver/archiverUtils/readableStream/internal/streams/duplex.js new file mode 100644 index 000000000..a0d6f6bd7 --- /dev/null +++ b/server/libs/archiver/archiverUtils/readableStream/internal/streams/duplex.js @@ -0,0 +1,128 @@ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. +// a duplex stream is just a stream that is both readable and writable. +// Since JS doesn't have multiple prototype inheritance, this class +// prototypically inherits from Readable, and then parasitically from +// Writable. +'use strict' + +const { + ObjectDefineProperties, + ObjectGetOwnPropertyDescriptor, + ObjectKeys, + ObjectSetPrototypeOf +} = require('../../ours/primordials') + +module.exports = Duplex + +const Readable = require('./readable') + +const Writable = require('./writable') + +ObjectSetPrototypeOf(Duplex.prototype, Readable.prototype) +ObjectSetPrototypeOf(Duplex, Readable) +{ + const keys = ObjectKeys(Writable.prototype) // Allow the keys array to be GC'ed. + + for (let i = 0; i < keys.length; i++) { + const method = keys[i] + if (!Duplex.prototype[method]) Duplex.prototype[method] = Writable.prototype[method] + } +} + +function Duplex(options) { + if (!(this instanceof Duplex)) return new Duplex(options) + Readable.call(this, options) + Writable.call(this, options) + + if (options) { + this.allowHalfOpen = options.allowHalfOpen !== false + + if (options.readable === false) { + this._readableState.readable = false + this._readableState.ended = true + this._readableState.endEmitted = true + } + + if (options.writable === false) { + this._writableState.writable = false + this._writableState.ending = true + this._writableState.ended = true + this._writableState.finished = true + } + } else { + this.allowHalfOpen = true + } +} + +ObjectDefineProperties(Duplex.prototype, { + writable: ObjectGetOwnPropertyDescriptor(Writable.prototype, 'writable'), + writableHighWaterMark: ObjectGetOwnPropertyDescriptor(Writable.prototype, 'writableHighWaterMark'), + writableObjectMode: ObjectGetOwnPropertyDescriptor(Writable.prototype, 'writableObjectMode'), + writableBuffer: ObjectGetOwnPropertyDescriptor(Writable.prototype, 'writableBuffer'), + writableLength: ObjectGetOwnPropertyDescriptor(Writable.prototype, 'writableLength'), + writableFinished: ObjectGetOwnPropertyDescriptor(Writable.prototype, 'writableFinished'), + writableCorked: ObjectGetOwnPropertyDescriptor(Writable.prototype, 'writableCorked'), + writableEnded: ObjectGetOwnPropertyDescriptor(Writable.prototype, 'writableEnded'), + writableNeedDrain: ObjectGetOwnPropertyDescriptor(Writable.prototype, 'writableNeedDrain'), + destroyed: { + get() { + if (this._readableState === undefined || this._writableState === undefined) { + return false + } + + return this._readableState.destroyed && this._writableState.destroyed + }, + + set(value) { + // Backward compatibility, the user is explicitly + // managing destroyed. + if (this._readableState && this._writableState) { + this._readableState.destroyed = value + this._writableState.destroyed = value + } + } + } +}) +let webStreamsAdapters // Lazy to avoid circular references + +function lazyWebStreams() { + if (webStreamsAdapters === undefined) webStreamsAdapters = {} + return webStreamsAdapters +} + +Duplex.fromWeb = function (pair, options) { + return lazyWebStreams().newStreamDuplexFromReadableWritablePair(pair, options) +} + +Duplex.toWeb = function (duplex) { + return lazyWebStreams().newReadableWritablePairFromDuplex(duplex) +} + +let duplexify + +Duplex.from = function (body) { + if (!duplexify) { + duplexify = require('./duplexify') + } + + return duplexify(body, 'body') +} diff --git a/server/libs/archiver/archiverUtils/readableStream/internal/streams/duplexify.js b/server/libs/archiver/archiverUtils/readableStream/internal/streams/duplexify.js new file mode 100644 index 000000000..3a11dfebc --- /dev/null +++ b/server/libs/archiver/archiverUtils/readableStream/internal/streams/duplexify.js @@ -0,0 +1,422 @@ +'use strict' + +const abortControllerModule = require('../../../../../watcher/aborter/controller') + +const bufferModule = require('buffer') + +const { + isReadable, + isWritable, + isIterable, + isNodeStream, + isReadableNodeStream, + isWritableNodeStream, + isDuplexNodeStream +} = require('./utils') + +const eos = require('./end-of-stream') + +const { + AbortError, + codes: { ERR_INVALID_ARG_TYPE, ERR_INVALID_RETURN_VALUE } +} = require('../../ours/errors') + +const { destroyer } = require('./destroy') + +const Duplex = require('./duplex') + +const Readable = require('./readable') + +const { createDeferredPromise } = require('../../ours/util') + +const from = require('./from') + +const Blob = globalThis.Blob || bufferModule.Blob +const isBlob = + typeof Blob !== 'undefined' + ? function isBlob(b) { + return b instanceof Blob + } + : function isBlob(b) { + return false + } +const AbortController = globalThis.AbortController || abortControllerModule.AbortController + +const { FunctionPrototypeCall } = require('../../ours/primordials') // This is needed for pre node 17. + +class Duplexify extends Duplex { + constructor(options) { + super(options) // https://github.com/nodejs/node/pull/34385 + + if ((options === null || options === undefined ? undefined : options.readable) === false) { + this._readableState.readable = false + this._readableState.ended = true + this._readableState.endEmitted = true + } + + if ((options === null || options === undefined ? undefined : options.writable) === false) { + this._writableState.writable = false + this._writableState.ending = true + this._writableState.ended = true + this._writableState.finished = true + } + } +} + +module.exports = function duplexify(body, name) { + if (isDuplexNodeStream(body)) { + return body + } + + if (isReadableNodeStream(body)) { + return _duplexify({ + readable: body + }) + } + + if (isWritableNodeStream(body)) { + return _duplexify({ + writable: body + }) + } + + if (isNodeStream(body)) { + return _duplexify({ + writable: false, + readable: false + }) + } // TODO: Webstreams + // if (isReadableStream(body)) { + // return _duplexify({ readable: Readable.fromWeb(body) }); + // } + // TODO: Webstreams + // if (isWritableStream(body)) { + // return _duplexify({ writable: Writable.fromWeb(body) }); + // } + + if (typeof body === 'function') { + const { value, write, final, destroy } = fromAsyncGen(body) + + if (isIterable(value)) { + return from(Duplexify, value, { + // TODO (ronag): highWaterMark? + objectMode: true, + write, + final, + destroy + }) + } + + const then = value === null || value === undefined ? undefined : value.then + + if (typeof then === 'function') { + let d + const promise = FunctionPrototypeCall( + then, + value, + (val) => { + if (val != null) { + throw new ERR_INVALID_RETURN_VALUE('nully', 'body', val) + } + }, + (err) => { + destroyer(d, err) + } + ) + return (d = new Duplexify({ + // TODO (ronag): highWaterMark? + objectMode: true, + readable: false, + write, + + final(cb) { + final(async () => { + try { + await promise + process.nextTick(cb, null) + } catch (err) { + process.nextTick(cb, err) + } + }) + }, + + destroy + })) + } + + throw new ERR_INVALID_RETURN_VALUE('Iterable, AsyncIterable or AsyncFunction', name, value) + } + + if (isBlob(body)) { + return duplexify(body.arrayBuffer()) + } + + if (isIterable(body)) { + return from(Duplexify, body, { + // TODO (ronag): highWaterMark? + objectMode: true, + writable: false + }) + } // TODO: Webstreams. + // if ( + // isReadableStream(body?.readable) && + // isWritableStream(body?.writable) + // ) { + // return Duplexify.fromWeb(body); + // } + + if ( + typeof (body === null || body === undefined ? undefined : body.writable) === 'object' || + typeof (body === null || body === undefined ? undefined : body.readable) === 'object' + ) { + const readable = + body !== null && body !== undefined && body.readable + ? isReadableNodeStream(body === null || body === undefined ? undefined : body.readable) + ? body === null || body === undefined + ? undefined + : body.readable + : duplexify(body.readable) + : undefined + const writable = + body !== null && body !== undefined && body.writable + ? isWritableNodeStream(body === null || body === undefined ? undefined : body.writable) + ? body === null || body === undefined + ? undefined + : body.writable + : duplexify(body.writable) + : undefined + return _duplexify({ + readable, + writable + }) + } + + const then = body === null || body === undefined ? undefined : body.then + + if (typeof then === 'function') { + let d + FunctionPrototypeCall( + then, + body, + (val) => { + if (val != null) { + d.push(val) + } + + d.push(null) + }, + (err) => { + destroyer(d, err) + } + ) + return (d = new Duplexify({ + objectMode: true, + writable: false, + + read() { } + })) + } + + throw new ERR_INVALID_ARG_TYPE( + name, + [ + 'Blob', + 'ReadableStream', + 'WritableStream', + 'Stream', + 'Iterable', + 'AsyncIterable', + 'Function', + '{ readable, writable } pair', + 'Promise' + ], + body + ) +} + +function fromAsyncGen(fn) { + let { promise, resolve } = createDeferredPromise() + const ac = new AbortController() + const signal = ac.signal + const value = fn( + (async function* () { + while (true) { + const _promise = promise + promise = null + const { chunk, done, cb } = await _promise + process.nextTick(cb) + if (done) return + if (signal.aborted) + throw new AbortError(undefined, { + cause: signal.reason + }) + ; ({ promise, resolve } = createDeferredPromise()) + yield chunk + } + })(), + { + signal + } + ) + return { + value, + + write(chunk, encoding, cb) { + const _resolve = resolve + resolve = null + + _resolve({ + chunk, + done: false, + cb + }) + }, + + final(cb) { + const _resolve = resolve + resolve = null + + _resolve({ + done: true, + cb + }) + }, + + destroy(err, cb) { + ac.abort() + cb(err) + } + } +} + +function _duplexify(pair) { + const r = pair.readable && typeof pair.readable.read !== 'function' ? Readable.wrap(pair.readable) : pair.readable + const w = pair.writable + let readable = !!isReadable(r) + let writable = !!isWritable(w) + let ondrain + let onfinish + let onreadable + let onclose + let d + + function onfinished(err) { + const cb = onclose + onclose = null + + if (cb) { + cb(err) + } else if (err) { + d.destroy(err) + } else if (!readable && !writable) { + d.destroy() + } + } // TODO(ronag): Avoid double buffering. + // Implement Writable/Readable/Duplex traits. + // See, https://github.com/nodejs/node/pull/33515. + + d = new Duplexify({ + // TODO (ronag): highWaterMark? + readableObjectMode: !!(r !== null && r !== undefined && r.readableObjectMode), + writableObjectMode: !!(w !== null && w !== undefined && w.writableObjectMode), + readable, + writable + }) + + if (writable) { + eos(w, (err) => { + writable = false + + if (err) { + destroyer(r, err) + } + + onfinished(err) + }) + + d._write = function (chunk, encoding, callback) { + if (w.write(chunk, encoding)) { + callback() + } else { + ondrain = callback + } + } + + d._final = function (callback) { + w.end() + onfinish = callback + } + + w.on('drain', function () { + if (ondrain) { + const cb = ondrain + ondrain = null + cb() + } + }) + w.on('finish', function () { + if (onfinish) { + const cb = onfinish + onfinish = null + cb() + } + }) + } + + if (readable) { + eos(r, (err) => { + readable = false + + if (err) { + destroyer(r, err) + } + + onfinished(err) + }) + r.on('readable', function () { + if (onreadable) { + const cb = onreadable + onreadable = null + cb() + } + }) + r.on('end', function () { + d.push(null) + }) + + d._read = function () { + while (true) { + const buf = r.read() + + if (buf === null) { + onreadable = d._read + return + } + + if (!d.push(buf)) { + return + } + } + } + } + + d._destroy = function (err, callback) { + if (!err && onclose !== null) { + err = new AbortError() + } + + onreadable = null + ondrain = null + onfinish = null + + if (onclose === null) { + callback(err) + } else { + onclose = callback + destroyer(w, err) + destroyer(r, err) + } + } + + return d +} diff --git a/server/libs/archiver/archiverUtils/readableStream/internal/streams/end-of-stream.js b/server/libs/archiver/archiverUtils/readableStream/internal/streams/end-of-stream.js new file mode 100644 index 000000000..3bafd53b4 --- /dev/null +++ b/server/libs/archiver/archiverUtils/readableStream/internal/streams/end-of-stream.js @@ -0,0 +1,258 @@ +// Ported from https://github.com/mafintosh/end-of-stream with +// permission from the author, Mathias Buus (@mafintosh). +'use strict' + +const { AbortError, codes } = require('../../ours/errors') + +const { ERR_INVALID_ARG_TYPE, ERR_STREAM_PREMATURE_CLOSE } = codes + +const { once } = require('../../ours/util') + +const { validateAbortSignal, validateFunction, validateObject } = require('../validators') + +const { Promise } = require('../../ours/primordials') + +const { + isClosed, + isReadable, + isReadableNodeStream, + isReadableFinished, + isReadableErrored, + isWritable, + isWritableNodeStream, + isWritableFinished, + isWritableErrored, + isNodeStream, + willEmitClose: _willEmitClose +} = require('./utils') + +function isRequest(stream) { + return stream.setHeader && typeof stream.abort === 'function' +} + +const nop = () => {} + +function eos(stream, options, callback) { + var _options$readable, _options$writable + + if (arguments.length === 2) { + callback = options + options = {} + } else if (options == null) { + options = {} + } else { + validateObject(options, 'options') + } + + validateFunction(callback, 'callback') + validateAbortSignal(options.signal, 'options.signal') + callback = once(callback) + const readable = + (_options$readable = options.readable) !== null && _options$readable !== undefined + ? _options$readable + : isReadableNodeStream(stream) + const writable = + (_options$writable = options.writable) !== null && _options$writable !== undefined + ? _options$writable + : isWritableNodeStream(stream) + + if (!isNodeStream(stream)) { + // TODO: Webstreams. + throw new ERR_INVALID_ARG_TYPE('stream', 'Stream', stream) + } + + const wState = stream._writableState + const rState = stream._readableState + + const onlegacyfinish = () => { + if (!stream.writable) { + onfinish() + } + } // TODO (ronag): Improve soft detection to include core modules and + // common ecosystem modules that do properly emit 'close' but fail + // this generic check. + + let willEmitClose = + _willEmitClose(stream) && isReadableNodeStream(stream) === readable && isWritableNodeStream(stream) === writable + let writableFinished = isWritableFinished(stream, false) + + const onfinish = () => { + writableFinished = true // Stream should not be destroyed here. If it is that + // means that user space is doing something differently and + // we cannot trust willEmitClose. + + if (stream.destroyed) { + willEmitClose = false + } + + if (willEmitClose && (!stream.readable || readable)) { + return + } + + if (!readable || readableFinished) { + callback.call(stream) + } + } + + let readableFinished = isReadableFinished(stream, false) + + const onend = () => { + readableFinished = true // Stream should not be destroyed here. If it is that + // means that user space is doing something differently and + // we cannot trust willEmitClose. + + if (stream.destroyed) { + willEmitClose = false + } + + if (willEmitClose && (!stream.writable || writable)) { + return + } + + if (!writable || writableFinished) { + callback.call(stream) + } + } + + const onerror = (err) => { + callback.call(stream, err) + } + + let closed = isClosed(stream) + + const onclose = () => { + closed = true + const errored = isWritableErrored(stream) || isReadableErrored(stream) + + if (errored && typeof errored !== 'boolean') { + return callback.call(stream, errored) + } + + if (readable && !readableFinished && isReadableNodeStream(stream, true)) { + if (!isReadableFinished(stream, false)) return callback.call(stream, new ERR_STREAM_PREMATURE_CLOSE()) + } + + if (writable && !writableFinished) { + if (!isWritableFinished(stream, false)) return callback.call(stream, new ERR_STREAM_PREMATURE_CLOSE()) + } + + callback.call(stream) + } + + const onrequest = () => { + stream.req.on('finish', onfinish) + } + + if (isRequest(stream)) { + stream.on('complete', onfinish) + + if (!willEmitClose) { + stream.on('abort', onclose) + } + + if (stream.req) { + onrequest() + } else { + stream.on('request', onrequest) + } + } else if (writable && !wState) { + // legacy streams + stream.on('end', onlegacyfinish) + stream.on('close', onlegacyfinish) + } // Not all streams will emit 'close' after 'aborted'. + + if (!willEmitClose && typeof stream.aborted === 'boolean') { + stream.on('aborted', onclose) + } + + stream.on('end', onend) + stream.on('finish', onfinish) + + if (options.error !== false) { + stream.on('error', onerror) + } + + stream.on('close', onclose) + + if (closed) { + process.nextTick(onclose) + } else if ( + (wState !== null && wState !== undefined && wState.errorEmitted) || + (rState !== null && rState !== undefined && rState.errorEmitted) + ) { + if (!willEmitClose) { + process.nextTick(onclose) + } + } else if ( + !readable && + (!willEmitClose || isReadable(stream)) && + (writableFinished || isWritable(stream) === false) + ) { + process.nextTick(onclose) + } else if ( + !writable && + (!willEmitClose || isWritable(stream)) && + (readableFinished || isReadable(stream) === false) + ) { + process.nextTick(onclose) + } else if (rState && stream.req && stream.aborted) { + process.nextTick(onclose) + } + + const cleanup = () => { + callback = nop + stream.removeListener('aborted', onclose) + stream.removeListener('complete', onfinish) + stream.removeListener('abort', onclose) + stream.removeListener('request', onrequest) + if (stream.req) stream.req.removeListener('finish', onfinish) + stream.removeListener('end', onlegacyfinish) + stream.removeListener('close', onlegacyfinish) + stream.removeListener('finish', onfinish) + stream.removeListener('end', onend) + stream.removeListener('error', onerror) + stream.removeListener('close', onclose) + } + + if (options.signal && !closed) { + const abort = () => { + // Keep it because cleanup removes it. + const endCallback = callback + cleanup() + endCallback.call( + stream, + new AbortError(undefined, { + cause: options.signal.reason + }) + ) + } + + if (options.signal.aborted) { + process.nextTick(abort) + } else { + const originalCallback = callback + callback = once((...args) => { + options.signal.removeEventListener('abort', abort) + originalCallback.apply(stream, args) + }) + options.signal.addEventListener('abort', abort) + } + } + + return cleanup +} + +function finished(stream, opts) { + return new Promise((resolve, reject) => { + eos(stream, opts, (err) => { + if (err) { + reject(err) + } else { + resolve() + } + }) + }) +} + +module.exports = eos +module.exports.finished = finished diff --git a/server/libs/archiver/archiverUtils/readableStream/internal/streams/from.js b/server/libs/archiver/archiverUtils/readableStream/internal/streams/from.js new file mode 100644 index 000000000..6d40ac0ae --- /dev/null +++ b/server/libs/archiver/archiverUtils/readableStream/internal/streams/from.js @@ -0,0 +1,108 @@ +'use strict' + +const { PromisePrototypeThen, SymbolAsyncIterator, SymbolIterator } = require('../../ours/primordials') + +const { ERR_INVALID_ARG_TYPE, ERR_STREAM_NULL_VALUES } = require('../../ours/errors').codes + +function from(Readable, iterable, opts) { + let iterator + + if (typeof iterable === 'string' || iterable instanceof Buffer) { + return new Readable({ + objectMode: true, + ...opts, + + read() { + this.push(iterable) + this.push(null) + } + }) + } + + let isAsync + + if (iterable && iterable[SymbolAsyncIterator]) { + isAsync = true + iterator = iterable[SymbolAsyncIterator]() + } else if (iterable && iterable[SymbolIterator]) { + isAsync = false + iterator = iterable[SymbolIterator]() + } else { + throw new ERR_INVALID_ARG_TYPE('iterable', ['Iterable'], iterable) + } + + const readable = new Readable({ + objectMode: true, + highWaterMark: 1, + // TODO(ronag): What options should be allowed? + ...opts + }) // Flag to protect against _read + // being called before last iteration completion. + + let reading = false + + readable._read = function () { + if (!reading) { + reading = true + next() + } + } + + readable._destroy = function (error, cb) { + PromisePrototypeThen( + close(error), + () => process.nextTick(cb, error), // nextTick is here in case cb throws + (e) => process.nextTick(cb, e || error) + ) + } + + async function close(error) { + const hadError = error !== undefined && error !== null + const hasThrow = typeof iterator.throw === 'function' + + if (hadError && hasThrow) { + const { value, done } = await iterator.throw(error) + await value + + if (done) { + return + } + } + + if (typeof iterator.return === 'function') { + const { value } = await iterator.return() + await value + } + } + + async function next() { + for (;;) { + try { + const { value, done } = isAsync ? await iterator.next() : iterator.next() + + if (done) { + readable.push(null) + } else { + const res = value && typeof value.then === 'function' ? await value : value + + if (res === null) { + reading = false + throw new ERR_STREAM_NULL_VALUES() + } else if (readable.push(res)) { + continue + } else { + reading = false + } + } + } catch (err) { + readable.destroy(err) + } + + break + } + } + + return readable +} + +module.exports = from diff --git a/server/libs/archiver/archiverUtils/readableStream/internal/streams/lazy_transform.js b/server/libs/archiver/archiverUtils/readableStream/internal/streams/lazy_transform.js new file mode 100644 index 000000000..06073b0d1 --- /dev/null +++ b/server/libs/archiver/archiverUtils/readableStream/internal/streams/lazy_transform.js @@ -0,0 +1,58 @@ +// LazyTransform is a special type of Transform stream that is lazily loaded. +// This is used for performance with bi-API-ship: when two APIs are available +// for the stream, one conventional and one non-conventional. +'use strict' + +const { ObjectDefineProperties, ObjectDefineProperty, ObjectSetPrototypeOf } = require('../../ours/primordials') + +const stream = require('../../stream') + +const { getDefaultEncoding } = require('../crypto/util') + +module.exports = LazyTransform + +function LazyTransform(options) { + this._options = options +} + +ObjectSetPrototypeOf(LazyTransform.prototype, stream.Transform.prototype) +ObjectSetPrototypeOf(LazyTransform, stream.Transform) + +function makeGetter(name) { + return function () { + stream.Transform.call(this, this._options) + this._writableState.decodeStrings = false + + if (!this._options || !this._options.defaultEncoding) { + this._writableState.defaultEncoding = getDefaultEncoding() + } + + return this[name] + } +} + +function makeSetter(name) { + return function (val) { + ObjectDefineProperty(this, name, { + value: val, + enumerable: true, + configurable: true, + writable: true + }) + } +} + +ObjectDefineProperties(LazyTransform.prototype, { + _readableState: { + get: makeGetter('_readableState'), + set: makeSetter('_readableState'), + configurable: true, + enumerable: true + }, + _writableState: { + get: makeGetter('_writableState'), + set: makeSetter('_writableState'), + configurable: true, + enumerable: true + } +}) diff --git a/server/libs/archiver/archiverUtils/readableStream/internal/streams/legacy.js b/server/libs/archiver/archiverUtils/readableStream/internal/streams/legacy.js new file mode 100644 index 000000000..09c3b7201 --- /dev/null +++ b/server/libs/archiver/archiverUtils/readableStream/internal/streams/legacy.js @@ -0,0 +1,100 @@ +'use strict' + +const { ArrayIsArray, ObjectSetPrototypeOf } = require('../../ours/primordials') + +const { EventEmitter: EE } = require('events') + +function Stream(opts) { + EE.call(this, opts) +} + +ObjectSetPrototypeOf(Stream.prototype, EE.prototype) +ObjectSetPrototypeOf(Stream, EE) + +Stream.prototype.pipe = function (dest, options) { + const source = this + + function ondata(chunk) { + if (dest.writable && dest.write(chunk) === false && source.pause) { + source.pause() + } + } + + source.on('data', ondata) + + function ondrain() { + if (source.readable && source.resume) { + source.resume() + } + } + + dest.on('drain', ondrain) // If the 'end' option is not supplied, dest.end() will be called when + // source gets the 'end' or 'close' events. Only dest.end() once. + + if (!dest._isStdio && (!options || options.end !== false)) { + source.on('end', onend) + source.on('close', onclose) + } + + let didOnEnd = false + + function onend() { + if (didOnEnd) return + didOnEnd = true + dest.end() + } + + function onclose() { + if (didOnEnd) return + didOnEnd = true + if (typeof dest.destroy === 'function') dest.destroy() + } // Don't leave dangling pipes when there are errors. + + function onerror(er) { + cleanup() + + if (EE.listenerCount(this, 'error') === 0) { + this.emit('error', er) + } + } + + prependListener(source, 'error', onerror) + prependListener(dest, 'error', onerror) // Remove all the event listeners that were added. + + function cleanup() { + source.removeListener('data', ondata) + dest.removeListener('drain', ondrain) + source.removeListener('end', onend) + source.removeListener('close', onclose) + source.removeListener('error', onerror) + dest.removeListener('error', onerror) + source.removeListener('end', cleanup) + source.removeListener('close', cleanup) + dest.removeListener('close', cleanup) + } + + source.on('end', cleanup) + source.on('close', cleanup) + dest.on('close', cleanup) + dest.emit('pipe', source) // Allow for unix-like usage: A.pipe(B).pipe(C) + + return dest +} + +function prependListener(emitter, event, fn) { + // Sadly this is not cacheable as some libraries bundle their own + // event emitter implementation with them. + if (typeof emitter.prependListener === 'function') return emitter.prependListener(event, fn) // This is a hack to make sure that our error handler is attached before any + // userland ones. NEVER DO THIS. This is here only because this code needs + // to continue to work with older versions of Node.js that do not include + // the prependListener() method. The goal is to eventually remove this hack. + + if (!emitter._events || !emitter._events[event]) emitter.on(event, fn) + else if (ArrayIsArray(emitter._events[event])) emitter._events[event].unshift(fn) + else emitter._events[event] = [fn, emitter._events[event]] +} + +module.exports = { + Stream, + prependListener +} diff --git a/server/libs/archiver/archiverUtils/readableStream/internal/streams/operators.js b/server/libs/archiver/archiverUtils/readableStream/internal/streams/operators.js new file mode 100644 index 000000000..ddaa7f6f1 --- /dev/null +++ b/server/libs/archiver/archiverUtils/readableStream/internal/streams/operators.js @@ -0,0 +1,537 @@ +'use strict' + +const abortControllerModule = require('../../../../../watcher/aborter/controller') + +const AbortController = globalThis.AbortController || abortControllerModule.AbortController + +const { + codes: { ERR_INVALID_ARG_TYPE, ERR_MISSING_ARGS, ERR_OUT_OF_RANGE }, + AbortError +} = require('../../ours/errors') + +const { validateAbortSignal, validateInteger, validateObject } = require('../validators') + +const kWeakHandler = require('../../ours/primordials').Symbol('kWeak') + +const { finished } = require('./end-of-stream') + +const { + ArrayPrototypePush, + MathFloor, + Number, + NumberIsNaN, + Promise, + PromiseReject, + PromisePrototypeCatch, + Symbol +} = require('../../ours/primordials') + +const kEmpty = Symbol('kEmpty') +const kEof = Symbol('kEof') + +function map(fn, options) { + if (typeof fn !== 'function') { + throw new ERR_INVALID_ARG_TYPE('fn', ['Function', 'AsyncFunction'], fn) + } + + if (options != null) { + validateObject(options, 'options') + } + + if ((options === null || options === undefined ? undefined : options.signal) != null) { + validateAbortSignal(options.signal, 'options.signal') + } + + let concurrency = 1 + + if ((options === null || options === undefined ? undefined : options.concurrency) != null) { + concurrency = MathFloor(options.concurrency) + } + + validateInteger(concurrency, 'concurrency', 1) + return async function* map() { + var _options$signal, _options$signal2 + + const ac = new AbortController() + const stream = this + const queue = [] + const signal = ac.signal + const signalOpt = { + signal + } + + const abort = () => ac.abort() + + if ( + options !== null && + options !== undefined && + (_options$signal = options.signal) !== null && + _options$signal !== undefined && + _options$signal.aborted + ) { + abort() + } + + options === null || options === undefined + ? undefined + : (_options$signal2 = options.signal) === null || _options$signal2 === undefined + ? undefined + : _options$signal2.addEventListener('abort', abort) + let next + let resume + let done = false + + function onDone() { + done = true + } + + async function pump() { + try { + for await (let val of stream) { + var _val + + if (done) { + return + } + + if (signal.aborted) { + throw new AbortError() + } + + try { + val = fn(val, signalOpt) + } catch (err) { + val = PromiseReject(err) + } + + if (val === kEmpty) { + continue + } + + if (typeof ((_val = val) === null || _val === undefined ? undefined : _val.catch) === 'function') { + val.catch(onDone) + } + + queue.push(val) + + if (next) { + next() + next = null + } + + if (!done && queue.length && queue.length >= concurrency) { + await new Promise((resolve) => { + resume = resolve + }) + } + } + + queue.push(kEof) + } catch (err) { + const val = PromiseReject(err) + PromisePrototypeCatch(val, onDone) + queue.push(val) + } finally { + var _options$signal3 + + done = true + + if (next) { + next() + next = null + } + + options === null || options === undefined + ? undefined + : (_options$signal3 = options.signal) === null || _options$signal3 === undefined + ? undefined + : _options$signal3.removeEventListener('abort', abort) + } + } + + pump() + + try { + while (true) { + while (queue.length > 0) { + const val = await queue[0] + + if (val === kEof) { + return + } + + if (signal.aborted) { + throw new AbortError() + } + + if (val !== kEmpty) { + yield val + } + + queue.shift() + + if (resume) { + resume() + resume = null + } + } + + await new Promise((resolve) => { + next = resolve + }) + } + } finally { + ac.abort() + done = true + + if (resume) { + resume() + resume = null + } + } + }.call(this) +} + +function asIndexedPairs(options = undefined) { + if (options != null) { + validateObject(options, 'options') + } + + if ((options === null || options === undefined ? undefined : options.signal) != null) { + validateAbortSignal(options.signal, 'options.signal') + } + + return async function* asIndexedPairs() { + let index = 0 + + for await (const val of this) { + var _options$signal4 + + if ( + options !== null && + options !== undefined && + (_options$signal4 = options.signal) !== null && + _options$signal4 !== undefined && + _options$signal4.aborted + ) { + throw new AbortError({ + cause: options.signal.reason + }) + } + + yield [index++, val] + } + }.call(this) +} + +async function some(fn, options = undefined) { + // eslint-disable-next-line no-unused-vars + for await (const unused of filter.call(this, fn, options)) { + return true + } + + return false +} + +async function every(fn, options = undefined) { + if (typeof fn !== 'function') { + throw new ERR_INVALID_ARG_TYPE('fn', ['Function', 'AsyncFunction'], fn) + } // https://en.wikipedia.org/wiki/De_Morgan%27s_laws + + return !(await some.call( + this, + async (...args) => { + return !(await fn(...args)) + }, + options + )) +} + +async function find(fn, options) { + for await (const result of filter.call(this, fn, options)) { + return result + } + + return undefined +} + +async function forEach(fn, options) { + if (typeof fn !== 'function') { + throw new ERR_INVALID_ARG_TYPE('fn', ['Function', 'AsyncFunction'], fn) + } + + async function forEachFn(value, options) { + await fn(value, options) + return kEmpty + } // eslint-disable-next-line no-unused-vars + + for await (const unused of map.call(this, forEachFn, options)); +} + +function filter(fn, options) { + if (typeof fn !== 'function') { + throw new ERR_INVALID_ARG_TYPE('fn', ['Function', 'AsyncFunction'], fn) + } + + async function filterFn(value, options) { + if (await fn(value, options)) { + return value + } + + return kEmpty + } + + return map.call(this, filterFn, options) +} // Specific to provide better error to reduce since the argument is only +// missing if the stream has no items in it - but the code is still appropriate + +class ReduceAwareErrMissingArgs extends ERR_MISSING_ARGS { + constructor() { + super('reduce') + this.message = 'Reduce of an empty stream requires an initial value' + } +} + +async function reduce(reducer, initialValue, options) { + var _options$signal5 + + if (typeof reducer !== 'function') { + throw new ERR_INVALID_ARG_TYPE('reducer', ['Function', 'AsyncFunction'], reducer) + } + + if (options != null) { + validateObject(options, 'options') + } + + if ((options === null || options === undefined ? undefined : options.signal) != null) { + validateAbortSignal(options.signal, 'options.signal') + } + + let hasInitialValue = arguments.length > 1 + + if ( + options !== null && + options !== undefined && + (_options$signal5 = options.signal) !== null && + _options$signal5 !== undefined && + _options$signal5.aborted + ) { + const err = new AbortError(undefined, { + cause: options.signal.reason + }) + this.once('error', () => { }) // The error is already propagated + + await finished(this.destroy(err)) + throw err + } + + const ac = new AbortController() + const signal = ac.signal + + if (options !== null && options !== undefined && options.signal) { + const opts = { + once: true, + [kWeakHandler]: this + } + options.signal.addEventListener('abort', () => ac.abort(), opts) + } + + let gotAnyItemFromStream = false + + try { + for await (const value of this) { + var _options$signal6 + + gotAnyItemFromStream = true + + if ( + options !== null && + options !== undefined && + (_options$signal6 = options.signal) !== null && + _options$signal6 !== undefined && + _options$signal6.aborted + ) { + throw new AbortError() + } + + if (!hasInitialValue) { + initialValue = value + hasInitialValue = true + } else { + initialValue = await reducer(initialValue, value, { + signal + }) + } + } + + if (!gotAnyItemFromStream && !hasInitialValue) { + throw new ReduceAwareErrMissingArgs() + } + } finally { + ac.abort() + } + + return initialValue +} + +async function toArray(options) { + if (options != null) { + validateObject(options, 'options') + } + + if ((options === null || options === undefined ? undefined : options.signal) != null) { + validateAbortSignal(options.signal, 'options.signal') + } + + const result = [] + + for await (const val of this) { + var _options$signal7 + + if ( + options !== null && + options !== undefined && + (_options$signal7 = options.signal) !== null && + _options$signal7 !== undefined && + _options$signal7.aborted + ) { + throw new AbortError(undefined, { + cause: options.signal.reason + }) + } + + ArrayPrototypePush(result, val) + } + + return result +} + +function flatMap(fn, options) { + const values = map.call(this, fn, options) + return async function* flatMap() { + for await (const val of values) { + yield* val + } + }.call(this) +} + +function toIntegerOrInfinity(number) { + // We coerce here to align with the spec + // https://github.com/tc39/proposal-iterator-helpers/issues/169 + number = Number(number) + + if (NumberIsNaN(number)) { + return 0 + } + + if (number < 0) { + throw new ERR_OUT_OF_RANGE('number', '>= 0', number) + } + + return number +} + +function drop(number, options = undefined) { + if (options != null) { + validateObject(options, 'options') + } + + if ((options === null || options === undefined ? undefined : options.signal) != null) { + validateAbortSignal(options.signal, 'options.signal') + } + + number = toIntegerOrInfinity(number) + return async function* drop() { + var _options$signal8 + + if ( + options !== null && + options !== undefined && + (_options$signal8 = options.signal) !== null && + _options$signal8 !== undefined && + _options$signal8.aborted + ) { + throw new AbortError() + } + + for await (const val of this) { + var _options$signal9 + + if ( + options !== null && + options !== undefined && + (_options$signal9 = options.signal) !== null && + _options$signal9 !== undefined && + _options$signal9.aborted + ) { + throw new AbortError() + } + + if (number-- <= 0) { + yield val + } + } + }.call(this) +} + +function take(number, options = undefined) { + if (options != null) { + validateObject(options, 'options') + } + + if ((options === null || options === undefined ? undefined : options.signal) != null) { + validateAbortSignal(options.signal, 'options.signal') + } + + number = toIntegerOrInfinity(number) + return async function* take() { + var _options$signal10 + + if ( + options !== null && + options !== undefined && + (_options$signal10 = options.signal) !== null && + _options$signal10 !== undefined && + _options$signal10.aborted + ) { + throw new AbortError() + } + + for await (const val of this) { + var _options$signal11 + + if ( + options !== null && + options !== undefined && + (_options$signal11 = options.signal) !== null && + _options$signal11 !== undefined && + _options$signal11.aborted + ) { + throw new AbortError() + } + + if (number-- > 0) { + yield val + } else { + return + } + } + }.call(this) +} + +module.exports.streamReturningOperators = { + asIndexedPairs, + drop, + filter, + flatMap, + map, + take +} +module.exports.promiseReturningOperators = { + every, + forEach, + reduce, + toArray, + some, + find +} diff --git a/server/libs/archiver/archiverUtils/readableStream/internal/streams/passthrough.js b/server/libs/archiver/archiverUtils/readableStream/internal/streams/passthrough.js new file mode 100644 index 000000000..55c551723 --- /dev/null +++ b/server/libs/archiver/archiverUtils/readableStream/internal/streams/passthrough.js @@ -0,0 +1,42 @@ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. +// a passthrough stream. +// basically just the most minimal sort of Transform stream. +// Every written chunk gets output as-is. +'use strict' + +const { ObjectSetPrototypeOf } = require('../../ours/primordials') + +module.exports = PassThrough + +const Transform = require('./transform') + +ObjectSetPrototypeOf(PassThrough.prototype, Transform.prototype) +ObjectSetPrototypeOf(PassThrough, Transform) + +function PassThrough(options) { + if (!(this instanceof PassThrough)) return new PassThrough(options) + Transform.call(this, options) +} + +PassThrough.prototype._transform = function (chunk, encoding, cb) { + cb(null, chunk) +} diff --git a/server/libs/archiver/archiverUtils/readableStream/internal/streams/pipeline.js b/server/libs/archiver/archiverUtils/readableStream/internal/streams/pipeline.js new file mode 100644 index 000000000..14c74b3a8 --- /dev/null +++ b/server/libs/archiver/archiverUtils/readableStream/internal/streams/pipeline.js @@ -0,0 +1,415 @@ +// Ported from https://github.com/mafintosh/pump with +// permission from the author, Mathias Buus (@mafintosh). +'use strict' + +const abortControllerModule = require('../../../../../watcher/aborter/controller') + +const { ArrayIsArray, Promise, SymbolAsyncIterator } = require('../../ours/primordials') + +const eos = require('./end-of-stream') + +const { once } = require('../../ours/util') + +const destroyImpl = require('./destroy') + +const Duplex = require('./duplex') + +const { + aggregateTwoErrors, + codes: { ERR_INVALID_ARG_TYPE, ERR_INVALID_RETURN_VALUE, ERR_MISSING_ARGS, ERR_STREAM_DESTROYED }, + AbortError +} = require('../../ours/errors') + +const { validateFunction, validateAbortSignal } = require('../validators') + +const { isIterable, isReadable, isReadableNodeStream, isNodeStream } = require('./utils') + +const AbortController = globalThis.AbortController || abortControllerModule.AbortController +let PassThrough +let Readable + +function destroyer(stream, reading, writing) { + let finished = false + stream.on('close', () => { + finished = true + }) + const cleanup = eos( + stream, + { + readable: reading, + writable: writing + }, + (err) => { + finished = !err + } + ) + return { + destroy: (err) => { + if (finished) return + finished = true + destroyImpl.destroyer(stream, err || new ERR_STREAM_DESTROYED('pipe')) + }, + cleanup + } +} + +function popCallback(streams) { + // Streams should never be an empty array. It should always contain at least + // a single stream. Therefore optimize for the average case instead of + // checking for length === 0 as well. + validateFunction(streams[streams.length - 1], 'streams[stream.length - 1]') + return streams.pop() +} + +function makeAsyncIterable(val) { + if (isIterable(val)) { + return val + } else if (isReadableNodeStream(val)) { + // Legacy streams are not Iterable. + return fromReadable(val) + } + + throw new ERR_INVALID_ARG_TYPE('val', ['Readable', 'Iterable', 'AsyncIterable'], val) +} + +async function* fromReadable(val) { + if (!Readable) { + Readable = require('./readable') + } + + yield* Readable.prototype[SymbolAsyncIterator].call(val) +} + +async function pump(iterable, writable, finish, { end }) { + let error + let onresolve = null + + const resume = (err) => { + if (err) { + error = err + } + + if (onresolve) { + const callback = onresolve + onresolve = null + callback() + } + } + + const wait = () => + new Promise((resolve, reject) => { + if (error) { + reject(error) + } else { + onresolve = () => { + if (error) { + reject(error) + } else { + resolve() + } + } + } + }) + + writable.on('drain', resume) + const cleanup = eos( + writable, + { + readable: false + }, + resume + ) + + try { + if (writable.writableNeedDrain) { + await wait() + } + + for await (const chunk of iterable) { + if (!writable.write(chunk)) { + await wait() + } + } + + if (end) { + writable.end() + } + + await wait() + finish() + } catch (err) { + finish(error !== err ? aggregateTwoErrors(error, err) : err) + } finally { + cleanup() + writable.off('drain', resume) + } +} + +function pipeline(...streams) { + return pipelineImpl(streams, once(popCallback(streams))) +} + +function pipelineImpl(streams, callback, opts) { + if (streams.length === 1 && ArrayIsArray(streams[0])) { + streams = streams[0] + } + + if (streams.length < 2) { + throw new ERR_MISSING_ARGS('streams') + } + + const ac = new AbortController() + const signal = ac.signal + const outerSignal = opts === null || opts === undefined ? undefined : opts.signal // Need to cleanup event listeners if last stream is readable + // https://github.com/nodejs/node/issues/35452 + + const lastStreamCleanup = [] + validateAbortSignal(outerSignal, 'options.signal') + + function abort() { + finishImpl(new AbortError()) + } + + outerSignal === null || outerSignal === undefined ? undefined : outerSignal.addEventListener('abort', abort) + let error + let value + const destroys = [] + let finishCount = 0 + + function finish(err) { + finishImpl(err, --finishCount === 0) + } + + function finishImpl(err, final) { + if (err && (!error || error.code === 'ERR_STREAM_PREMATURE_CLOSE')) { + error = err + } + + if (!error && !final) { + return + } + + while (destroys.length) { + destroys.shift()(error) + } + + outerSignal === null || outerSignal === undefined ? undefined : outerSignal.removeEventListener('abort', abort) + ac.abort() + + if (final) { + if (!error) { + lastStreamCleanup.forEach((fn) => fn()) + } + + process.nextTick(callback, error, value) + } + } + + let ret + + for (let i = 0; i < streams.length; i++) { + const stream = streams[i] + const reading = i < streams.length - 1 + const writing = i > 0 + const end = reading || (opts === null || opts === undefined ? undefined : opts.end) !== false + const isLastStream = i === streams.length - 1 + + if (isNodeStream(stream)) { + if (end) { + const { destroy, cleanup } = destroyer(stream, reading, writing) + destroys.push(destroy) + + if (isReadable(stream) && isLastStream) { + lastStreamCleanup.push(cleanup) + } + } // Catch stream errors that occur after pipe/pump has completed. + + function onError(err) { + if (err && err.name !== 'AbortError' && err.code !== 'ERR_STREAM_PREMATURE_CLOSE') { + finish(err) + } + } + + stream.on('error', onError) + + if (isReadable(stream) && isLastStream) { + lastStreamCleanup.push(() => { + stream.removeListener('error', onError) + }) + } + } + + if (i === 0) { + if (typeof stream === 'function') { + ret = stream({ + signal + }) + + if (!isIterable(ret)) { + throw new ERR_INVALID_RETURN_VALUE('Iterable, AsyncIterable or Stream', 'source', ret) + } + } else if (isIterable(stream) || isReadableNodeStream(stream)) { + ret = stream + } else { + ret = Duplex.from(stream) + } + } else if (typeof stream === 'function') { + ret = makeAsyncIterable(ret) + ret = stream(ret, { + signal + }) + + if (reading) { + if (!isIterable(ret, true)) { + throw new ERR_INVALID_RETURN_VALUE('AsyncIterable', `transform[${i - 1}]`, ret) + } + } else { + var _ret + + if (!PassThrough) { + PassThrough = require('./passthrough') + } // If the last argument to pipeline is not a stream + // we must create a proxy stream so that pipeline(...) + // always returns a stream which can be further + // composed through `.pipe(stream)`. + + const pt = new PassThrough({ + objectMode: true + }) // Handle Promises/A+ spec, `then` could be a getter that throws on + // second use. + + const then = (_ret = ret) === null || _ret === undefined ? undefined : _ret.then + + if (typeof then === 'function') { + finishCount++ + then.call( + ret, + (val) => { + value = val + + if (val != null) { + pt.write(val) + } + + if (end) { + pt.end() + } + + process.nextTick(finish) + }, + (err) => { + pt.destroy(err) + process.nextTick(finish, err) + } + ) + } else if (isIterable(ret, true)) { + finishCount++ + pump(ret, pt, finish, { + end + }) + } else { + throw new ERR_INVALID_RETURN_VALUE('AsyncIterable or Promise', 'destination', ret) + } + + ret = pt + const { destroy, cleanup } = destroyer(ret, false, true) + destroys.push(destroy) + + if (isLastStream) { + lastStreamCleanup.push(cleanup) + } + } + } else if (isNodeStream(stream)) { + if (isReadableNodeStream(ret)) { + finishCount += 2 + const cleanup = pipe(ret, stream, finish, { + end + }) + + if (isReadable(stream) && isLastStream) { + lastStreamCleanup.push(cleanup) + } + } else if (isIterable(ret)) { + finishCount++ + pump(ret, stream, finish, { + end + }) + } else { + throw new ERR_INVALID_ARG_TYPE('val', ['Readable', 'Iterable', 'AsyncIterable'], ret) + } + + ret = stream + } else { + ret = Duplex.from(stream) + } + } + + if ( + (signal !== null && signal !== undefined && signal.aborted) || + (outerSignal !== null && outerSignal !== undefined && outerSignal.aborted) + ) { + process.nextTick(abort) + } + + return ret +} + +function pipe(src, dst, finish, { end }) { + src.pipe(dst, { + end + }) + + if (end) { + // Compat. Before node v10.12.0 stdio used to throw an error so + // pipe() did/does not end() stdio destinations. + // Now they allow it but "secretly" don't close the underlying fd. + src.once('end', () => dst.end()) + } else { + finish() + } + + eos( + src, + { + readable: true, + writable: false + }, + (err) => { + const rState = src._readableState + + if ( + err && + err.code === 'ERR_STREAM_PREMATURE_CLOSE' && + rState && + rState.ended && + !rState.errored && + !rState.errorEmitted + ) { + // Some readable streams will emit 'close' before 'end'. However, since + // this is on the readable side 'end' should still be emitted if the + // stream has been ended and no error emitted. This should be allowed in + // favor of backwards compatibility. Since the stream is piped to a + // destination this should not result in any observable difference. + // We don't need to check if this is a writable premature close since + // eos will only fail with premature close on the reading side for + // duplex streams. + src.once('end', finish).once('error', finish) + } else { + finish(err) + } + } + ) + return eos( + dst, + { + readable: false, + writable: true + }, + finish + ) +} + +module.exports = { + pipelineImpl, + pipeline +} diff --git a/server/libs/archiver/archiverUtils/readableStream/internal/streams/readable.js b/server/libs/archiver/archiverUtils/readableStream/internal/streams/readable.js new file mode 100644 index 000000000..9c263c8a6 --- /dev/null +++ b/server/libs/archiver/archiverUtils/readableStream/internal/streams/readable.js @@ -0,0 +1,1314 @@ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. +'use strict' + +const { + ArrayPrototypeIndexOf, + NumberIsInteger, + NumberIsNaN, + NumberParseInt, + ObjectDefineProperties, + ObjectKeys, + ObjectSetPrototypeOf, + Promise, + SafeSet, + SymbolAsyncIterator, + Symbol +} = require('../../ours/primordials') + +module.exports = Readable +Readable.ReadableState = ReadableState + +const { EventEmitter: EE } = require('events') + +const { Stream, prependListener } = require('./legacy') + +const { addAbortSignal } = require('./add-abort-signal') + +const eos = require('./end-of-stream') + +let debug = require('../../ours/util').debuglog('stream', (fn) => { + debug = fn +}) + +const BufferList = require('./buffer_list') + +const destroyImpl = require('./destroy') + +const { getHighWaterMark, getDefaultHighWaterMark } = require('./state') + +const { + aggregateTwoErrors, + codes: { + ERR_INVALID_ARG_TYPE, + ERR_METHOD_NOT_IMPLEMENTED, + ERR_OUT_OF_RANGE, + ERR_STREAM_PUSH_AFTER_EOF, + ERR_STREAM_UNSHIFT_AFTER_END_EVENT + } +} = require('../../ours/errors') + +const { validateObject } = require('../validators') + +const kPaused = Symbol('kPaused') + +const { StringDecoder } = require('string_decoder') + +const from = require('./from') + +ObjectSetPrototypeOf(Readable.prototype, Stream.prototype) +ObjectSetPrototypeOf(Readable, Stream) + +const nop = () => {} + +const { errorOrDestroy } = destroyImpl + +function ReadableState(options, stream, isDuplex) { + // Duplex streams are both readable and writable, but share + // the same options object. + // However, some cases require setting options to different + // values for the readable and the writable sides of the duplex stream. + // These options can be provided separately as readableXXX and writableXXX. + if (typeof isDuplex !== 'boolean') isDuplex = stream instanceof require('./duplex') // Object stream flag. Used to make read(n) ignore n and to + // make all the buffer merging and length checks go away. + + this.objectMode = !!(options && options.objectMode) + if (isDuplex) this.objectMode = this.objectMode || !!(options && options.readableObjectMode) // The point at which it stops calling _read() to fill the buffer + // Note: 0 is a valid value, means "don't call _read preemptively ever" + + this.highWaterMark = options + ? getHighWaterMark(this, options, 'readableHighWaterMark', isDuplex) + : getDefaultHighWaterMark(false) // A linked list is used to store data chunks instead of an array because the + // linked list can remove elements from the beginning faster than + // array.shift(). + + this.buffer = new BufferList() + this.length = 0 + this.pipes = [] + this.flowing = null + this.ended = false + this.endEmitted = false + this.reading = false // Stream is still being constructed and cannot be + // destroyed until construction finished or failed. + // Async construction is opt in, therefore we start as + // constructed. + + this.constructed = true // A flag to be able to tell if the event 'readable'/'data' is emitted + // immediately, or on a later tick. We set this to true at first, because + // any actions that shouldn't happen until "later" should generally also + // not happen before the first read call. + + this.sync = true // Whenever we return null, then we set a flag to say + // that we're awaiting a 'readable' event emission. + + this.needReadable = false + this.emittedReadable = false + this.readableListening = false + this.resumeScheduled = false + this[kPaused] = null // True if the error was already emitted and should not be thrown again. + + this.errorEmitted = false // Should close be emitted on destroy. Defaults to true. + + this.emitClose = !options || options.emitClose !== false // Should .destroy() be called after 'end' (and potentially 'finish'). + + this.autoDestroy = !options || options.autoDestroy !== false // Has it been destroyed. + + this.destroyed = false // Indicates whether the stream has errored. When true no further + // _read calls, 'data' or 'readable' events should occur. This is needed + // since when autoDestroy is disabled we need a way to tell whether the + // stream has failed. + + this.errored = null // Indicates whether the stream has finished destroying. + + this.closed = false // True if close has been emitted or would have been emitted + // depending on emitClose. + + this.closeEmitted = false // Crypto is kind of old and crusty. Historically, its default string + // encoding is 'binary' so we have to make this configurable. + // Everything else in the universe uses 'utf8', though. + + this.defaultEncoding = (options && options.defaultEncoding) || 'utf8' // Ref the piped dest which we need a drain event on it + // type: null | Writable | Set. + + this.awaitDrainWriters = null + this.multiAwaitDrain = false // If true, a maybeReadMore has been scheduled. + + this.readingMore = false + this.dataEmitted = false + this.decoder = null + this.encoding = null + + if (options && options.encoding) { + this.decoder = new StringDecoder(options.encoding) + this.encoding = options.encoding + } +} + +function Readable(options) { + if (!(this instanceof Readable)) return new Readable(options) // Checking for a Stream.Duplex instance is faster here instead of inside + // the ReadableState constructor, at least with V8 6.5. + + const isDuplex = this instanceof require('./duplex') + + this._readableState = new ReadableState(options, this, isDuplex) + + if (options) { + if (typeof options.read === 'function') this._read = options.read + if (typeof options.destroy === 'function') this._destroy = options.destroy + if (typeof options.construct === 'function') this._construct = options.construct + if (options.signal && !isDuplex) addAbortSignal(options.signal, this) + } + + Stream.call(this, options) + destroyImpl.construct(this, () => { + if (this._readableState.needReadable) { + maybeReadMore(this, this._readableState) + } + }) +} + +Readable.prototype.destroy = destroyImpl.destroy +Readable.prototype._undestroy = destroyImpl.undestroy + +Readable.prototype._destroy = function (err, cb) { + cb(err) +} + +Readable.prototype[EE.captureRejectionSymbol] = function (err) { + this.destroy(err) +} // Manually shove something into the read() buffer. +// This returns true if the highWaterMark has not been hit yet, +// similar to how Writable.write() returns true if you should +// write() some more. + +Readable.prototype.push = function (chunk, encoding) { + return readableAddChunk(this, chunk, encoding, false) +} // Unshift should *always* be something directly out of read(). + +Readable.prototype.unshift = function (chunk, encoding) { + return readableAddChunk(this, chunk, encoding, true) +} + +function readableAddChunk(stream, chunk, encoding, addToFront) { + debug('readableAddChunk', chunk) + const state = stream._readableState + let err + + if (!state.objectMode) { + if (typeof chunk === 'string') { + encoding = encoding || state.defaultEncoding + + if (state.encoding !== encoding) { + if (addToFront && state.encoding) { + // When unshifting, if state.encoding is set, we have to save + // the string in the BufferList with the state encoding. + chunk = Buffer.from(chunk, encoding).toString(state.encoding) + } else { + chunk = Buffer.from(chunk, encoding) + encoding = '' + } + } + } else if (chunk instanceof Buffer) { + encoding = '' + } else if (Stream._isUint8Array(chunk)) { + chunk = Stream._uint8ArrayToBuffer(chunk) + encoding = '' + } else if (chunk != null) { + err = new ERR_INVALID_ARG_TYPE('chunk', ['string', 'Buffer', 'Uint8Array'], chunk) + } + } + + if (err) { + errorOrDestroy(stream, err) + } else if (chunk === null) { + state.reading = false + onEofChunk(stream, state) + } else if (state.objectMode || (chunk && chunk.length > 0)) { + if (addToFront) { + if (state.endEmitted) errorOrDestroy(stream, new ERR_STREAM_UNSHIFT_AFTER_END_EVENT()) + else if (state.destroyed || state.errored) return false + else addChunk(stream, state, chunk, true) + } else if (state.ended) { + errorOrDestroy(stream, new ERR_STREAM_PUSH_AFTER_EOF()) + } else if (state.destroyed || state.errored) { + return false + } else { + state.reading = false + + if (state.decoder && !encoding) { + chunk = state.decoder.write(chunk) + if (state.objectMode || chunk.length !== 0) addChunk(stream, state, chunk, false) + else maybeReadMore(stream, state) + } else { + addChunk(stream, state, chunk, false) + } + } + } else if (!addToFront) { + state.reading = false + maybeReadMore(stream, state) + } // We can push more data if we are below the highWaterMark. + // Also, if we have no data yet, we can stand some more bytes. + // This is to work around cases where hwm=0, such as the repl. + + return !state.ended && (state.length < state.highWaterMark || state.length === 0) +} + +function addChunk(stream, state, chunk, addToFront) { + if (state.flowing && state.length === 0 && !state.sync && stream.listenerCount('data') > 0) { + // Use the guard to avoid creating `Set()` repeatedly + // when we have multiple pipes. + if (state.multiAwaitDrain) { + state.awaitDrainWriters.clear() + } else { + state.awaitDrainWriters = null + } + + state.dataEmitted = true + stream.emit('data', chunk) + } else { + // Update the buffer info. + state.length += state.objectMode ? 1 : chunk.length + if (addToFront) state.buffer.unshift(chunk) + else state.buffer.push(chunk) + if (state.needReadable) emitReadable(stream) + } + + maybeReadMore(stream, state) +} + +Readable.prototype.isPaused = function () { + const state = this._readableState + return state[kPaused] === true || state.flowing === false +} // Backwards compatibility. + +Readable.prototype.setEncoding = function (enc) { + const decoder = new StringDecoder(enc) + this._readableState.decoder = decoder // If setEncoding(null), decoder.encoding equals utf8. + + this._readableState.encoding = this._readableState.decoder.encoding + const buffer = this._readableState.buffer // Iterate over current buffer to convert already stored Buffers: + + let content = '' + + for (const data of buffer) { + content += decoder.write(data) + } + + buffer.clear() + if (content !== '') buffer.push(content) + this._readableState.length = content.length + return this +} // Don't raise the hwm > 1GB. + +const MAX_HWM = 0x40000000 + +function computeNewHighWaterMark(n) { + if (n > MAX_HWM) { + throw new ERR_OUT_OF_RANGE('size', '<= 1GiB', n) + } else { + // Get the next highest power of 2 to prevent increasing hwm excessively in + // tiny amounts. + n-- + n |= n >>> 1 + n |= n >>> 2 + n |= n >>> 4 + n |= n >>> 8 + n |= n >>> 16 + n++ + } + + return n +} // This function is designed to be inlinable, so please take care when making +// changes to the function body. + +function howMuchToRead(n, state) { + if (n <= 0 || (state.length === 0 && state.ended)) return 0 + if (state.objectMode) return 1 + + if (NumberIsNaN(n)) { + // Only flow one buffer at a time. + if (state.flowing && state.length) return state.buffer.first().length + return state.length + } + + if (n <= state.length) return n + return state.ended ? state.length : 0 +} // You can override either this method, or the async _read(n) below. + +Readable.prototype.read = function (n) { + debug('read', n) // Same as parseInt(undefined, 10), however V8 7.3 performance regressed + // in this scenario, so we are doing it manually. + + if (n === undefined) { + n = NaN + } else if (!NumberIsInteger(n)) { + n = NumberParseInt(n, 10) + } + + const state = this._readableState + const nOrig = n // If we're asking for more than the current hwm, then raise the hwm. + + if (n > state.highWaterMark) state.highWaterMark = computeNewHighWaterMark(n) + if (n !== 0) state.emittedReadable = false // If we're doing read(0) to trigger a readable event, but we + // already have a bunch of data in the buffer, then just trigger + // the 'readable' event and move on. + + if ( + n === 0 && + state.needReadable && + ((state.highWaterMark !== 0 ? state.length >= state.highWaterMark : state.length > 0) || state.ended) + ) { + debug('read: emitReadable', state.length, state.ended) + if (state.length === 0 && state.ended) endReadable(this) + else emitReadable(this) + return null + } + + n = howMuchToRead(n, state) // If we've ended, and we're now clear, then finish it up. + + if (n === 0 && state.ended) { + if (state.length === 0) endReadable(this) + return null + } // All the actual chunk generation logic needs to be + // *below* the call to _read. The reason is that in certain + // synthetic stream cases, such as passthrough streams, _read + // may be a completely synchronous operation which may change + // the state of the read buffer, providing enough data when + // before there was *not* enough. + // + // So, the steps are: + // 1. Figure out what the state of things will be after we do + // a read from the buffer. + // + // 2. If that resulting state will trigger a _read, then call _read. + // Note that this may be asynchronous, or synchronous. Yes, it is + // deeply ugly to write APIs this way, but that still doesn't mean + // that the Readable class should behave improperly, as streams are + // designed to be sync/async agnostic. + // Take note if the _read call is sync or async (ie, if the read call + // has returned yet), so that we know whether or not it's safe to emit + // 'readable' etc. + // + // 3. Actually pull the requested chunks out of the buffer and return. + // if we need a readable event, then we need to do some reading. + + let doRead = state.needReadable + debug('need readable', doRead) // If we currently have less than the highWaterMark, then also read some. + + if (state.length === 0 || state.length - n < state.highWaterMark) { + doRead = true + debug('length less than watermark', doRead) + } // However, if we've ended, then there's no point, if we're already + // reading, then it's unnecessary, if we're constructing we have to wait, + // and if we're destroyed or errored, then it's not allowed, + + if (state.ended || state.reading || state.destroyed || state.errored || !state.constructed) { + doRead = false + debug('reading, ended or constructing', doRead) + } else if (doRead) { + debug('do read') + state.reading = true + state.sync = true // If the length is currently zero, then we *need* a readable event. + + if (state.length === 0) state.needReadable = true // Call internal read method + + try { + this._read(state.highWaterMark) + } catch (err) { + errorOrDestroy(this, err) + } + + state.sync = false // If _read pushed data synchronously, then `reading` will be false, + // and we need to re-evaluate how much data we can return to the user. + + if (!state.reading) n = howMuchToRead(nOrig, state) + } + + let ret + if (n > 0) ret = fromList(n, state) + else ret = null + + if (ret === null) { + state.needReadable = state.length <= state.highWaterMark + n = 0 + } else { + state.length -= n + + if (state.multiAwaitDrain) { + state.awaitDrainWriters.clear() + } else { + state.awaitDrainWriters = null + } + } + + if (state.length === 0) { + // If we have nothing in the buffer, then we want to know + // as soon as we *do* get something into the buffer. + if (!state.ended) state.needReadable = true // If we tried to read() past the EOF, then emit end on the next tick. + + if (nOrig !== n && state.ended) endReadable(this) + } + + if (ret !== null && !state.errorEmitted && !state.closeEmitted) { + state.dataEmitted = true + this.emit('data', ret) + } + + return ret +} + +function onEofChunk(stream, state) { + debug('onEofChunk') + if (state.ended) return + + if (state.decoder) { + const chunk = state.decoder.end() + + if (chunk && chunk.length) { + state.buffer.push(chunk) + state.length += state.objectMode ? 1 : chunk.length + } + } + + state.ended = true + + if (state.sync) { + // If we are sync, wait until next tick to emit the data. + // Otherwise we risk emitting data in the flow() + // the readable code triggers during a read() call. + emitReadable(stream) + } else { + // Emit 'readable' now to make sure it gets picked up. + state.needReadable = false + state.emittedReadable = true // We have to emit readable now that we are EOF. Modules + // in the ecosystem (e.g. dicer) rely on this event being sync. + + emitReadable_(stream) + } +} // Don't emit readable right away in sync mode, because this can trigger +// another read() call => stack overflow. This way, it might trigger +// a nextTick recursion warning, but that's not so bad. + +function emitReadable(stream) { + const state = stream._readableState + debug('emitReadable', state.needReadable, state.emittedReadable) + state.needReadable = false + + if (!state.emittedReadable) { + debug('emitReadable', state.flowing) + state.emittedReadable = true + process.nextTick(emitReadable_, stream) + } +} + +function emitReadable_(stream) { + const state = stream._readableState + debug('emitReadable_', state.destroyed, state.length, state.ended) + + if (!state.destroyed && !state.errored && (state.length || state.ended)) { + stream.emit('readable') + state.emittedReadable = false + } // The stream needs another readable event if: + // 1. It is not flowing, as the flow mechanism will take + // care of it. + // 2. It is not ended. + // 3. It is below the highWaterMark, so we can schedule + // another readable later. + + state.needReadable = !state.flowing && !state.ended && state.length <= state.highWaterMark + flow(stream) +} // At this point, the user has presumably seen the 'readable' event, +// and called read() to consume some data. that may have triggered +// in turn another _read(n) call, in which case reading = true if +// it's in progress. +// However, if we're not ended, or reading, and the length < hwm, +// then go ahead and try to read some more preemptively. + +function maybeReadMore(stream, state) { + if (!state.readingMore && state.constructed) { + state.readingMore = true + process.nextTick(maybeReadMore_, stream, state) + } +} + +function maybeReadMore_(stream, state) { + // Attempt to read more data if we should. + // + // The conditions for reading more data are (one of): + // - Not enough data buffered (state.length < state.highWaterMark). The loop + // is responsible for filling the buffer with enough data if such data + // is available. If highWaterMark is 0 and we are not in the flowing mode + // we should _not_ attempt to buffer any extra data. We'll get more data + // when the stream consumer calls read() instead. + // - No data in the buffer, and the stream is in flowing mode. In this mode + // the loop below is responsible for ensuring read() is called. Failing to + // call read here would abort the flow and there's no other mechanism for + // continuing the flow if the stream consumer has just subscribed to the + // 'data' event. + // + // In addition to the above conditions to keep reading data, the following + // conditions prevent the data from being read: + // - The stream has ended (state.ended). + // - There is already a pending 'read' operation (state.reading). This is a + // case where the stream has called the implementation defined _read() + // method, but they are processing the call asynchronously and have _not_ + // called push() with new data. In this case we skip performing more + // read()s. The execution ends in this method again after the _read() ends + // up calling push() with more data. + while ( + !state.reading && + !state.ended && + (state.length < state.highWaterMark || (state.flowing && state.length === 0)) + ) { + const len = state.length + debug('maybeReadMore read 0') + stream.read(0) + if (len === state.length) + // Didn't get any data, stop spinning. + break + } + + state.readingMore = false +} // Abstract method. to be overridden in specific implementation classes. +// call cb(er, data) where data is <= n in length. +// for virtual (non-string, non-buffer) streams, "length" is somewhat +// arbitrary, and perhaps not very meaningful. + +Readable.prototype._read = function (n) { + throw new ERR_METHOD_NOT_IMPLEMENTED('_read()') +} + +Readable.prototype.pipe = function (dest, pipeOpts) { + const src = this + const state = this._readableState + + if (state.pipes.length === 1) { + if (!state.multiAwaitDrain) { + state.multiAwaitDrain = true + state.awaitDrainWriters = new SafeSet(state.awaitDrainWriters ? [state.awaitDrainWriters] : []) + } + } + + state.pipes.push(dest) + debug('pipe count=%d opts=%j', state.pipes.length, pipeOpts) + const doEnd = (!pipeOpts || pipeOpts.end !== false) && dest !== process.stdout && dest !== process.stderr + const endFn = doEnd ? onend : unpipe + if (state.endEmitted) process.nextTick(endFn) + else src.once('end', endFn) + dest.on('unpipe', onunpipe) + + function onunpipe(readable, unpipeInfo) { + debug('onunpipe') + + if (readable === src) { + if (unpipeInfo && unpipeInfo.hasUnpiped === false) { + unpipeInfo.hasUnpiped = true + cleanup() + } + } + } + + function onend() { + debug('onend') + dest.end() + } + + let ondrain + let cleanedUp = false + + function cleanup() { + debug('cleanup') // Cleanup event handlers once the pipe is broken. + + dest.removeListener('close', onclose) + dest.removeListener('finish', onfinish) + + if (ondrain) { + dest.removeListener('drain', ondrain) + } + + dest.removeListener('error', onerror) + dest.removeListener('unpipe', onunpipe) + src.removeListener('end', onend) + src.removeListener('end', unpipe) + src.removeListener('data', ondata) + cleanedUp = true // If the reader is waiting for a drain event from this + // specific writer, then it would cause it to never start + // flowing again. + // So, if this is awaiting a drain, then we just call it now. + // If we don't know, then assume that we are waiting for one. + + if (ondrain && state.awaitDrainWriters && (!dest._writableState || dest._writableState.needDrain)) ondrain() + } + + function pause() { + // If the user unpiped during `dest.write()`, it is possible + // to get stuck in a permanently paused state if that write + // also returned false. + // => Check whether `dest` is still a piping destination. + if (!cleanedUp) { + if (state.pipes.length === 1 && state.pipes[0] === dest) { + debug('false write response, pause', 0) + state.awaitDrainWriters = dest + state.multiAwaitDrain = false + } else if (state.pipes.length > 1 && state.pipes.includes(dest)) { + debug('false write response, pause', state.awaitDrainWriters.size) + state.awaitDrainWriters.add(dest) + } + + src.pause() + } + + if (!ondrain) { + // When the dest drains, it reduces the awaitDrain counter + // on the source. This would be more elegant with a .once() + // handler in flow(), but adding and removing repeatedly is + // too slow. + ondrain = pipeOnDrain(src, dest) + dest.on('drain', ondrain) + } + } + + src.on('data', ondata) + + function ondata(chunk) { + debug('ondata') + const ret = dest.write(chunk) + debug('dest.write', ret) + + if (ret === false) { + pause() + } + } // If the dest has an error, then stop piping into it. + // However, don't suppress the throwing behavior for this. + + function onerror(er) { + debug('onerror', er) + unpipe() + dest.removeListener('error', onerror) + + if (dest.listenerCount('error') === 0) { + const s = dest._writableState || dest._readableState + + if (s && !s.errorEmitted) { + // User incorrectly emitted 'error' directly on the stream. + errorOrDestroy(dest, er) + } else { + dest.emit('error', er) + } + } + } // Make sure our error handler is attached before userland ones. + + prependListener(dest, 'error', onerror) // Both close and finish should trigger unpipe, but only once. + + function onclose() { + dest.removeListener('finish', onfinish) + unpipe() + } + + dest.once('close', onclose) + + function onfinish() { + debug('onfinish') + dest.removeListener('close', onclose) + unpipe() + } + + dest.once('finish', onfinish) + + function unpipe() { + debug('unpipe') + src.unpipe(dest) + } // Tell the dest that it's being piped to. + + dest.emit('pipe', src) // Start the flow if it hasn't been started already. + + if (dest.writableNeedDrain === true) { + if (state.flowing) { + pause() + } + } else if (!state.flowing) { + debug('pipe resume') + src.resume() + } + + return dest +} + +function pipeOnDrain(src, dest) { + return function pipeOnDrainFunctionResult() { + const state = src._readableState // `ondrain` will call directly, + // `this` maybe not a reference to dest, + // so we use the real dest here. + + if (state.awaitDrainWriters === dest) { + debug('pipeOnDrain', 1) + state.awaitDrainWriters = null + } else if (state.multiAwaitDrain) { + debug('pipeOnDrain', state.awaitDrainWriters.size) + state.awaitDrainWriters.delete(dest) + } + + if ((!state.awaitDrainWriters || state.awaitDrainWriters.size === 0) && src.listenerCount('data')) { + src.resume() + } + } +} + +Readable.prototype.unpipe = function (dest) { + const state = this._readableState + const unpipeInfo = { + hasUnpiped: false + } // If we're not piping anywhere, then do nothing. + + if (state.pipes.length === 0) return this + + if (!dest) { + // remove all. + const dests = state.pipes + state.pipes = [] + this.pause() + + for (let i = 0; i < dests.length; i++) + dests[i].emit('unpipe', this, { + hasUnpiped: false + }) + + return this + } // Try to find the right one. + + const index = ArrayPrototypeIndexOf(state.pipes, dest) + if (index === -1) return this + state.pipes.splice(index, 1) + if (state.pipes.length === 0) this.pause() + dest.emit('unpipe', this, unpipeInfo) + return this +} // Set up data events if they are asked for +// Ensure readable listeners eventually get something. + +Readable.prototype.on = function (ev, fn) { + const res = Stream.prototype.on.call(this, ev, fn) + const state = this._readableState + + if (ev === 'data') { + // Update readableListening so that resume() may be a no-op + // a few lines down. This is needed to support once('readable'). + state.readableListening = this.listenerCount('readable') > 0 // Try start flowing on next tick if stream isn't explicitly paused. + + if (state.flowing !== false) this.resume() + } else if (ev === 'readable') { + if (!state.endEmitted && !state.readableListening) { + state.readableListening = state.needReadable = true + state.flowing = false + state.emittedReadable = false + debug('on readable', state.length, state.reading) + + if (state.length) { + emitReadable(this) + } else if (!state.reading) { + process.nextTick(nReadingNextTick, this) + } + } + } + + return res +} + +Readable.prototype.addListener = Readable.prototype.on + +Readable.prototype.removeListener = function (ev, fn) { + const res = Stream.prototype.removeListener.call(this, ev, fn) + + if (ev === 'readable') { + // We need to check if there is someone still listening to + // readable and reset the state. However this needs to happen + // after readable has been emitted but before I/O (nextTick) to + // support once('readable', fn) cycles. This means that calling + // resume within the same tick will have no + // effect. + process.nextTick(updateReadableListening, this) + } + + return res +} + +Readable.prototype.off = Readable.prototype.removeListener + +Readable.prototype.removeAllListeners = function (ev) { + const res = Stream.prototype.removeAllListeners.apply(this, arguments) + + if (ev === 'readable' || ev === undefined) { + // We need to check if there is someone still listening to + // readable and reset the state. However this needs to happen + // after readable has been emitted but before I/O (nextTick) to + // support once('readable', fn) cycles. This means that calling + // resume within the same tick will have no + // effect. + process.nextTick(updateReadableListening, this) + } + + return res +} + +function updateReadableListening(self) { + const state = self._readableState + state.readableListening = self.listenerCount('readable') > 0 + + if (state.resumeScheduled && state[kPaused] === false) { + // Flowing needs to be set to true now, otherwise + // the upcoming resume will not flow. + state.flowing = true // Crude way to check if we should resume. + } else if (self.listenerCount('data') > 0) { + self.resume() + } else if (!state.readableListening) { + state.flowing = null + } +} + +function nReadingNextTick(self) { + debug('readable nexttick read 0') + self.read(0) +} // pause() and resume() are remnants of the legacy readable stream API +// If the user uses them, then switch into old mode. + +Readable.prototype.resume = function () { + const state = this._readableState + + if (!state.flowing) { + debug('resume') // We flow only if there is no one listening + // for readable, but we still have to call + // resume(). + + state.flowing = !state.readableListening + resume(this, state) + } + + state[kPaused] = false + return this +} + +function resume(stream, state) { + if (!state.resumeScheduled) { + state.resumeScheduled = true + process.nextTick(resume_, stream, state) + } +} + +function resume_(stream, state) { + debug('resume', state.reading) + + if (!state.reading) { + stream.read(0) + } + + state.resumeScheduled = false + stream.emit('resume') + flow(stream) + if (state.flowing && !state.reading) stream.read(0) +} + +Readable.prototype.pause = function () { + debug('call pause flowing=%j', this._readableState.flowing) + + if (this._readableState.flowing !== false) { + debug('pause') + this._readableState.flowing = false + this.emit('pause') + } + + this._readableState[kPaused] = true + return this +} + +function flow(stream) { + const state = stream._readableState + debug('flow', state.flowing) + + while (state.flowing && stream.read() !== null); +} // Wrap an old-style stream as the async data source. +// This is *not* part of the readable stream interface. +// It is an ugly unfortunate mess of history. + +Readable.prototype.wrap = function (stream) { + let paused = false // TODO (ronag): Should this.destroy(err) emit + // 'error' on the wrapped stream? Would require + // a static factory method, e.g. Readable.wrap(stream). + + stream.on('data', (chunk) => { + if (!this.push(chunk) && stream.pause) { + paused = true + stream.pause() + } + }) + stream.on('end', () => { + this.push(null) + }) + stream.on('error', (err) => { + errorOrDestroy(this, err) + }) + stream.on('close', () => { + this.destroy() + }) + stream.on('destroy', () => { + this.destroy() + }) + + this._read = () => { + if (paused && stream.resume) { + paused = false + stream.resume() + } + } // Proxy all the other methods. Important when wrapping filters and duplexes. + + const streamKeys = ObjectKeys(stream) + + for (let j = 1; j < streamKeys.length; j++) { + const i = streamKeys[j] + + if (this[i] === undefined && typeof stream[i] === 'function') { + this[i] = stream[i].bind(stream) + } + } + + return this +} + +Readable.prototype[SymbolAsyncIterator] = function () { + return streamToAsyncIterator(this) +} + +Readable.prototype.iterator = function (options) { + if (options !== undefined) { + validateObject(options, 'options') + } + + return streamToAsyncIterator(this, options) +} + +function streamToAsyncIterator(stream, options) { + if (typeof stream.read !== 'function') { + stream = Readable.wrap(stream, { + objectMode: true + }) + } + + const iter = createAsyncIterator(stream, options) + iter.stream = stream + return iter +} + +async function* createAsyncIterator(stream, options) { + let callback = nop + + function next(resolve) { + if (this === stream) { + callback() + callback = nop + } else { + callback = resolve + } + } + + stream.on('readable', next) + let error + const cleanup = eos( + stream, + { + writable: false + }, + (err) => { + error = err ? aggregateTwoErrors(error, err) : null + callback() + callback = nop + } + ) + + try { + while (true) { + const chunk = stream.destroyed ? null : stream.read() + + if (chunk !== null) { + yield chunk + } else if (error) { + throw error + } else if (error === null) { + return + } else { + await new Promise(next) + } + } + } catch (err) { + error = aggregateTwoErrors(error, err) + throw error + } finally { + if ( + (error || (options === null || options === undefined ? undefined : options.destroyOnReturn) !== false) && + (error === undefined || stream._readableState.autoDestroy) + ) { + destroyImpl.destroyer(stream, null) + } else { + stream.off('readable', next) + cleanup() + } + } +} // Making it explicit these properties are not enumerable +// because otherwise some prototype manipulation in +// userland will fail. + +ObjectDefineProperties(Readable.prototype, { + readable: { + get() { + const r = this._readableState // r.readable === false means that this is part of a Duplex stream + // where the readable side was disabled upon construction. + // Compat. The user might manually disable readable side through + // deprecated setter. + + return !!r && r.readable !== false && !r.destroyed && !r.errorEmitted && !r.endEmitted + }, + + set(val) { + // Backwards compat. + if (this._readableState) { + this._readableState.readable = !!val + } + } + }, + readableDidRead: { + enumerable: false, + get: function () { + return this._readableState.dataEmitted + } + }, + readableAborted: { + enumerable: false, + get: function () { + return !!( + this._readableState.readable !== false && + (this._readableState.destroyed || this._readableState.errored) && + !this._readableState.endEmitted + ) + } + }, + readableHighWaterMark: { + enumerable: false, + get: function () { + return this._readableState.highWaterMark + } + }, + readableBuffer: { + enumerable: false, + get: function () { + return this._readableState && this._readableState.buffer + } + }, + readableFlowing: { + enumerable: false, + get: function () { + return this._readableState.flowing + }, + set: function (state) { + if (this._readableState) { + this._readableState.flowing = state + } + } + }, + readableLength: { + enumerable: false, + + get() { + return this._readableState.length + } + }, + readableObjectMode: { + enumerable: false, + + get() { + return this._readableState ? this._readableState.objectMode : false + } + }, + readableEncoding: { + enumerable: false, + + get() { + return this._readableState ? this._readableState.encoding : null + } + }, + errored: { + enumerable: false, + + get() { + return this._readableState ? this._readableState.errored : null + } + }, + closed: { + get() { + return this._readableState ? this._readableState.closed : false + } + }, + destroyed: { + enumerable: false, + + get() { + return this._readableState ? this._readableState.destroyed : false + }, + + set(value) { + // We ignore the value if the stream + // has not been initialized yet. + if (!this._readableState) { + return + } // Backward compatibility, the user is explicitly + // managing destroyed. + + this._readableState.destroyed = value + } + }, + readableEnded: { + enumerable: false, + + get() { + return this._readableState ? this._readableState.endEmitted : false + } + } +}) +ObjectDefineProperties(ReadableState.prototype, { + // Legacy getter for `pipesCount`. + pipesCount: { + get() { + return this.pipes.length + } + }, + // Legacy property for `paused`. + paused: { + get() { + return this[kPaused] !== false + }, + + set(value) { + this[kPaused] = !!value + } + } +}) // Exposed for testing purposes only. + +Readable._fromList = fromList // Pluck off n bytes from an array of buffers. +// Length is the combined lengths of all the buffers in the list. +// This function is designed to be inlinable, so please take care when making +// changes to the function body. + +function fromList(n, state) { + // nothing buffered. + if (state.length === 0) return null + let ret + if (state.objectMode) ret = state.buffer.shift() + else if (!n || n >= state.length) { + // Read it all, truncate the list. + if (state.decoder) ret = state.buffer.join('') + else if (state.buffer.length === 1) ret = state.buffer.first() + else ret = state.buffer.concat(state.length) + state.buffer.clear() + } else { + // read part of list. + ret = state.buffer.consume(n, state.decoder) + } + return ret +} + +function endReadable(stream) { + const state = stream._readableState + debug('endReadable', state.endEmitted) + + if (!state.endEmitted) { + state.ended = true + process.nextTick(endReadableNT, state, stream) + } +} + +function endReadableNT(state, stream) { + debug('endReadableNT', state.endEmitted, state.length) // Check that we didn't get one last unshift. + + if (!state.errored && !state.closeEmitted && !state.endEmitted && state.length === 0) { + state.endEmitted = true + stream.emit('end') + + if (stream.writable && stream.allowHalfOpen === false) { + process.nextTick(endWritableNT, stream) + } else if (state.autoDestroy) { + // In case of duplex streams we need a way to detect + // if the writable side is ready for autoDestroy as well. + const wState = stream._writableState + const autoDestroy = + !wState || + (wState.autoDestroy && // We don't expect the writable to ever 'finish' + // if writable is explicitly set to false. + (wState.finished || wState.writable === false)) + + if (autoDestroy) { + stream.destroy() + } + } + } +} + +function endWritableNT(stream) { + const writable = stream.writable && !stream.writableEnded && !stream.destroyed + + if (writable) { + stream.end() + } +} + +Readable.from = function (iterable, opts) { + return from(Readable, iterable, opts) +} + +let webStreamsAdapters // Lazy to avoid circular references + +function lazyWebStreams() { + if (webStreamsAdapters === undefined) webStreamsAdapters = {} + return webStreamsAdapters +} + +Readable.fromWeb = function (readableStream, options) { + return lazyWebStreams().newStreamReadableFromReadableStream(readableStream, options) +} + +Readable.toWeb = function (streamReadable) { + return lazyWebStreams().newReadableStreamFromStreamReadable(streamReadable) +} + +Readable.wrap = function (src, options) { + var _ref, _src$readableObjectMo + + return new Readable({ + objectMode: + (_ref = + (_src$readableObjectMo = src.readableObjectMode) !== null && _src$readableObjectMo !== undefined + ? _src$readableObjectMo + : src.objectMode) !== null && _ref !== undefined + ? _ref + : true, + ...options, + + destroy(err, callback) { + destroyImpl.destroyer(src, err) + callback(err) + } + }).wrap(src) +} diff --git a/server/libs/archiver/archiverUtils/readableStream/internal/streams/state.js b/server/libs/archiver/archiverUtils/readableStream/internal/streams/state.js new file mode 100644 index 000000000..e7fcebdde --- /dev/null +++ b/server/libs/archiver/archiverUtils/readableStream/internal/streams/state.js @@ -0,0 +1,33 @@ +'use strict' + +const { MathFloor, NumberIsInteger } = require('../../ours/primordials') + +const { ERR_INVALID_ARG_VALUE } = require('../../ours/errors').codes + +function highWaterMarkFrom(options, isDuplex, duplexKey) { + return options.highWaterMark != null ? options.highWaterMark : isDuplex ? options[duplexKey] : null +} + +function getDefaultHighWaterMark(objectMode) { + return objectMode ? 16 : 16 * 1024 +} + +function getHighWaterMark(state, options, duplexKey, isDuplex) { + const hwm = highWaterMarkFrom(options, isDuplex, duplexKey) + + if (hwm != null) { + if (!NumberIsInteger(hwm) || hwm < 0) { + const name = isDuplex ? `options.${duplexKey}` : 'options.highWaterMark' + throw new ERR_INVALID_ARG_VALUE(name, hwm) + } + + return MathFloor(hwm) + } // Default value + + return getDefaultHighWaterMark(state.objectMode) +} + +module.exports = { + getHighWaterMark, + getDefaultHighWaterMark +} diff --git a/server/libs/archiver/archiverUtils/readableStream/internal/streams/transform.js b/server/libs/archiver/archiverUtils/readableStream/internal/streams/transform.js new file mode 100644 index 000000000..5a34c250b --- /dev/null +++ b/server/libs/archiver/archiverUtils/readableStream/internal/streams/transform.js @@ -0,0 +1,175 @@ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. +// a transform stream is a readable/writable stream where you do +// something with the data. Sometimes it's called a "filter", +// but that's not a great name for it, since that implies a thing where +// some bits pass through, and others are simply ignored. (That would +// be a valid example of a transform, of course.) +// +// While the output is causally related to the input, it's not a +// necessarily symmetric or synchronous transformation. For example, +// a zlib stream might take multiple plain-text writes(), and then +// emit a single compressed chunk some time in the future. +// +// Here's how this works: +// +// The Transform stream has all the aspects of the readable and writable +// stream classes. When you write(chunk), that calls _write(chunk,cb) +// internally, and returns false if there's a lot of pending writes +// buffered up. When you call read(), that calls _read(n) until +// there's enough pending readable data buffered up. +// +// In a transform stream, the written data is placed in a buffer. When +// _read(n) is called, it transforms the queued up data, calling the +// buffered _write cb's as it consumes chunks. If consuming a single +// written chunk would result in multiple output chunks, then the first +// outputted bit calls the readcb, and subsequent chunks just go into +// the read buffer, and will cause it to emit 'readable' if necessary. +// +// This way, back-pressure is actually determined by the reading side, +// since _read has to be called to start processing a new chunk. However, +// a pathological inflate type of transform can cause excessive buffering +// here. For example, imagine a stream where every byte of input is +// interpreted as an integer from 0-255, and then results in that many +// bytes of output. Writing the 4 bytes {ff,ff,ff,ff} would result in +// 1kb of data being output. In this case, you could write a very small +// amount of input, and end up with a very large amount of output. In +// such a pathological inflating mechanism, there'd be no way to tell +// the system to stop doing the transform. A single 4MB write could +// cause the system to run out of memory. +// +// However, even in such a pathological case, only a single written chunk +// would be consumed, and then the rest would wait (un-transformed) until +// the results of the previous transformed chunk were consumed. +'use strict' + +const { ObjectSetPrototypeOf, Symbol } = require('../../ours/primordials') + +module.exports = Transform + +const { ERR_METHOD_NOT_IMPLEMENTED } = require('../../ours/errors').codes + +const Duplex = require('./duplex') + +ObjectSetPrototypeOf(Transform.prototype, Duplex.prototype) +ObjectSetPrototypeOf(Transform, Duplex) +const kCallback = Symbol('kCallback') + +function Transform(options) { + if (!(this instanceof Transform)) return new Transform(options) + Duplex.call(this, options) // We have implemented the _read method, and done the other things + // that Readable wants before the first _read call, so unset the + // sync guard flag. + + this._readableState.sync = false + this[kCallback] = null + + if (options) { + if (typeof options.transform === 'function') this._transform = options.transform + if (typeof options.flush === 'function') this._flush = options.flush + } // When the writable side finishes, then flush out anything remaining. + // Backwards compat. Some Transform streams incorrectly implement _final + // instead of or in addition to _flush. By using 'prefinish' instead of + // implementing _final we continue supporting this unfortunate use case. + + this.on('prefinish', prefinish) +} + +function final(cb) { + if (typeof this._flush === 'function' && !this.destroyed) { + this._flush((er, data) => { + if (er) { + if (cb) { + cb(er) + } else { + this.destroy(er) + } + + return + } + + if (data != null) { + this.push(data) + } + + this.push(null) + + if (cb) { + cb() + } + }) + } else { + this.push(null) + + if (cb) { + cb() + } + } +} + +function prefinish() { + if (this._final !== final) { + final.call(this) + } +} + +Transform.prototype._final = final + +Transform.prototype._transform = function (chunk, encoding, callback) { + throw new ERR_METHOD_NOT_IMPLEMENTED('_transform()') +} + +Transform.prototype._write = function (chunk, encoding, callback) { + const rState = this._readableState + const wState = this._writableState + const length = rState.length + + this._transform(chunk, encoding, (err, val) => { + if (err) { + callback(err) + return + } + + if (val != null) { + this.push(val) + } + + if ( + wState.ended || // Backwards compat. + length === rState.length || // Backwards compat. + rState.length < rState.highWaterMark || + rState.highWaterMark === 0 || + rState.length === 0 + ) { + callback() + } else { + this[kCallback] = callback + } + }) +} + +Transform.prototype._read = function () { + if (this[kCallback]) { + const callback = this[kCallback] + this[kCallback] = null + callback() + } +} diff --git a/server/libs/archiver/archiverUtils/readableStream/internal/streams/utils.js b/server/libs/archiver/archiverUtils/readableStream/internal/streams/utils.js new file mode 100644 index 000000000..b1aa7d817 --- /dev/null +++ b/server/libs/archiver/archiverUtils/readableStream/internal/streams/utils.js @@ -0,0 +1,328 @@ +'use strict' + +const { Symbol, SymbolAsyncIterator, SymbolIterator } = require('../../ours/primordials') + +const kDestroyed = Symbol('kDestroyed') +const kIsErrored = Symbol('kIsErrored') +const kIsReadable = Symbol('kIsReadable') +const kIsDisturbed = Symbol('kIsDisturbed') + +function isReadableNodeStream(obj, strict = false) { + var _obj$_readableState + + return !!( + ( + obj && + typeof obj.pipe === 'function' && + typeof obj.on === 'function' && + (!strict || (typeof obj.pause === 'function' && typeof obj.resume === 'function')) && + (!obj._writableState || + ((_obj$_readableState = obj._readableState) === null || _obj$_readableState === undefined + ? undefined + : _obj$_readableState.readable) !== false) && // Duplex + (!obj._writableState || obj._readableState) + ) // Writable has .pipe. + ) +} + +function isWritableNodeStream(obj) { + var _obj$_writableState + + return !!( + ( + obj && + typeof obj.write === 'function' && + typeof obj.on === 'function' && + (!obj._readableState || + ((_obj$_writableState = obj._writableState) === null || _obj$_writableState === undefined + ? undefined + : _obj$_writableState.writable) !== false) + ) // Duplex + ) +} + +function isDuplexNodeStream(obj) { + return !!( + obj && + typeof obj.pipe === 'function' && + obj._readableState && + typeof obj.on === 'function' && + typeof obj.write === 'function' + ) +} + +function isNodeStream(obj) { + return ( + obj && + (obj._readableState || + obj._writableState || + (typeof obj.write === 'function' && typeof obj.on === 'function') || + (typeof obj.pipe === 'function' && typeof obj.on === 'function')) + ) +} + +function isIterable(obj, isAsync) { + if (obj == null) return false + if (isAsync === true) return typeof obj[SymbolAsyncIterator] === 'function' + if (isAsync === false) return typeof obj[SymbolIterator] === 'function' + return typeof obj[SymbolAsyncIterator] === 'function' || typeof obj[SymbolIterator] === 'function' +} + +function isDestroyed(stream) { + if (!isNodeStream(stream)) return null + const wState = stream._writableState + const rState = stream._readableState + const state = wState || rState + return !!(stream.destroyed || stream[kDestroyed] || (state !== null && state !== undefined && state.destroyed)) +} // Have been end():d. + +function isWritableEnded(stream) { + if (!isWritableNodeStream(stream)) return null + if (stream.writableEnded === true) return true + const wState = stream._writableState + if (wState !== null && wState !== undefined && wState.errored) return false + if (typeof (wState === null || wState === undefined ? undefined : wState.ended) !== 'boolean') return null + return wState.ended +} // Have emitted 'finish'. + +function isWritableFinished(stream, strict) { + if (!isWritableNodeStream(stream)) return null + if (stream.writableFinished === true) return true + const wState = stream._writableState + if (wState !== null && wState !== undefined && wState.errored) return false + if (typeof (wState === null || wState === undefined ? undefined : wState.finished) !== 'boolean') return null + return !!(wState.finished || (strict === false && wState.ended === true && wState.length === 0)) +} // Have been push(null):d. + +function isReadableEnded(stream) { + if (!isReadableNodeStream(stream)) return null + if (stream.readableEnded === true) return true + const rState = stream._readableState + if (!rState || rState.errored) return false + if (typeof (rState === null || rState === undefined ? undefined : rState.ended) !== 'boolean') return null + return rState.ended +} // Have emitted 'end'. + +function isReadableFinished(stream, strict) { + if (!isReadableNodeStream(stream)) return null + const rState = stream._readableState + if (rState !== null && rState !== undefined && rState.errored) return false + if (typeof (rState === null || rState === undefined ? undefined : rState.endEmitted) !== 'boolean') return null + return !!(rState.endEmitted || (strict === false && rState.ended === true && rState.length === 0)) +} + +function isReadable(stream) { + if (stream && stream[kIsReadable] != null) return stream[kIsReadable] + if (typeof (stream === null || stream === undefined ? undefined : stream.readable) !== 'boolean') return null + if (isDestroyed(stream)) return false + return isReadableNodeStream(stream) && stream.readable && !isReadableFinished(stream) +} + +function isWritable(stream) { + if (typeof (stream === null || stream === undefined ? undefined : stream.writable) !== 'boolean') return null + if (isDestroyed(stream)) return false + return isWritableNodeStream(stream) && stream.writable && !isWritableEnded(stream) +} + +function isFinished(stream, opts) { + if (!isNodeStream(stream)) { + return null + } + + if (isDestroyed(stream)) { + return true + } + + if ((opts === null || opts === undefined ? undefined : opts.readable) !== false && isReadable(stream)) { + return false + } + + if ((opts === null || opts === undefined ? undefined : opts.writable) !== false && isWritable(stream)) { + return false + } + + return true +} + +function isWritableErrored(stream) { + var _stream$_writableStat, _stream$_writableStat2 + + if (!isNodeStream(stream)) { + return null + } + + if (stream.writableErrored) { + return stream.writableErrored + } + + return (_stream$_writableStat = + (_stream$_writableStat2 = stream._writableState) === null || _stream$_writableStat2 === undefined + ? undefined + : _stream$_writableStat2.errored) !== null && _stream$_writableStat !== undefined + ? _stream$_writableStat + : null +} + +function isReadableErrored(stream) { + var _stream$_readableStat, _stream$_readableStat2 + + if (!isNodeStream(stream)) { + return null + } + + if (stream.readableErrored) { + return stream.readableErrored + } + + return (_stream$_readableStat = + (_stream$_readableStat2 = stream._readableState) === null || _stream$_readableStat2 === undefined + ? undefined + : _stream$_readableStat2.errored) !== null && _stream$_readableStat !== undefined + ? _stream$_readableStat + : null +} + +function isClosed(stream) { + if (!isNodeStream(stream)) { + return null + } + + if (typeof stream.closed === 'boolean') { + return stream.closed + } + + const wState = stream._writableState + const rState = stream._readableState + + if ( + typeof (wState === null || wState === undefined ? undefined : wState.closed) === 'boolean' || + typeof (rState === null || rState === undefined ? undefined : rState.closed) === 'boolean' + ) { + return ( + (wState === null || wState === undefined ? undefined : wState.closed) || + (rState === null || rState === undefined ? undefined : rState.closed) + ) + } + + if (typeof stream._closed === 'boolean' && isOutgoingMessage(stream)) { + return stream._closed + } + + return null +} + +function isOutgoingMessage(stream) { + return ( + typeof stream._closed === 'boolean' && + typeof stream._defaultKeepAlive === 'boolean' && + typeof stream._removedConnection === 'boolean' && + typeof stream._removedContLen === 'boolean' + ) +} + +function isServerResponse(stream) { + return typeof stream._sent100 === 'boolean' && isOutgoingMessage(stream) +} + +function isServerRequest(stream) { + var _stream$req + + return ( + typeof stream._consuming === 'boolean' && + typeof stream._dumped === 'boolean' && + ((_stream$req = stream.req) === null || _stream$req === undefined ? undefined : _stream$req.upgradeOrConnect) === + undefined + ) +} + +function willEmitClose(stream) { + if (!isNodeStream(stream)) return null + const wState = stream._writableState + const rState = stream._readableState + const state = wState || rState + return ( + (!state && isServerResponse(stream)) || !!(state && state.autoDestroy && state.emitClose && state.closed === false) + ) +} + +function isDisturbed(stream) { + var _stream$kIsDisturbed + + return !!( + stream && + ((_stream$kIsDisturbed = stream[kIsDisturbed]) !== null && _stream$kIsDisturbed !== undefined + ? _stream$kIsDisturbed + : stream.readableDidRead || stream.readableAborted) + ) +} + +function isErrored(stream) { + var _ref, + _ref2, + _ref3, + _ref4, + _ref5, + _stream$kIsErrored, + _stream$_readableStat3, + _stream$_writableStat3, + _stream$_readableStat4, + _stream$_writableStat4 + + return !!( + stream && + ((_ref = + (_ref2 = + (_ref3 = + (_ref4 = + (_ref5 = + (_stream$kIsErrored = stream[kIsErrored]) !== null && _stream$kIsErrored !== undefined + ? _stream$kIsErrored + : stream.readableErrored) !== null && _ref5 !== undefined + ? _ref5 + : stream.writableErrored) !== null && _ref4 !== undefined + ? _ref4 + : (_stream$_readableStat3 = stream._readableState) === null || _stream$_readableStat3 === undefined + ? undefined + : _stream$_readableStat3.errorEmitted) !== null && _ref3 !== undefined + ? _ref3 + : (_stream$_writableStat3 = stream._writableState) === null || _stream$_writableStat3 === undefined + ? undefined + : _stream$_writableStat3.errorEmitted) !== null && _ref2 !== undefined + ? _ref2 + : (_stream$_readableStat4 = stream._readableState) === null || _stream$_readableStat4 === undefined + ? undefined + : _stream$_readableStat4.errored) !== null && _ref !== undefined + ? _ref + : (_stream$_writableStat4 = stream._writableState) === null || _stream$_writableStat4 === undefined + ? undefined + : _stream$_writableStat4.errored) + ) +} + +module.exports = { + kDestroyed, + isDisturbed, + kIsDisturbed, + isErrored, + kIsErrored, + isReadable, + kIsReadable, + isClosed, + isDestroyed, + isDuplexNodeStream, + isFinished, + isIterable, + isReadableNodeStream, + isReadableEnded, + isReadableFinished, + isReadableErrored, + isNodeStream, + isWritable, + isWritableNodeStream, + isWritableEnded, + isWritableFinished, + isWritableErrored, + isServerRequest, + isServerResponse, + willEmitClose +} diff --git a/server/libs/archiver/archiverUtils/readableStream/internal/streams/writable.js b/server/libs/archiver/archiverUtils/readableStream/internal/streams/writable.js new file mode 100644 index 000000000..ac97ec0d1 --- /dev/null +++ b/server/libs/archiver/archiverUtils/readableStream/internal/streams/writable.js @@ -0,0 +1,860 @@ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. +// A bit simpler than readable streams. +// Implement an async ._write(chunk, encoding, cb), and it'll handle all +// the drain event emission and buffering. +'use strict' + +const { + ArrayPrototypeSlice, + Error, + FunctionPrototypeSymbolHasInstance, + ObjectDefineProperty, + ObjectDefineProperties, + ObjectSetPrototypeOf, + StringPrototypeToLowerCase, + Symbol, + SymbolHasInstance +} = require('../../ours/primordials') + +module.exports = Writable +Writable.WritableState = WritableState + +const { EventEmitter: EE } = require('events') + +const Stream = require('./legacy').Stream + +const destroyImpl = require('./destroy') + +const { addAbortSignal } = require('./add-abort-signal') + +const { getHighWaterMark, getDefaultHighWaterMark } = require('./state') + +const { + ERR_INVALID_ARG_TYPE, + ERR_METHOD_NOT_IMPLEMENTED, + ERR_MULTIPLE_CALLBACK, + ERR_STREAM_CANNOT_PIPE, + ERR_STREAM_DESTROYED, + ERR_STREAM_ALREADY_FINISHED, + ERR_STREAM_NULL_VALUES, + ERR_STREAM_WRITE_AFTER_END, + ERR_UNKNOWN_ENCODING +} = require('../../ours/errors').codes + +const { errorOrDestroy } = destroyImpl +ObjectSetPrototypeOf(Writable.prototype, Stream.prototype) +ObjectSetPrototypeOf(Writable, Stream) + +function nop() {} + +const kOnFinished = Symbol('kOnFinished') + +function WritableState(options, stream, isDuplex) { + // Duplex streams are both readable and writable, but share + // the same options object. + // However, some cases require setting options to different + // values for the readable and the writable sides of the duplex stream, + // e.g. options.readableObjectMode vs. options.writableObjectMode, etc. + if (typeof isDuplex !== 'boolean') isDuplex = stream instanceof require('./duplex') // Object stream flag to indicate whether or not this stream + // contains buffers or objects. + + this.objectMode = !!(options && options.objectMode) + if (isDuplex) this.objectMode = this.objectMode || !!(options && options.writableObjectMode) // The point at which write() starts returning false + // Note: 0 is a valid value, means that we always return false if + // the entire buffer is not flushed immediately on write(). + + this.highWaterMark = options + ? getHighWaterMark(this, options, 'writableHighWaterMark', isDuplex) + : getDefaultHighWaterMark(false) // if _final has been called. + + this.finalCalled = false // drain event flag. + + this.needDrain = false // At the start of calling end() + + this.ending = false // When end() has been called, and returned. + + this.ended = false // When 'finish' is emitted. + + this.finished = false // Has it been destroyed + + this.destroyed = false // Should we decode strings into buffers before passing to _write? + // this is here so that some node-core streams can optimize string + // handling at a lower level. + + const noDecode = !!(options && options.decodeStrings === false) + this.decodeStrings = !noDecode // Crypto is kind of old and crusty. Historically, its default string + // encoding is 'binary' so we have to make this configurable. + // Everything else in the universe uses 'utf8', though. + + this.defaultEncoding = (options && options.defaultEncoding) || 'utf8' // Not an actual buffer we keep track of, but a measurement + // of how much we're waiting to get pushed to some underlying + // socket or file. + + this.length = 0 // A flag to see when we're in the middle of a write. + + this.writing = false // When true all writes will be buffered until .uncork() call. + + this.corked = 0 // A flag to be able to tell if the onwrite cb is called immediately, + // or on a later tick. We set this to true at first, because any + // actions that shouldn't happen until "later" should generally also + // not happen before the first write call. + + this.sync = true // A flag to know if we're processing previously buffered items, which + // may call the _write() callback in the same tick, so that we don't + // end up in an overlapped onwrite situation. + + this.bufferProcessing = false // The callback that's passed to _write(chunk, cb). + + this.onwrite = onwrite.bind(undefined, stream) // The callback that the user supplies to write(chunk, encoding, cb). + + this.writecb = null // The amount that is being written when _write is called. + + this.writelen = 0 // Storage for data passed to the afterWrite() callback in case of + // synchronous _write() completion. + + this.afterWriteTickInfo = null + resetBuffer(this) // Number of pending user-supplied write callbacks + // this must be 0 before 'finish' can be emitted. + + this.pendingcb = 0 // Stream is still being constructed and cannot be + // destroyed until construction finished or failed. + // Async construction is opt in, therefore we start as + // constructed. + + this.constructed = true // Emit prefinish if the only thing we're waiting for is _write cbs + // This is relevant for synchronous Transform streams. + + this.prefinished = false // True if the error was already emitted and should not be thrown again. + + this.errorEmitted = false // Should close be emitted on destroy. Defaults to true. + + this.emitClose = !options || options.emitClose !== false // Should .destroy() be called after 'finish' (and potentially 'end'). + + this.autoDestroy = !options || options.autoDestroy !== false // Indicates whether the stream has errored. When true all write() calls + // should return false. This is needed since when autoDestroy + // is disabled we need a way to tell whether the stream has failed. + + this.errored = null // Indicates whether the stream has finished destroying. + + this.closed = false // True if close has been emitted or would have been emitted + // depending on emitClose. + + this.closeEmitted = false + this[kOnFinished] = [] +} + +function resetBuffer(state) { + state.buffered = [] + state.bufferedIndex = 0 + state.allBuffers = true + state.allNoop = true +} + +WritableState.prototype.getBuffer = function getBuffer() { + return ArrayPrototypeSlice(this.buffered, this.bufferedIndex) +} + +ObjectDefineProperty(WritableState.prototype, 'bufferedRequestCount', { + get() { + return this.buffered.length - this.bufferedIndex + } +}) + +function Writable(options) { + // Writable ctor is applied to Duplexes, too. + // `realHasInstance` is necessary because using plain `instanceof` + // would return false, as no `_writableState` property is attached. + // Trying to use the custom `instanceof` for Writable here will also break the + // Node.js LazyTransform implementation, which has a non-trivial getter for + // `_writableState` that would lead to infinite recursion. + // Checking for a Stream.Duplex instance is faster here instead of inside + // the WritableState constructor, at least with V8 6.5. + const isDuplex = this instanceof require('./duplex') + + if (!isDuplex && !FunctionPrototypeSymbolHasInstance(Writable, this)) return new Writable(options) + this._writableState = new WritableState(options, this, isDuplex) + + if (options) { + if (typeof options.write === 'function') this._write = options.write + if (typeof options.writev === 'function') this._writev = options.writev + if (typeof options.destroy === 'function') this._destroy = options.destroy + if (typeof options.final === 'function') this._final = options.final + if (typeof options.construct === 'function') this._construct = options.construct + if (options.signal) addAbortSignal(options.signal, this) + } + + Stream.call(this, options) + destroyImpl.construct(this, () => { + const state = this._writableState + + if (!state.writing) { + clearBuffer(this, state) + } + + finishMaybe(this, state) + }) +} + +ObjectDefineProperty(Writable, SymbolHasInstance, { + value: function (object) { + if (FunctionPrototypeSymbolHasInstance(this, object)) return true + if (this !== Writable) return false + return object && object._writableState instanceof WritableState + } +}) // Otherwise people can pipe Writable streams, which is just wrong. + +Writable.prototype.pipe = function () { + errorOrDestroy(this, new ERR_STREAM_CANNOT_PIPE()) +} + +function _write(stream, chunk, encoding, cb) { + const state = stream._writableState + + if (typeof encoding === 'function') { + cb = encoding + encoding = state.defaultEncoding + } else { + if (!encoding) encoding = state.defaultEncoding + else if (encoding !== 'buffer' && !Buffer.isEncoding(encoding)) throw new ERR_UNKNOWN_ENCODING(encoding) + if (typeof cb !== 'function') cb = nop + } + + if (chunk === null) { + throw new ERR_STREAM_NULL_VALUES() + } else if (!state.objectMode) { + if (typeof chunk === 'string') { + if (state.decodeStrings !== false) { + chunk = Buffer.from(chunk, encoding) + encoding = 'buffer' + } + } else if (chunk instanceof Buffer) { + encoding = 'buffer' + } else if (Stream._isUint8Array(chunk)) { + chunk = Stream._uint8ArrayToBuffer(chunk) + encoding = 'buffer' + } else { + throw new ERR_INVALID_ARG_TYPE('chunk', ['string', 'Buffer', 'Uint8Array'], chunk) + } + } + + let err + + if (state.ending) { + err = new ERR_STREAM_WRITE_AFTER_END() + } else if (state.destroyed) { + err = new ERR_STREAM_DESTROYED('write') + } + + if (err) { + process.nextTick(cb, err) + errorOrDestroy(stream, err, true) + return err + } + + state.pendingcb++ + return writeOrBuffer(stream, state, chunk, encoding, cb) +} + +Writable.prototype.write = function (chunk, encoding, cb) { + return _write(this, chunk, encoding, cb) === true +} + +Writable.prototype.cork = function () { + this._writableState.corked++ +} + +Writable.prototype.uncork = function () { + const state = this._writableState + + if (state.corked) { + state.corked-- + if (!state.writing) clearBuffer(this, state) + } +} + +Writable.prototype.setDefaultEncoding = function setDefaultEncoding(encoding) { + // node::ParseEncoding() requires lower case. + if (typeof encoding === 'string') encoding = StringPrototypeToLowerCase(encoding) + if (!Buffer.isEncoding(encoding)) throw new ERR_UNKNOWN_ENCODING(encoding) + this._writableState.defaultEncoding = encoding + return this +} // If we're already writing something, then just put this +// in the queue, and wait our turn. Otherwise, call _write +// If we return false, then we need a drain event, so set that flag. + +function writeOrBuffer(stream, state, chunk, encoding, callback) { + const len = state.objectMode ? 1 : chunk.length + state.length += len // stream._write resets state.length + + const ret = state.length < state.highWaterMark // We must ensure that previous needDrain will not be reset to false. + + if (!ret) state.needDrain = true + + if (state.writing || state.corked || state.errored || !state.constructed) { + state.buffered.push({ + chunk, + encoding, + callback + }) + + if (state.allBuffers && encoding !== 'buffer') { + state.allBuffers = false + } + + if (state.allNoop && callback !== nop) { + state.allNoop = false + } + } else { + state.writelen = len + state.writecb = callback + state.writing = true + state.sync = true + + stream._write(chunk, encoding, state.onwrite) + + state.sync = false + } // Return false if errored or destroyed in order to break + // any synchronous while(stream.write(data)) loops. + + return ret && !state.errored && !state.destroyed +} + +function doWrite(stream, state, writev, len, chunk, encoding, cb) { + state.writelen = len + state.writecb = cb + state.writing = true + state.sync = true + if (state.destroyed) state.onwrite(new ERR_STREAM_DESTROYED('write')) + else if (writev) stream._writev(chunk, state.onwrite) + else stream._write(chunk, encoding, state.onwrite) + state.sync = false +} + +function onwriteError(stream, state, er, cb) { + --state.pendingcb + cb(er) // Ensure callbacks are invoked even when autoDestroy is + // not enabled. Passing `er` here doesn't make sense since + // it's related to one specific write, not to the buffered + // writes. + + errorBuffer(state) // This can emit error, but error must always follow cb. + + errorOrDestroy(stream, er) +} + +function onwrite(stream, er) { + const state = stream._writableState + const sync = state.sync + const cb = state.writecb + + if (typeof cb !== 'function') { + errorOrDestroy(stream, new ERR_MULTIPLE_CALLBACK()) + return + } + + state.writing = false + state.writecb = null + state.length -= state.writelen + state.writelen = 0 + + if (er) { + // Avoid V8 leak, https://github.com/nodejs/node/pull/34103#issuecomment-652002364 + er.stack // eslint-disable-line no-unused-expressions + + if (!state.errored) { + state.errored = er + } // In case of duplex streams we need to notify the readable side of the + // error. + + if (stream._readableState && !stream._readableState.errored) { + stream._readableState.errored = er + } + + if (sync) { + process.nextTick(onwriteError, stream, state, er, cb) + } else { + onwriteError(stream, state, er, cb) + } + } else { + if (state.buffered.length > state.bufferedIndex) { + clearBuffer(stream, state) + } + + if (sync) { + // It is a common case that the callback passed to .write() is always + // the same. In that case, we do not schedule a new nextTick(), but + // rather just increase a counter, to improve performance and avoid + // memory allocations. + if (state.afterWriteTickInfo !== null && state.afterWriteTickInfo.cb === cb) { + state.afterWriteTickInfo.count++ + } else { + state.afterWriteTickInfo = { + count: 1, + cb, + stream, + state + } + process.nextTick(afterWriteTick, state.afterWriteTickInfo) + } + } else { + afterWrite(stream, state, 1, cb) + } + } +} + +function afterWriteTick({ stream, state, count, cb }) { + state.afterWriteTickInfo = null + return afterWrite(stream, state, count, cb) +} + +function afterWrite(stream, state, count, cb) { + const needDrain = !state.ending && !stream.destroyed && state.length === 0 && state.needDrain + + if (needDrain) { + state.needDrain = false + stream.emit('drain') + } + + while (count-- > 0) { + state.pendingcb-- + cb() + } + + if (state.destroyed) { + errorBuffer(state) + } + + finishMaybe(stream, state) +} // If there's something in the buffer waiting, then invoke callbacks. + +function errorBuffer(state) { + if (state.writing) { + return + } + + for (let n = state.bufferedIndex; n < state.buffered.length; ++n) { + var _state$errored + + const { chunk, callback } = state.buffered[n] + const len = state.objectMode ? 1 : chunk.length + state.length -= len + callback( + (_state$errored = state.errored) !== null && _state$errored !== undefined + ? _state$errored + : new ERR_STREAM_DESTROYED('write') + ) + } + + const onfinishCallbacks = state[kOnFinished].splice(0) + + for (let i = 0; i < onfinishCallbacks.length; i++) { + var _state$errored2 + + onfinishCallbacks[i]( + (_state$errored2 = state.errored) !== null && _state$errored2 !== undefined + ? _state$errored2 + : new ERR_STREAM_DESTROYED('end') + ) + } + + resetBuffer(state) +} // If there's something in the buffer waiting, then process it. + +function clearBuffer(stream, state) { + if (state.corked || state.bufferProcessing || state.destroyed || !state.constructed) { + return + } + + const { buffered, bufferedIndex, objectMode } = state + const bufferedLength = buffered.length - bufferedIndex + + if (!bufferedLength) { + return + } + + let i = bufferedIndex + state.bufferProcessing = true + + if (bufferedLength > 1 && stream._writev) { + state.pendingcb -= bufferedLength - 1 + const callback = state.allNoop + ? nop + : (err) => { + for (let n = i; n < buffered.length; ++n) { + buffered[n].callback(err) + } + } // Make a copy of `buffered` if it's going to be used by `callback` above, + // since `doWrite` will mutate the array. + + const chunks = state.allNoop && i === 0 ? buffered : ArrayPrototypeSlice(buffered, i) + chunks.allBuffers = state.allBuffers + doWrite(stream, state, true, state.length, chunks, '', callback) + resetBuffer(state) + } else { + do { + const { chunk, encoding, callback } = buffered[i] + buffered[i++] = null + const len = objectMode ? 1 : chunk.length + doWrite(stream, state, false, len, chunk, encoding, callback) + } while (i < buffered.length && !state.writing) + + if (i === buffered.length) { + resetBuffer(state) + } else if (i > 256) { + buffered.splice(0, i) + state.bufferedIndex = 0 + } else { + state.bufferedIndex = i + } + } + + state.bufferProcessing = false +} + +Writable.prototype._write = function (chunk, encoding, cb) { + if (this._writev) { + this._writev( + [ + { + chunk, + encoding + } + ], + cb + ) + } else { + throw new ERR_METHOD_NOT_IMPLEMENTED('_write()') + } +} + +Writable.prototype._writev = null + +Writable.prototype.end = function (chunk, encoding, cb) { + const state = this._writableState + + if (typeof chunk === 'function') { + cb = chunk + chunk = null + encoding = null + } else if (typeof encoding === 'function') { + cb = encoding + encoding = null + } + + let err + + if (chunk !== null && chunk !== undefined) { + const ret = _write(this, chunk, encoding) + + if (ret instanceof Error) { + err = ret + } + } // .end() fully uncorks. + + if (state.corked) { + state.corked = 1 + this.uncork() + } + + if (err) { + // Do nothing... + } else if (!state.errored && !state.ending) { + // This is forgiving in terms of unnecessary calls to end() and can hide + // logic errors. However, usually such errors are harmless and causing a + // hard error can be disproportionately destructive. It is not always + // trivial for the user to determine whether end() needs to be called + // or not. + state.ending = true + finishMaybe(this, state, true) + state.ended = true + } else if (state.finished) { + err = new ERR_STREAM_ALREADY_FINISHED('end') + } else if (state.destroyed) { + err = new ERR_STREAM_DESTROYED('end') + } + + if (typeof cb === 'function') { + if (err || state.finished) { + process.nextTick(cb, err) + } else { + state[kOnFinished].push(cb) + } + } + + return this +} + +function needFinish(state) { + return ( + state.ending && + !state.destroyed && + state.constructed && + state.length === 0 && + !state.errored && + state.buffered.length === 0 && + !state.finished && + !state.writing && + !state.errorEmitted && + !state.closeEmitted + ) +} + +function callFinal(stream, state) { + let called = false + + function onFinish(err) { + if (called) { + errorOrDestroy(stream, err !== null && err !== undefined ? err : ERR_MULTIPLE_CALLBACK()) + return + } + + called = true + state.pendingcb-- + + if (err) { + const onfinishCallbacks = state[kOnFinished].splice(0) + + for (let i = 0; i < onfinishCallbacks.length; i++) { + onfinishCallbacks[i](err) + } + + errorOrDestroy(stream, err, state.sync) + } else if (needFinish(state)) { + state.prefinished = true + stream.emit('prefinish') // Backwards compat. Don't check state.sync here. + // Some streams assume 'finish' will be emitted + // asynchronously relative to _final callback. + + state.pendingcb++ + process.nextTick(finish, stream, state) + } + } + + state.sync = true + state.pendingcb++ + + try { + stream._final(onFinish) + } catch (err) { + onFinish(err) + } + + state.sync = false +} + +function prefinish(stream, state) { + if (!state.prefinished && !state.finalCalled) { + if (typeof stream._final === 'function' && !state.destroyed) { + state.finalCalled = true + callFinal(stream, state) + } else { + state.prefinished = true + stream.emit('prefinish') + } + } +} + +function finishMaybe(stream, state, sync) { + if (needFinish(state)) { + prefinish(stream, state) + + if (state.pendingcb === 0) { + if (sync) { + state.pendingcb++ + process.nextTick( + (stream, state) => { + if (needFinish(state)) { + finish(stream, state) + } else { + state.pendingcb-- + } + }, + stream, + state + ) + } else if (needFinish(state)) { + state.pendingcb++ + finish(stream, state) + } + } + } +} + +function finish(stream, state) { + state.pendingcb-- + state.finished = true + const onfinishCallbacks = state[kOnFinished].splice(0) + + for (let i = 0; i < onfinishCallbacks.length; i++) { + onfinishCallbacks[i]() + } + + stream.emit('finish') + + if (state.autoDestroy) { + // In case of duplex streams we need a way to detect + // if the readable side is ready for autoDestroy as well. + const rState = stream._readableState + const autoDestroy = + !rState || + (rState.autoDestroy && // We don't expect the readable to ever 'end' + // if readable is explicitly set to false. + (rState.endEmitted || rState.readable === false)) + + if (autoDestroy) { + stream.destroy() + } + } +} + +ObjectDefineProperties(Writable.prototype, { + closed: { + get() { + return this._writableState ? this._writableState.closed : false + } + }, + destroyed: { + get() { + return this._writableState ? this._writableState.destroyed : false + }, + + set(value) { + // Backward compatibility, the user is explicitly managing destroyed. + if (this._writableState) { + this._writableState.destroyed = value + } + } + }, + writable: { + get() { + const w = this._writableState // w.writable === false means that this is part of a Duplex stream + // where the writable side was disabled upon construction. + // Compat. The user might manually disable writable side through + // deprecated setter. + + return !!w && w.writable !== false && !w.destroyed && !w.errored && !w.ending && !w.ended + }, + + set(val) { + // Backwards compatible. + if (this._writableState) { + this._writableState.writable = !!val + } + } + }, + writableFinished: { + get() { + return this._writableState ? this._writableState.finished : false + } + }, + writableObjectMode: { + get() { + return this._writableState ? this._writableState.objectMode : false + } + }, + writableBuffer: { + get() { + return this._writableState && this._writableState.getBuffer() + } + }, + writableEnded: { + get() { + return this._writableState ? this._writableState.ending : false + } + }, + writableNeedDrain: { + get() { + const wState = this._writableState + if (!wState) return false + return !wState.destroyed && !wState.ending && wState.needDrain + } + }, + writableHighWaterMark: { + get() { + return this._writableState && this._writableState.highWaterMark + } + }, + writableCorked: { + get() { + return this._writableState ? this._writableState.corked : 0 + } + }, + writableLength: { + get() { + return this._writableState && this._writableState.length + } + }, + errored: { + enumerable: false, + + get() { + return this._writableState ? this._writableState.errored : null + } + }, + writableAborted: { + enumerable: false, + get: function () { + return !!( + this._writableState.writable !== false && + (this._writableState.destroyed || this._writableState.errored) && + !this._writableState.finished + ) + } + } +}) +const destroy = destroyImpl.destroy + +Writable.prototype.destroy = function (err, cb) { + const state = this._writableState // Invoke pending callbacks. + + if (!state.destroyed && (state.bufferedIndex < state.buffered.length || state[kOnFinished].length)) { + process.nextTick(errorBuffer, state) + } + + destroy.call(this, err, cb) + return this +} + +Writable.prototype._undestroy = destroyImpl.undestroy + +Writable.prototype._destroy = function (err, cb) { + cb(err) +} + +Writable.prototype[EE.captureRejectionSymbol] = function (err) { + this.destroy(err) +} + +let webStreamsAdapters // Lazy to avoid circular references + +function lazyWebStreams() { + if (webStreamsAdapters === undefined) webStreamsAdapters = {} + return webStreamsAdapters +} + +Writable.fromWeb = function (writableStream, options) { + return lazyWebStreams().newStreamWritableFromWritableStream(writableStream, options) +} + +Writable.toWeb = function (streamWritable) { + return lazyWebStreams().newWritableStreamFromStreamWritable(streamWritable) +} diff --git a/server/libs/archiver/archiverUtils/readableStream/internal/validators.js b/server/libs/archiver/archiverUtils/readableStream/internal/validators.js new file mode 100644 index 000000000..11689d2ba --- /dev/null +++ b/server/libs/archiver/archiverUtils/readableStream/internal/validators.js @@ -0,0 +1,246 @@ +'use strict' + +const { + ArrayIsArray, + ArrayPrototypeIncludes, + ArrayPrototypeJoin, + ArrayPrototypeMap, + NumberIsInteger, + NumberMAX_SAFE_INTEGER, + NumberMIN_SAFE_INTEGER, + NumberParseInt, + RegExpPrototypeTest, + String, + StringPrototypeToUpperCase, + StringPrototypeTrim +} = require('../ours/primordials') + +const { + hideStackFrames, + codes: { ERR_SOCKET_BAD_PORT, ERR_INVALID_ARG_TYPE, ERR_INVALID_ARG_VALUE, ERR_OUT_OF_RANGE, ERR_UNKNOWN_SIGNAL } +} = require('../ours/errors') + +const { normalizeEncoding } = require('../ours/util') + +const { isAsyncFunction, isArrayBufferView } = require('../ours/util').types + +const signals = {} + +function isInt32(value) { + return value === (value | 0) +} + +function isUint32(value) { + return value === value >>> 0 +} + +const octalReg = /^[0-7]+$/ +const modeDesc = 'must be a 32-bit unsigned integer or an octal string' +/** + * Parse and validate values that will be converted into mode_t (the S_* + * constants). Only valid numbers and octal strings are allowed. They could be + * converted to 32-bit unsigned integers or non-negative signed integers in the + * C++ land, but any value higher than 0o777 will result in platform-specific + * behaviors. + * + * @param {*} value Values to be validated + * @param {string} name Name of the argument + * @param {number} [def] If specified, will be returned for invalid values + * @returns {number} + */ + +function parseFileMode(value, name, def) { + if (typeof value === 'undefined') { + value = def + } + + if (typeof value === 'string') { + if (!RegExpPrototypeTest(octalReg, value)) { + throw new ERR_INVALID_ARG_VALUE(name, value, modeDesc) + } + + value = NumberParseInt(value, 8) + } + + validateInt32(value, name, 0, 2 ** 32 - 1) + return value +} + +const validateInteger = hideStackFrames((value, name, min = NumberMIN_SAFE_INTEGER, max = NumberMAX_SAFE_INTEGER) => { + if (typeof value !== 'number') throw new ERR_INVALID_ARG_TYPE(name, 'number', value) + if (!NumberIsInteger(value)) throw new ERR_OUT_OF_RANGE(name, 'an integer', value) + if (value < min || value > max) throw new ERR_OUT_OF_RANGE(name, `>= ${min} && <= ${max}`, value) +}) +const validateInt32 = hideStackFrames((value, name, min = -2147483648, max = 2147483647) => { + // The defaults for min and max correspond to the limits of 32-bit integers. + if (typeof value !== 'number') { + throw new ERR_INVALID_ARG_TYPE(name, 'number', value) + } + + if (!isInt32(value)) { + if (!NumberIsInteger(value)) { + throw new ERR_OUT_OF_RANGE(name, 'an integer', value) + } + + throw new ERR_OUT_OF_RANGE(name, `>= ${min} && <= ${max}`, value) + } + + if (value < min || value > max) { + throw new ERR_OUT_OF_RANGE(name, `>= ${min} && <= ${max}`, value) + } +}) +const validateUint32 = hideStackFrames((value, name, positive) => { + if (typeof value !== 'number') { + throw new ERR_INVALID_ARG_TYPE(name, 'number', value) + } + + if (!isUint32(value)) { + if (!NumberIsInteger(value)) { + throw new ERR_OUT_OF_RANGE(name, 'an integer', value) + } + + const min = positive ? 1 : 0 // 2 ** 32 === 4294967296 + + throw new ERR_OUT_OF_RANGE(name, `>= ${min} && < 4294967296`, value) + } + + if (positive && value === 0) { + throw new ERR_OUT_OF_RANGE(name, '>= 1 && < 4294967296', value) + } +}) + +function validateString(value, name) { + if (typeof value !== 'string') throw new ERR_INVALID_ARG_TYPE(name, 'string', value) +} + +function validateNumber(value, name) { + if (typeof value !== 'number') throw new ERR_INVALID_ARG_TYPE(name, 'number', value) +} + +const validateOneOf = hideStackFrames((value, name, oneOf) => { + if (!ArrayPrototypeIncludes(oneOf, value)) { + const allowed = ArrayPrototypeJoin( + ArrayPrototypeMap(oneOf, (v) => (typeof v === 'string' ? `'${v}'` : String(v))), + ', ' + ) + const reason = 'must be one of: ' + allowed + throw new ERR_INVALID_ARG_VALUE(name, value, reason) + } +}) + +function validateBoolean(value, name) { + if (typeof value !== 'boolean') throw new ERR_INVALID_ARG_TYPE(name, 'boolean', value) +} +/** + * @param {unknown} value + * @param {string} name + * @param {{ + * allowArray?: boolean, + * allowFunction?: boolean, + * nullable?: boolean + * }} [options] + */ + +const validateObject = hideStackFrames((value, name, options) => { + const useDefaultOptions = options == null + const allowArray = useDefaultOptions ? false : options.allowArray + const allowFunction = useDefaultOptions ? false : options.allowFunction + const nullable = useDefaultOptions ? false : options.nullable + + if ( + (!nullable && value === null) || + (!allowArray && ArrayIsArray(value)) || + (typeof value !== 'object' && (!allowFunction || typeof value !== 'function')) + ) { + throw new ERR_INVALID_ARG_TYPE(name, 'Object', value) + } +}) +const validateArray = hideStackFrames((value, name, minLength = 0) => { + if (!ArrayIsArray(value)) { + throw new ERR_INVALID_ARG_TYPE(name, 'Array', value) + } + + if (value.length < minLength) { + const reason = `must be longer than ${minLength}` + throw new ERR_INVALID_ARG_VALUE(name, value, reason) + } +}) + +function validateSignalName(signal, name = 'signal') { + validateString(signal, name) + + if (signals[signal] === undefined) { + if (signals[StringPrototypeToUpperCase(signal)] !== undefined) { + throw new ERR_UNKNOWN_SIGNAL(signal + ' (signals must use all capital letters)') + } + + throw new ERR_UNKNOWN_SIGNAL(signal) + } +} + +const validateBuffer = hideStackFrames((buffer, name = 'buffer') => { + if (!isArrayBufferView(buffer)) { + throw new ERR_INVALID_ARG_TYPE(name, ['Buffer', 'TypedArray', 'DataView'], buffer) + } +}) + +function validateEncoding(data, encoding) { + const normalizedEncoding = normalizeEncoding(encoding) + const length = data.length + + if (normalizedEncoding === 'hex' && length % 2 !== 0) { + throw new ERR_INVALID_ARG_VALUE('encoding', encoding, `is invalid for data of length ${length}`) + } +} // Check that the port number is not NaN when coerced to a number, +// is an integer and that it falls within the legal range of port numbers. + +function validatePort(port, name = 'Port', allowZero = true) { + if ( + (typeof port !== 'number' && typeof port !== 'string') || + (typeof port === 'string' && StringPrototypeTrim(port).length === 0) || + +port !== +port >>> 0 || + port > 0xffff || + (port === 0 && !allowZero) + ) { + throw new ERR_SOCKET_BAD_PORT(name, port, allowZero) + } + + return port | 0 +} + +const validateAbortSignal = hideStackFrames((signal, name) => { + if (signal !== undefined && (signal === null || typeof signal !== 'object' || !('aborted' in signal))) { + throw new ERR_INVALID_ARG_TYPE(name, 'AbortSignal', signal) + } +}) +const validateFunction = hideStackFrames((value, name) => { + if (typeof value !== 'function') throw new ERR_INVALID_ARG_TYPE(name, 'Function', value) +}) +const validatePlainFunction = hideStackFrames((value, name) => { + if (typeof value !== 'function' || isAsyncFunction(value)) throw new ERR_INVALID_ARG_TYPE(name, 'Function', value) +}) +const validateUndefined = hideStackFrames((value, name) => { + if (value !== undefined) throw new ERR_INVALID_ARG_TYPE(name, 'undefined', value) +}) +module.exports = { + isInt32, + isUint32, + parseFileMode, + validateArray, + validateBoolean, + validateBuffer, + validateEncoding, + validateFunction, + validateInt32, + validateInteger, + validateNumber, + validateObject, + validateOneOf, + validatePlainFunction, + validatePort, + validateSignalName, + validateString, + validateUint32, + validateUndefined, + validateAbortSignal +} diff --git a/server/libs/archiver/archiverUtils/readableStream/ours/browser.js b/server/libs/archiver/archiverUtils/readableStream/ours/browser.js new file mode 100644 index 000000000..7083fb31e --- /dev/null +++ b/server/libs/archiver/archiverUtils/readableStream/ours/browser.js @@ -0,0 +1,36 @@ +'use strict' + +const CustomStream = require('../stream') + +const promises = require('../stream/promises') + +const originalDestroy = CustomStream.Readable.destroy +module.exports = CustomStream.Readable // Explicit export naming is needed for ESM + +module.exports._uint8ArrayToBuffer = CustomStream._uint8ArrayToBuffer +module.exports._isUint8Array = CustomStream._isUint8Array +module.exports.isDisturbed = CustomStream.isDisturbed +module.exports.isErrored = CustomStream.isErrored +module.exports.isReadable = CustomStream.isReadable +module.exports.Readable = CustomStream.Readable +module.exports.Writable = CustomStream.Writable +module.exports.Duplex = CustomStream.Duplex +module.exports.Transform = CustomStream.Transform +module.exports.PassThrough = CustomStream.PassThrough +module.exports.addAbortSignal = CustomStream.addAbortSignal +module.exports.finished = CustomStream.finished +module.exports.destroy = CustomStream.destroy +module.exports.destroy = originalDestroy +module.exports.pipeline = CustomStream.pipeline +module.exports.compose = CustomStream.compose +Object.defineProperty(CustomStream, 'promises', { + configurable: true, + enumerable: true, + + get() { + return promises + } +}) +module.exports.Stream = CustomStream.Stream // Allow default importing + +module.exports.default = module.exports diff --git a/server/libs/archiver/archiverUtils/readableStream/ours/errors.js b/server/libs/archiver/archiverUtils/readableStream/ours/errors.js new file mode 100644 index 000000000..fab32d254 --- /dev/null +++ b/server/libs/archiver/archiverUtils/readableStream/ours/errors.js @@ -0,0 +1,380 @@ +'use strict' + +const { format, inspect, AggregateError: CustomAggregateError } = require('./util') +/* + This file is a reduced and adapted version of the main lib/internal/errors.js file defined at + + https://github.com/nodejs/node/blob/master/lib/internal/errors.js + + Don't try to replace with the original file and keep it up to date (starting from E(...) definitions) + with the upstream file. +*/ + +const AggregateError = globalThis.AggregateError || CustomAggregateError +const kIsNodeError = Symbol('kIsNodeError') +const kTypes = [ + 'string', + 'function', + 'number', + 'object', // Accept 'Function' and 'Object' as alternative to the lower cased version. + 'Function', + 'Object', + 'boolean', + 'bigint', + 'symbol' +] +const classRegExp = /^([A-Z][a-z0-9]*)+$/ +const nodeInternalPrefix = '__node_internal_' +const codes = {} + +function assert(value, message) { + if (!value) { + throw new codes.ERR_INTERNAL_ASSERTION(message) + } +} // Only use this for integers! Decimal numbers do not work with this function. + +function addNumericalSeparator(val) { + let res = '' + let i = val.length + const start = val[0] === '-' ? 1 : 0 + + for (; i >= start + 4; i -= 3) { + res = `_${val.slice(i - 3, i)}${res}` + } + + return `${val.slice(0, i)}${res}` +} + +function getMessage(key, msg, args) { + if (typeof msg === 'function') { + assert( + msg.length <= args.length, // Default options do not count. + `Code: ${key}; The provided arguments length (${args.length}) does not match the required ones (${msg.length}).` + ) + return msg(...args) + } + + const expectedLength = (msg.match(/%[dfijoOs]/g) || []).length + assert( + expectedLength === args.length, + `Code: ${key}; The provided arguments length (${args.length}) does not match the required ones (${expectedLength}).` + ) + + if (args.length === 0) { + return msg + } + + return format(msg, ...args) +} + +function E(code, message, Base) { + if (!Base) { + Base = Error + } + + class NodeError extends Base { + constructor(...args) { + super(getMessage(code, message, args)) + } + + toString() { + return `${this.name} [${code}]: ${this.message}` + } + } + + NodeError.prototype.name = Base.name + NodeError.prototype.code = code + NodeError.prototype[kIsNodeError] = true + + NodeError.prototype.toString = function () { + return `${this.name} [${code}]: ${this.message}` + } + + codes[code] = NodeError +} + +function hideStackFrames(fn) { + // We rename the functions that will be hidden to cut off the stacktrace + // at the outermost one + const hidden = nodeInternalPrefix + fn.name + Object.defineProperty(fn, 'name', { + value: hidden + }) + return fn +} + +function aggregateTwoErrors(innerError, outerError) { + if (innerError && outerError && innerError !== outerError) { + if (Array.isArray(outerError.errors)) { + // If `outerError` is already an `AggregateError`. + outerError.errors.push(innerError) + return outerError + } + + const err = new AggregateError([outerError, innerError], outerError.message) + err.code = outerError.code + return err + } + + return innerError || outerError +} + +class AbortError extends Error { + constructor(message = 'The operation was aborted', options = undefined) { + if (options !== undefined && typeof options !== 'object') { + throw new codes.ERR_INVALID_ARG_TYPE('options', 'Object', options) + } + + super(message, options) + this.code = 'ABORT_ERR' + this.name = 'AbortError' + } +} + +E('ERR_ASSERTION', '%s', Error) +E( + 'ERR_INVALID_ARG_TYPE', + (name, expected, actual) => { + assert(typeof name === 'string', "'name' must be a string") + + if (!Array.isArray(expected)) { + expected = [expected] + } + + let msg = 'The ' + + if (name.endsWith(' argument')) { + // For cases like 'first argument' + msg += `${name} ` + } else { + msg += `"${name}" ${name.includes('.') ? 'property' : 'argument'} ` + } + + msg += 'must be ' + const types = [] + const instances = [] + const other = [] + + for (const value of expected) { + assert(typeof value === 'string', 'All expected entries have to be of type string') + + if (kTypes.includes(value)) { + types.push(value.toLowerCase()) + } else if (classRegExp.test(value)) { + instances.push(value) + } else { + assert(value !== 'object', 'The value "object" should be written as "Object"') + other.push(value) + } + } // Special handle `object` in case other instances are allowed to outline + // the differences between each other. + + if (instances.length > 0) { + const pos = types.indexOf('object') + + if (pos !== -1) { + types.splice(types, pos, 1) + instances.push('Object') + } + } + + if (types.length > 0) { + switch (types.length) { + case 1: + msg += `of type ${types[0]}` + break + + case 2: + msg += `one of type ${types[0]} or ${types[1]}` + break + + default: { + const last = types.pop() + msg += `one of type ${types.join(', ')}, or ${last}` + } + } + + if (instances.length > 0 || other.length > 0) { + msg += ' or ' + } + } + + if (instances.length > 0) { + switch (instances.length) { + case 1: + msg += `an instance of ${instances[0]}` + break + + case 2: + msg += `an instance of ${instances[0]} or ${instances[1]}` + break + + default: { + const last = instances.pop() + msg += `an instance of ${instances.join(', ')}, or ${last}` + } + } + + if (other.length > 0) { + msg += ' or ' + } + } + + switch (other.length) { + case 0: + break + + case 1: + if (other[0].toLowerCase() !== other[0]) { + msg += 'an ' + } + + msg += `${other[0]}` + break + + case 2: + msg += `one of ${other[0]} or ${other[1]}` + break + + default: { + const last = other.pop() + msg += `one of ${other.join(', ')}, or ${last}` + } + } + + if (actual == null) { + msg += `. Received ${actual}` + } else if (typeof actual === 'function' && actual.name) { + msg += `. Received function ${actual.name}` + } else if (typeof actual === 'object') { + var _actual$constructor + + if ( + (_actual$constructor = actual.constructor) !== null && + _actual$constructor !== undefined && + _actual$constructor.name + ) { + msg += `. Received an instance of ${actual.constructor.name}` + } else { + const inspected = inspect(actual, { + depth: -1 + }) + msg += `. Received ${inspected}` + } + } else { + let inspected = inspect(actual, { + colors: false + }) + + if (inspected.length > 25) { + inspected = `${inspected.slice(0, 25)}...` + } + + msg += `. Received type ${typeof actual} (${inspected})` + } + + return msg + }, + TypeError +) +E( + 'ERR_INVALID_ARG_VALUE', + (name, value, reason = 'is invalid') => { + let inspected = inspect(value) + + if (inspected.length > 128) { + inspected = inspected.slice(0, 128) + '...' + } + + const type = name.includes('.') ? 'property' : 'argument' + return `The ${type} '${name}' ${reason}. Received ${inspected}` + }, + TypeError +) +E( + 'ERR_INVALID_RETURN_VALUE', + (input, name, value) => { + var _value$constructor + + const type = + value !== null && + value !== undefined && + (_value$constructor = value.constructor) !== null && + _value$constructor !== undefined && + _value$constructor.name + ? `instance of ${value.constructor.name}` + : `type ${typeof value}` + return `Expected ${input} to be returned from the "${name}"` + ` function but got ${type}.` + }, + TypeError +) +E( + 'ERR_MISSING_ARGS', + (...args) => { + assert(args.length > 0, 'At least one arg needs to be specified') + let msg + const len = args.length + args = (Array.isArray(args) ? args : [args]).map((a) => `"${a}"`).join(' or ') + + switch (len) { + case 1: + msg += `The ${args[0]} argument` + break + + case 2: + msg += `The ${args[0]} and ${args[1]} arguments` + break + + default: + { + const last = args.pop() + msg += `The ${args.join(', ')}, and ${last} arguments` + } + break + } + + return `${msg} must be specified` + }, + TypeError +) +E( + 'ERR_OUT_OF_RANGE', + (str, range, input) => { + assert(range, 'Missing "range" argument') + let received + + if (Number.isInteger(input) && Math.abs(input) > 2 ** 32) { + received = addNumericalSeparator(String(input)) + } else if (typeof input === 'bigint') { + received = String(input) + + if (input > 2n ** 32n || input < -(2n ** 32n)) { + received = addNumericalSeparator(received) + } + + received += 'n' + } else { + received = inspect(input) + } + + return `The value of "${str}" is out of range. It must be ${range}. Received ${received}` + }, + RangeError +) +E('ERR_MULTIPLE_CALLBACK', 'Callback called multiple times', Error) +E('ERR_METHOD_NOT_IMPLEMENTED', 'The %s method is not implemented', Error) +E('ERR_STREAM_ALREADY_FINISHED', 'Cannot call %s after a stream was finished', Error) +E('ERR_STREAM_CANNOT_PIPE', 'Cannot pipe, not readable', Error) +E('ERR_STREAM_DESTROYED', 'Cannot call %s after a stream was destroyed', Error) +E('ERR_STREAM_NULL_VALUES', 'May not write null values to stream', TypeError) +E('ERR_STREAM_PREMATURE_CLOSE', 'Premature close', Error) +E('ERR_STREAM_PUSH_AFTER_EOF', 'stream.push() after EOF', Error) +E('ERR_STREAM_UNSHIFT_AFTER_END_EVENT', 'stream.unshift() after end event', Error) +E('ERR_STREAM_WRITE_AFTER_END', 'write after end', Error) +E('ERR_UNKNOWN_ENCODING', 'Unknown encoding: %s', TypeError) +module.exports = { + AbortError, + aggregateTwoErrors: hideStackFrames(aggregateTwoErrors), + hideStackFrames, + codes +} diff --git a/server/libs/archiver/archiverUtils/readableStream/ours/primordials.js b/server/libs/archiver/archiverUtils/readableStream/ours/primordials.js new file mode 100644 index 000000000..fab7a28e4 --- /dev/null +++ b/server/libs/archiver/archiverUtils/readableStream/ours/primordials.js @@ -0,0 +1,130 @@ +'use strict' +/* + This file is a reduced and adapted version of the main lib/internal/per_context/primordials.js file defined at + + https://github.com/nodejs/node/blob/master/lib/internal/per_context/primordials.js + + Don't try to replace with the original file and keep it up to date with the upstream file. +*/ + +module.exports = { + ArrayIsArray(self) { + return Array.isArray(self) + }, + + ArrayPrototypeIncludes(self, el) { + return self.includes(el) + }, + + ArrayPrototypeIndexOf(self, el) { + return self.indexOf(el) + }, + + ArrayPrototypeJoin(self, sep) { + return self.join(sep) + }, + + ArrayPrototypeMap(self, fn) { + return self.map(fn) + }, + + ArrayPrototypePop(self, el) { + return self.pop(el) + }, + + ArrayPrototypePush(self, el) { + return self.push(el) + }, + + ArrayPrototypeSlice(self, start, end) { + return self.slice(start, end) + }, + + Error, + + FunctionPrototypeCall(fn, thisArgs, ...args) { + return fn.call(thisArgs, ...args) + }, + + FunctionPrototypeSymbolHasInstance(self, instance) { + return Function.prototype[Symbol.hasInstance].call(self, instance) + }, + + MathFloor: Math.floor, + Number, + NumberIsInteger: Number.isInteger, + NumberIsNaN: Number.isNaN, + NumberMAX_SAFE_INTEGER: Number.MAX_SAFE_INTEGER, + NumberMIN_SAFE_INTEGER: Number.MIN_SAFE_INTEGER, + NumberParseInt: Number.parseInt, + + ObjectDefineProperties(self, props) { + return Object.defineProperties(self, props) + }, + + ObjectDefineProperty(self, name, prop) { + return Object.defineProperty(self, name, prop) + }, + + ObjectGetOwnPropertyDescriptor(self, name) { + return Object.getOwnPropertyDescriptor(self, name) + }, + + ObjectKeys(obj) { + return Object.keys(obj) + }, + + ObjectSetPrototypeOf(target, proto) { + return Object.setPrototypeOf(target, proto) + }, + + Promise, + + PromisePrototypeCatch(self, fn) { + return self.catch(fn) + }, + + PromisePrototypeThen(self, thenFn, catchFn) { + return self.then(thenFn, catchFn) + }, + + PromiseReject(err) { + return Promise.reject(err) + }, + + ReflectApply: Reflect.apply, + + RegExpPrototypeTest(self, value) { + return self.test(value) + }, + + SafeSet: Set, + String, + + StringPrototypeSlice(self, start, end) { + return self.slice(start, end) + }, + + StringPrototypeToLowerCase(self) { + return self.toLowerCase() + }, + + StringPrototypeToUpperCase(self) { + return self.toUpperCase() + }, + + StringPrototypeTrim(self) { + return self.trim() + }, + + Symbol, + SymbolAsyncIterator: Symbol.asyncIterator, + SymbolHasInstance: Symbol.hasInstance, + SymbolIterator: Symbol.iterator, + + TypedArrayPrototypeSet(self, buf, len) { + return self.set(buf, len) + }, + + Uint8Array +} diff --git a/server/libs/archiver/archiverUtils/readableStream/ours/util.js b/server/libs/archiver/archiverUtils/readableStream/ours/util.js new file mode 100644 index 000000000..275ac68ce --- /dev/null +++ b/server/libs/archiver/archiverUtils/readableStream/ours/util.js @@ -0,0 +1,149 @@ +'use strict' + +const bufferModule = require('buffer') + +const AsyncFunction = Object.getPrototypeOf(async function () {}).constructor +const Blob = globalThis.Blob || bufferModule.Blob +/* eslint-disable indent */ + +const isBlob = + typeof Blob !== 'undefined' + ? function isBlob(b) { + // eslint-disable-next-line indent + return b instanceof Blob + } + : function isBlob(b) { + return false + } +/* eslint-enable indent */ +// This is a simplified version of AggregateError + +class AggregateError extends Error { + constructor(errors) { + if (!Array.isArray(errors)) { + throw new TypeError(`Expected input to be an Array, got ${typeof errors}`) + } + + let message = '' + + for (let i = 0; i < errors.length; i++) { + message += ` ${errors[i].stack}\n` + } + + super(message) + this.name = 'AggregateError' + this.errors = errors + } +} + +module.exports = { + AggregateError, + + once(callback) { + let called = false + return function (...args) { + if (called) { + return + } + + called = true + callback.apply(this, args) + } + }, + + createDeferredPromise: function () { + let resolve + let reject // eslint-disable-next-line promise/param-names + + const promise = new Promise((res, rej) => { + resolve = res + reject = rej + }) + return { + promise, + resolve, + reject + } + }, + + promisify(fn) { + return new Promise((resolve, reject) => { + fn((err, ...args) => { + if (err) { + return reject(err) + } + + return resolve(...args) + }) + }) + }, + + debuglog() { + return function () {} + }, + + format(format, ...args) { + // Simplified version of https://nodejs.org/api/util.html#utilformatformat-args + return format.replace(/%([sdifj])/g, function (...[_unused, type]) { + const replacement = args.shift() + + if (type === 'f') { + return replacement.toFixed(6) + } else if (type === 'j') { + return JSON.stringify(replacement) + } else if (type === 's' && typeof replacement === 'object') { + const ctor = replacement.constructor !== Object ? replacement.constructor.name : '' + return `${ctor} {}`.trim() + } else { + return replacement.toString() + } + }) + }, + + inspect(value) { + // Vastly simplified version of https://nodejs.org/api/util.html#utilinspectobject-options + switch (typeof value) { + case 'string': + if (value.includes("'")) { + if (!value.includes('"')) { + return `"${value}"` + } else if (!value.includes('`') && !value.includes('${')) { + return `\`${value}\`` + } + } + + return `'${value}'` + + case 'number': + if (isNaN(value)) { + return 'NaN' + } else if (Object.is(value, -0)) { + return String(value) + } + + return value + + case 'bigint': + return `${String(value)}n` + + case 'boolean': + case 'undefined': + return String(value) + + case 'object': + return '{}' + } + }, + + types: { + isAsyncFunction(fn) { + return fn instanceof AsyncFunction + }, + + isArrayBufferView(arr) { + return ArrayBuffer.isView(arr) + } + }, + isBlob +} +module.exports.promisify.custom = Symbol.for('nodejs.util.promisify.custom') diff --git a/server/libs/archiver/archiverUtils/readableStream/stream.js b/server/libs/archiver/archiverUtils/readableStream/stream.js new file mode 100644 index 000000000..311208630 --- /dev/null +++ b/server/libs/archiver/archiverUtils/readableStream/stream.js @@ -0,0 +1,149 @@ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. +'use strict' + +const { ObjectDefineProperty, ObjectKeys, ReflectApply } = require('./ours/primordials') + +const { + promisify: { custom: customPromisify } +} = require('./ours/util') + +const { streamReturningOperators, promiseReturningOperators } = require('./internal/streams/operators') + +const { + codes: { ERR_ILLEGAL_CONSTRUCTOR } +} = require('./ours/errors') + +const compose = require('./internal/streams/compose') + +const { pipeline } = require('./internal/streams/pipeline') + +const { destroyer } = require('./internal/streams/destroy') + +const eos = require('./internal/streams/end-of-stream') + +const internalBuffer = {} + +const promises = require('./stream/promises') + +const utils = require('./internal/streams/utils') + +const Stream = (module.exports = require('./internal/streams/legacy').Stream) + +Stream.isDisturbed = utils.isDisturbed +Stream.isErrored = utils.isErrored +Stream.isReadable = utils.isReadable +Stream.Readable = require('./internal/streams/readable') + +for (const key of ObjectKeys(streamReturningOperators)) { + const op = streamReturningOperators[key] + + function fn(...args) { + if (new.target) { + throw ERR_ILLEGAL_CONSTRUCTOR() + } + + return Stream.Readable.from(ReflectApply(op, this, args)) + } + + ObjectDefineProperty(fn, 'name', { + value: op.name + }) + ObjectDefineProperty(fn, 'length', { + value: op.length + }) + ObjectDefineProperty(Stream.Readable.prototype, key, { + value: fn, + enumerable: false, + configurable: true, + writable: true + }) +} + +for (const key of ObjectKeys(promiseReturningOperators)) { + const op = promiseReturningOperators[key] + + function fn(...args) { + if (new.target) { + throw ERR_ILLEGAL_CONSTRUCTOR() + } + + return ReflectApply(op, this, args) + } + + ObjectDefineProperty(fn, 'name', { + value: op.name + }) + ObjectDefineProperty(fn, 'length', { + value: op.length + }) + ObjectDefineProperty(Stream.Readable.prototype, key, { + value: fn, + enumerable: false, + configurable: true, + writable: true + }) +} + +Stream.Writable = require('./internal/streams/writable') +Stream.Duplex = require('./internal/streams/duplex') +Stream.Transform = require('./internal/streams/transform') +Stream.PassThrough = require('./internal/streams/passthrough') +Stream.pipeline = pipeline + +const { addAbortSignal } = require('./internal/streams/add-abort-signal') + +Stream.addAbortSignal = addAbortSignal +Stream.finished = eos +Stream.destroy = destroyer +Stream.compose = compose +ObjectDefineProperty(Stream, 'promises', { + configurable: true, + enumerable: true, + + get() { + return promises + } +}) +ObjectDefineProperty(pipeline, customPromisify, { + enumerable: true, + + get() { + return promises.pipeline + } +}) +ObjectDefineProperty(eos, customPromisify, { + enumerable: true, + + get() { + return promises.finished + } +}) // Backwards-compat with node 0.4.x + +Stream.Stream = Stream + +Stream._isUint8Array = function isUint8Array(value) { + return value instanceof Uint8Array +} + +Stream._uint8ArrayToBuffer = function _uint8ArrayToBuffer(chunk) { + return Buffer.from(chunk.buffer, chunk.byteOffset, chunk.byteLength) +} diff --git a/server/libs/archiver/archiverUtils/readableStream/stream/promises.js b/server/libs/archiver/archiverUtils/readableStream/stream/promises.js new file mode 100644 index 000000000..5e7972ee8 --- /dev/null +++ b/server/libs/archiver/archiverUtils/readableStream/stream/promises.js @@ -0,0 +1,43 @@ +'use strict' + +const { ArrayPrototypePop, Promise } = require('../ours/primordials') + +const { isIterable, isNodeStream } = require('../internal/streams/utils') + +const { pipelineImpl: pl } = require('../internal/streams/pipeline') + +const { finished } = require('../internal/streams/end-of-stream') + +function pipeline(...streams) { + return new Promise((resolve, reject) => { + let signal + let end + const lastArg = streams[streams.length - 1] + + if (lastArg && typeof lastArg === 'object' && !isNodeStream(lastArg) && !isIterable(lastArg)) { + const options = ArrayPrototypePop(streams) + signal = options.signal + end = options.end + } + + pl( + streams, + (err, value) => { + if (err) { + reject(err) + } else { + resolve(value) + } + }, + { + signal, + end + } + ) + }) +} + +module.exports = { + finished, + pipeline +} diff --git a/server/libs/archiver/archiverUtils/safeBuffer/LICENSE b/server/libs/archiver/archiverUtils/safeBuffer/LICENSE new file mode 100644 index 000000000..bf6c69d3e --- /dev/null +++ b/server/libs/archiver/archiverUtils/safeBuffer/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) Feross Aboukhadijeh + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. \ No newline at end of file diff --git a/server/libs/archiver/archiverUtils/safeBuffer/index.js b/server/libs/archiver/archiverUtils/safeBuffer/index.js new file mode 100644 index 000000000..e07d0d937 --- /dev/null +++ b/server/libs/archiver/archiverUtils/safeBuffer/index.js @@ -0,0 +1,65 @@ +/*! safe-buffer. MIT License. Feross Aboukhadijeh */ +/* eslint-disable node/no-deprecated-api, no-var */ +var buffer = require('buffer') +var Buffer = buffer.Buffer + +// alternative to using Object.keys for old browsers +function copyProps(src, dst) { + for (var key in src) { + dst[key] = src[key] + } +} +if (Buffer.from && Buffer.alloc && Buffer.allocUnsafe && Buffer.allocUnsafeSlow) { + module.exports = buffer +} else { + // Copy properties from require('buffer') + copyProps(buffer, exports) + exports.Buffer = SafeBuffer +} + +function SafeBuffer(arg, encodingOrOffset, length) { + return Buffer(arg, encodingOrOffset, length) +} + +SafeBuffer.prototype = Object.create(Buffer.prototype) + +// Copy static methods from Buffer +copyProps(Buffer, SafeBuffer) + +SafeBuffer.from = function (arg, encodingOrOffset, length) { + if (typeof arg === 'number') { + throw new TypeError('Argument must not be a number') + } + return Buffer(arg, encodingOrOffset, length) +} + +SafeBuffer.alloc = function (size, fill, encoding) { + if (typeof size !== 'number') { + throw new TypeError('Argument must be a number') + } + var buf = Buffer(size) + if (fill !== undefined) { + if (typeof encoding === 'string') { + buf.fill(fill, encoding) + } else { + buf.fill(fill) + } + } else { + buf.fill(0) + } + return buf +} + +SafeBuffer.allocUnsafe = function (size) { + if (typeof size !== 'number') { + throw new TypeError('Argument must be a number') + } + return Buffer(size) +} + +SafeBuffer.allocUnsafeSlow = function (size) { + if (typeof size !== 'number') { + throw new TypeError('Argument must be a number') + } + return buffer.SlowBuffer(size) +} \ No newline at end of file diff --git a/server/libs/archiver/archiverUtils/stringDecoder/LICENSE b/server/libs/archiver/archiverUtils/stringDecoder/LICENSE new file mode 100644 index 000000000..2873b3b2e --- /dev/null +++ b/server/libs/archiver/archiverUtils/stringDecoder/LICENSE @@ -0,0 +1,47 @@ +Node.js is licensed for use as follows: + +""" +Copyright Node.js contributors. All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to +deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +sell copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +IN THE SOFTWARE. +""" + +This license applies to parts of Node.js originating from the +https://github.com/joyent/node repository: + +""" +Copyright Joyent, Inc. and other Node contributors. All rights reserved. +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to +deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +sell copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +IN THE SOFTWARE. +""" diff --git a/server/libs/archiver/archiverUtils/stringDecoder/index.js b/server/libs/archiver/archiverUtils/stringDecoder/index.js new file mode 100644 index 000000000..cd68356e9 --- /dev/null +++ b/server/libs/archiver/archiverUtils/stringDecoder/index.js @@ -0,0 +1,295 @@ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +'use strict'; + +/**/ +var Buffer = require('../safeBuffer').Buffer; +/**/ + +var isEncoding = Buffer.isEncoding || function (encoding) { + encoding = '' + encoding; + switch (encoding && encoding.toLowerCase()) { + case 'hex': case 'utf8': case 'utf-8': case 'ascii': case 'binary': case 'base64': case 'ucs2': case 'ucs-2': case 'utf16le': case 'utf-16le': case 'raw': + return true; + default: + return false; + } +}; + +function _normalizeEncoding(enc) { + if (!enc) return 'utf8'; + var retried; + while (true) { + switch (enc) { + case 'utf8': + case 'utf-8': + return 'utf8'; + case 'ucs2': + case 'ucs-2': + case 'utf16le': + case 'utf-16le': + return 'utf16le'; + case 'latin1': + case 'binary': + return 'latin1'; + case 'base64': + case 'ascii': + case 'hex': + return enc; + default: + if (retried) return; // undefined + enc = ('' + enc).toLowerCase(); + retried = true; + } + } +}; + +// Do not cache `Buffer.isEncoding` when checking encoding names as some +// modules monkey-patch it to support additional encodings +function normalizeEncoding(enc) { + var nenc = _normalizeEncoding(enc); + if (typeof nenc !== 'string' && (Buffer.isEncoding === isEncoding || !isEncoding(enc))) throw new Error('Unknown encoding: ' + enc); + return nenc || enc; +} + +// StringDecoder provides an interface for efficiently splitting a series of +// buffers into a series of JS strings without breaking apart multi-byte +// characters. +exports.StringDecoder = StringDecoder; +function StringDecoder(encoding) { + this.encoding = normalizeEncoding(encoding); + var nb; + switch (this.encoding) { + case 'utf16le': + this.text = utf16Text; + this.end = utf16End; + nb = 4; + break; + case 'utf8': + this.fillLast = utf8FillLast; + nb = 4; + break; + case 'base64': + this.text = base64Text; + this.end = base64End; + nb = 3; + break; + default: + this.write = simpleWrite; + this.end = simpleEnd; + return; + } + this.lastNeed = 0; + this.lastTotal = 0; + this.lastChar = Buffer.allocUnsafe(nb); +} + +StringDecoder.prototype.write = function (buf) { + if (buf.length === 0) return ''; + var r; + var i; + if (this.lastNeed) { + r = this.fillLast(buf); + if (r === undefined) return ''; + i = this.lastNeed; + this.lastNeed = 0; + } else { + i = 0; + } + if (i < buf.length) return r ? r + this.text(buf, i) : this.text(buf, i); + return r || ''; +}; + +StringDecoder.prototype.end = utf8End; + +// Returns only complete characters in a Buffer +StringDecoder.prototype.text = utf8Text; + +// Attempts to complete a partial non-UTF-8 character using bytes from a Buffer +StringDecoder.prototype.fillLast = function (buf) { + if (this.lastNeed <= buf.length) { + buf.copy(this.lastChar, this.lastTotal - this.lastNeed, 0, this.lastNeed); + return this.lastChar.toString(this.encoding, 0, this.lastTotal); + } + buf.copy(this.lastChar, this.lastTotal - this.lastNeed, 0, buf.length); + this.lastNeed -= buf.length; +}; + +// Checks the type of a UTF-8 byte, whether it's ASCII, a leading byte, or a +// continuation byte. If an invalid byte is detected, -2 is returned. +function utf8CheckByte(byte) { + if (byte <= 0x7F) return 0; else if (byte >> 5 === 0x06) return 2; else if (byte >> 4 === 0x0E) return 3; else if (byte >> 3 === 0x1E) return 4; + return byte >> 6 === 0x02 ? -1 : -2; +} + +// Checks at most 3 bytes at the end of a Buffer in order to detect an +// incomplete multi-byte UTF-8 character. The total number of bytes (2, 3, or 4) +// needed to complete the UTF-8 character (if applicable) are returned. +function utf8CheckIncomplete(self, buf, i) { + var j = buf.length - 1; + if (j < i) return 0; + var nb = utf8CheckByte(buf[j]); + if (nb >= 0) { + if (nb > 0) self.lastNeed = nb - 1; + return nb; + } + if (--j < i || nb === -2) return 0; + nb = utf8CheckByte(buf[j]); + if (nb >= 0) { + if (nb > 0) self.lastNeed = nb - 2; + return nb; + } + if (--j < i || nb === -2) return 0; + nb = utf8CheckByte(buf[j]); + if (nb >= 0) { + if (nb > 0) { + if (nb === 2) nb = 0; else self.lastNeed = nb - 3; + } + return nb; + } + return 0; +} + +// Validates as many continuation bytes for a multi-byte UTF-8 character as +// needed or are available. If we see a non-continuation byte where we expect +// one, we "replace" the validated continuation bytes we've seen so far with +// a single UTF-8 replacement character ('\ufffd'), to match v8's UTF-8 decoding +// behavior. The continuation byte check is included three times in the case +// where all of the continuation bytes for a character exist in the same buffer. +// It is also done this way as a slight performance increase instead of using a +// loop. +function utf8CheckExtraBytes(self, buf, p) { + if ((buf[0] & 0xC0) !== 0x80) { + self.lastNeed = 0; + return '\ufffd'; + } + if (self.lastNeed > 1 && buf.length > 1) { + if ((buf[1] & 0xC0) !== 0x80) { + self.lastNeed = 1; + return '\ufffd'; + } + if (self.lastNeed > 2 && buf.length > 2) { + if ((buf[2] & 0xC0) !== 0x80) { + self.lastNeed = 2; + return '\ufffd'; + } + } + } +} + +// Attempts to complete a multi-byte UTF-8 character using bytes from a Buffer. +function utf8FillLast(buf) { + var p = this.lastTotal - this.lastNeed; + var r = utf8CheckExtraBytes(this, buf, p); + if (r !== undefined) return r; + if (this.lastNeed <= buf.length) { + buf.copy(this.lastChar, p, 0, this.lastNeed); + return this.lastChar.toString(this.encoding, 0, this.lastTotal); + } + buf.copy(this.lastChar, p, 0, buf.length); + this.lastNeed -= buf.length; +} + +// Returns all complete UTF-8 characters in a Buffer. If the Buffer ended on a +// partial character, the character's bytes are buffered until the required +// number of bytes are available. +function utf8Text(buf, i) { + var total = utf8CheckIncomplete(this, buf, i); + if (!this.lastNeed) return buf.toString('utf8', i); + this.lastTotal = total; + var end = buf.length - (total - this.lastNeed); + buf.copy(this.lastChar, 0, end); + return buf.toString('utf8', i, end); +} + +// For UTF-8, a replacement character is added when ending on a partial +// character. +function utf8End(buf) { + var r = buf && buf.length ? this.write(buf) : ''; + if (this.lastNeed) return r + '\ufffd'; + return r; +} + +// UTF-16LE typically needs two bytes per character, but even if we have an even +// number of bytes available, we need to check if we end on a leading/high +// surrogate. In that case, we need to wait for the next two bytes in order to +// decode the last character properly. +function utf16Text(buf, i) { + if ((buf.length - i) % 2 === 0) { + var r = buf.toString('utf16le', i); + if (r) { + var c = r.charCodeAt(r.length - 1); + if (c >= 0xD800 && c <= 0xDBFF) { + this.lastNeed = 2; + this.lastTotal = 4; + this.lastChar[0] = buf[buf.length - 2]; + this.lastChar[1] = buf[buf.length - 1]; + return r.slice(0, -1); + } + } + return r; + } + this.lastNeed = 1; + this.lastTotal = 2; + this.lastChar[0] = buf[buf.length - 1]; + return buf.toString('utf16le', i, buf.length - 1); +} + +// For UTF-16LE we do not explicitly append special replacement characters if we +// end on a partial character, we simply let v8 handle that. +function utf16End(buf) { + var r = buf && buf.length ? this.write(buf) : ''; + if (this.lastNeed) { + var end = this.lastTotal - this.lastNeed; + return r + this.lastChar.toString('utf16le', 0, end); + } + return r; +} + +function base64Text(buf, i) { + var n = (buf.length - i) % 3; + if (n === 0) return buf.toString('base64', i); + this.lastNeed = 3 - n; + this.lastTotal = 3; + if (n === 1) { + this.lastChar[0] = buf[buf.length - 1]; + } else { + this.lastChar[0] = buf[buf.length - 2]; + this.lastChar[1] = buf[buf.length - 1]; + } + return buf.toString('base64', i, buf.length - n); +} + +function base64End(buf) { + var r = buf && buf.length ? this.write(buf) : ''; + if (this.lastNeed) return r + this.lastChar.toString('base64', 0, 3 - this.lastNeed); + return r; +} + +// Pass bytes on through for single-byte encodings (e.g. ascii, latin1, hex) +function simpleWrite(buf) { + return buf.toString(this.encoding); +} + +function simpleEnd(buf) { + return buf && buf.length ? this.write(buf) : ''; +} \ No newline at end of file diff --git a/server/libs/archiver/archiverUtils/wrappy/LICENSE b/server/libs/archiver/archiverUtils/wrappy/LICENSE new file mode 100644 index 000000000..3cb6837a6 --- /dev/null +++ b/server/libs/archiver/archiverUtils/wrappy/LICENSE @@ -0,0 +1,15 @@ +The ISC License + +Copyright (c) Isaac Z. Schlueter and Contributors + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR +IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. \ No newline at end of file diff --git a/server/libs/archiver/archiverUtils/wrappy/index.js b/server/libs/archiver/archiverUtils/wrappy/index.js new file mode 100644 index 000000000..570ea5861 --- /dev/null +++ b/server/libs/archiver/archiverUtils/wrappy/index.js @@ -0,0 +1,29 @@ +// Returns a wrapper function that returns a wrapped callback +// The wrapper function should do some stuff, and return a +// presumably different callback function. +// This makes sure that own properties are retained, so that +// decorations and such are not lost along the way. +module.exports = wrappy +function wrappy(fn, cb) { + if (fn && cb) return wrappy(fn)(cb) + + if (typeof fn !== 'function') + throw new TypeError('need wrapper function') + + Object.keys(fn).forEach(function (k) { + wrapper[k] = fn[k] + }) + + return wrapper + + function wrapper() { + var ret = fn.apply(this, arguments) + var cb = arguments[arguments.length - 1] + if (typeof ret === 'function' && ret !== cb) { + Object.keys(cb).forEach(function (k) { + ret[k] = cb[k] + }) + } + return ret + } +} \ No newline at end of file diff --git a/server/libs/archiver/compress-commons/archivers/archive-output-stream.js b/server/libs/archiver/compress-commons/archivers/archive-output-stream.js index b5fa4939c..475b99584 100644 --- a/server/libs/archiver/compress-commons/archivers/archive-output-stream.js +++ b/server/libs/archiver/compress-commons/archivers/archive-output-stream.js @@ -6,12 +6,12 @@ * https://github.com/archiverjs/node-compress-commons/blob/master/LICENSE-MIT */ var inherits = require('util').inherits; -var Transform = require('readable-stream').Transform; +var Transform = require('../../archiverUtils/readableStream').Transform; var ArchiveEntry = require('./archive-entry'); var util = require('../util'); -var ArchiveOutputStream = module.exports = function(options) { +var ArchiveOutputStream = module.exports = function (options) { if (!(this instanceof ArchiveOutputStream)) { return new ArchiveOutputStream(options); } @@ -28,33 +28,33 @@ var ArchiveOutputStream = module.exports = function(options) { inherits(ArchiveOutputStream, Transform); -ArchiveOutputStream.prototype._appendBuffer = function(zae, source, callback) { +ArchiveOutputStream.prototype._appendBuffer = function (zae, source, callback) { // scaffold only }; -ArchiveOutputStream.prototype._appendStream = function(zae, source, callback) { +ArchiveOutputStream.prototype._appendStream = function (zae, source, callback) { // scaffold only }; -ArchiveOutputStream.prototype._emitErrorCallback = function(err) { +ArchiveOutputStream.prototype._emitErrorCallback = function (err) { if (err) { this.emit('error', err); } }; -ArchiveOutputStream.prototype._finish = function(ae) { +ArchiveOutputStream.prototype._finish = function (ae) { // scaffold only }; -ArchiveOutputStream.prototype._normalizeEntry = function(ae) { +ArchiveOutputStream.prototype._normalizeEntry = function (ae) { // scaffold only }; -ArchiveOutputStream.prototype._transform = function(chunk, encoding, callback) { +ArchiveOutputStream.prototype._transform = function (chunk, encoding, callback) { callback(null, chunk); }; -ArchiveOutputStream.prototype.entry = function(ae, source, callback) { +ArchiveOutputStream.prototype.entry = function (ae, source, callback) { source = source || null; if (typeof callback !== 'function') { @@ -95,7 +95,7 @@ ArchiveOutputStream.prototype.entry = function(ae, source, callback) { return this; }; -ArchiveOutputStream.prototype.finish = function() { +ArchiveOutputStream.prototype.finish = function () { if (this._archive.processing) { this._archive.finish = true; return; @@ -104,11 +104,11 @@ ArchiveOutputStream.prototype.finish = function() { this._finish(); }; -ArchiveOutputStream.prototype.getBytesWritten = function() { +ArchiveOutputStream.prototype.getBytesWritten = function () { return this.offset; }; -ArchiveOutputStream.prototype.write = function(chunk, cb) { +ArchiveOutputStream.prototype.write = function (chunk, cb) { if (chunk) { this.offset += chunk.length; } diff --git a/server/libs/archiver/compress-commons/util/index.js b/server/libs/archiver/compress-commons/util/index.js index 20a678331..1e7718c51 100644 --- a/server/libs/archiver/compress-commons/util/index.js +++ b/server/libs/archiver/compress-commons/util/index.js @@ -6,15 +6,15 @@ * https://github.com/archiverjs/node-compress-commons/blob/master/LICENSE-MIT */ var Stream = require('stream').Stream; -var PassThrough = require('readable-stream').PassThrough; +var PassThrough = require('../../archiverUtils/readableStream').PassThrough; var util = module.exports = {}; -util.isStream = function(source) { +util.isStream = function (source) { return source instanceof Stream; }; -util.normalizeInputSource = function(source) { +util.normalizeInputSource = function (source) { if (source === null) { return Buffer.alloc(0); } else if (typeof source === 'string') { diff --git a/server/libs/archiver/crc32-stream/crc32-stream.js b/server/libs/archiver/crc32-stream/crc32-stream.js index b3588b268..c89bcbaa1 100644 --- a/server/libs/archiver/crc32-stream/crc32-stream.js +++ b/server/libs/archiver/crc32-stream/crc32-stream.js @@ -8,8 +8,7 @@ 'use strict'; -const { Transform } = require('readable-stream'); - +const { Transform } = require('../archiverUtils/readableStream'); const crc32 = require('../crc32'); class CRC32Stream extends Transform { diff --git a/server/libs/archiver/lib/core.js b/server/libs/archiver/lib/core.js index 8e4aa96d2..935d6e1ff 100644 --- a/server/libs/archiver/lib/core.js +++ b/server/libs/archiver/lib/core.js @@ -9,11 +9,11 @@ var fs = require('fs'); var glob = require('../readdir-glob'); var async = require('../../async'); var path = require('path'); -var util = require('archiver-utils'); +var util = require('../archiverUtils'); var inherits = require('util').inherits; var ArchiverError = require('./error'); -var Transform = require('readable-stream').Transform; +var Transform = require('../archiverUtils/readableStream').Transform; var win32 = process.platform === 'win32'; diff --git a/server/libs/archiver/lib/plugins/json.js b/server/libs/archiver/lib/plugins/json.js index 713594c3b..f7b7891c7 100644 --- a/server/libs/archiver/lib/plugins/json.js +++ b/server/libs/archiver/lib/plugins/json.js @@ -6,10 +6,10 @@ * @copyright (c) 2012-2014 Chris Talkington, contributors. */ var inherits = require('util').inherits; -var Transform = require('readable-stream').Transform; +var Transform = require('../../archiverUtils/readableStream').Transform; var crc32 = require('../../buffer-crc32'); -var util = require('archiver-utils'); +var util = require('../../archiverUtils'); /** * @constructor diff --git a/server/libs/archiver/lib/plugins/zip.js b/server/libs/archiver/lib/plugins/zip.js index fe5d8ee2f..524bede8a 100644 --- a/server/libs/archiver/lib/plugins/zip.js +++ b/server/libs/archiver/lib/plugins/zip.js @@ -6,7 +6,7 @@ * @copyright (c) 2012-2014 Chris Talkington, contributors. */ var engine = require('../../zip-stream'); -var util = require('archiver-utils'); +var util = require('../../archiverUtils'); /** * @constructor diff --git a/server/libs/archiver/readdir-glob/index.js b/server/libs/archiver/readdir-glob/index.js index a188f3acd..bebcec145 100644 --- a/server/libs/archiver/readdir-glob/index.js +++ b/server/libs/archiver/readdir-glob/index.js @@ -7,7 +7,7 @@ module.exports = readdirGlob; const fs = require('fs'); const { EventEmitter } = require('events'); -const { Minimatch } = require('minimatch'); +const { Minimatch } = require('../archiverUtils/minimatch'); const { resolve } = require('path'); function readdir(dir, strict) { diff --git a/server/libs/archiver/zip-stream/index.js b/server/libs/archiver/zip-stream/index.js index de182f3bf..7b30e8414 100644 --- a/server/libs/archiver/zip-stream/index.js +++ b/server/libs/archiver/zip-stream/index.js @@ -10,7 +10,7 @@ var inherits = require('util').inherits; var ZipArchiveOutputStream = require('../compress-commons').ZipArchiveOutputStream; var ZipArchiveEntry = require('../compress-commons').ZipArchiveEntry; -var util = require('archiver-utils'); +var util = require('../archiverUtils'); /** * @constructor From 997e23150ef8359a80de6e2dcf6666e07946bc7c Mon Sep 17 00:00:00 2001 From: jmt-gh <13617455+jmt-gh@users.noreply.github.com> Date: Fri, 8 Jul 2022 20:26:30 -0700 Subject: [PATCH 012/100] extract current version changelog information --- client/plugins/version.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/client/plugins/version.js b/client/plugins/version.js index b1f9d5770..75b948c8c 100644 --- a/client/plugins/version.js +++ b/client/plugins/version.js @@ -47,8 +47,13 @@ export async function checkForUpdate() { largestVer = verObj } } + + if (verObj.version == currVerObj.version) { + currVerObj.changelog = release.body + } }) } + }) if (!largestVer) { console.error('No valid version tags to compare with') @@ -59,6 +64,7 @@ export async function checkForUpdate() { hasUpdate: largestVer.total > currVerObj.total, latestVersion: largestVer.version, githubTagUrl: `https://github.com/advplyr/audiobookshelf/releases/tag/v${largestVer.version}`, - currentVersion: currVerObj.version + currentVersion: currVerObj.version, + currentVersionChangelog: currVerObj.changelog } } \ No newline at end of file From 05afd12682381e22feaf508358e0363091927ead Mon Sep 17 00:00:00 2001 From: jmt-gh <13617455+jmt-gh@users.noreply.github.com> Date: Fri, 8 Jul 2022 20:27:02 -0700 Subject: [PATCH 013/100] add new changelog modal --- .../components/modals/changelog/ViewModal.vue | 63 +++++++++++++++++++ package-lock.json | 17 +++++ package.json | 1 + 3 files changed, 81 insertions(+) create mode 100644 client/components/modals/changelog/ViewModal.vue diff --git a/client/components/modals/changelog/ViewModal.vue b/client/components/modals/changelog/ViewModal.vue new file mode 100644 index 000000000..270c2d5f9 --- /dev/null +++ b/client/components/modals/changelog/ViewModal.vue @@ -0,0 +1,63 @@ + + + + \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 83f891ccb..136595c5a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,6 +13,7 @@ "express": "^4.17.1", "graceful-fs": "^4.2.10", "htmlparser2": "^8.0.1", + "marked": "^4.0.17", "socket.io": "^4.4.1", "xml2js": "^0.4.23" }, @@ -530,6 +531,17 @@ "node": ">= 0.10" } }, + "node_modules/marked": { + "version": "4.0.17", + "resolved": "https://registry.npmjs.org/marked/-/marked-4.0.17.tgz", + "integrity": "sha512-Wfk0ATOK5iPxM4ptrORkFemqroz0ZDxp5MWfYA7H/F+wO17NRWV5Ypxi6p3g2Xmw2bKeiYOl6oVnLHKxBA0VhA==", + "bin": { + "marked": "bin/marked.js" + }, + "engines": { + "node": ">= 12" + } + }, "node_modules/media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", @@ -1317,6 +1329,11 @@ "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==" }, + "marked": { + "version": "4.0.17", + "resolved": "https://registry.npmjs.org/marked/-/marked-4.0.17.tgz", + "integrity": "sha512-Wfk0ATOK5iPxM4ptrORkFemqroz0ZDxp5MWfYA7H/F+wO17NRWV5Ypxi6p3g2Xmw2bKeiYOl6oVnLHKxBA0VhA==" + }, "media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", diff --git a/package.json b/package.json index eaeb8cf20..d567147ae 100644 --- a/package.json +++ b/package.json @@ -34,6 +34,7 @@ "express": "^4.17.1", "graceful-fs": "^4.2.10", "htmlparser2": "^8.0.1", + "marked": "^4.0.17", "socket.io": "^4.4.1", "xml2js": "^0.4.23" } From b823a93ae2d1bc987df954684ee8caa401b60742 Mon Sep 17 00:00:00 2001 From: jmt-gh <13617455+jmt-gh@users.noreply.github.com> Date: Fri, 8 Jul 2022 20:29:18 -0700 Subject: [PATCH 014/100] integrate modal to sidenavs --- client/components/app/ConfigSideNav.vue | 16 +++++++++++++--- client/components/app/SideRail.vue | 20 ++++++++++++++------ 2 files changed, 27 insertions(+), 9 deletions(-) diff --git a/client/components/app/ConfigSideNav.vue b/client/components/app/ConfigSideNav.vue index bbadecc31..50cec860c 100644 --- a/client/components/app/ConfigSideNav.vue +++ b/client/components/app/ConfigSideNav.vue @@ -11,12 +11,14 @@
-

v{{ $config.version }}

+

v{{ $config.version }}

{{ Source }}

Latest: {{ latestVersion }}
+ + @@ -26,7 +28,9 @@ export default { isOpen: Boolean }, data() { - return {} + return { + showChangelogModal: false + } }, computed: { Source() { @@ -129,18 +133,24 @@ export default { githubTagUrl() { return this.versionData.githubTagUrl }, + currentVersionChangelog() { + return this.versionData.currentVersionChangelog || 'No Changelog Available' + }, streamLibraryItem() { return this.$store.state.streamLibraryItem } }, methods: { + clickChangelog(){ + this.showChangelogModal = true + }, clickOutside() { if (!this.isOpen) return this.closeDrawer() }, closeDrawer() { this.$emit('update:isOpen', false) - } + }, } } \ No newline at end of file diff --git a/client/components/app/SideRail.vue b/client/components/app/SideRail.vue index eddcdf26d..a60a6a658 100644 --- a/client/components/app/SideRail.vue +++ b/client/components/app/SideRail.vue @@ -75,17 +75,21 @@
-

v{{ $config.version }}

+

v{{ $config.version }}

Update

{{ Source }}

+ + \ No newline at end of file From bf6e87d4bc2ef802a99ac97245bccbeea148cb47 Mon Sep 17 00:00:00 2001 From: jmt-gh <13617455+jmt-gh@users.noreply.github.com> Date: Fri, 8 Jul 2022 20:34:32 -0700 Subject: [PATCH 015/100] update formatting --- client/components/modals/changelog/ViewModal.vue | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/client/components/modals/changelog/ViewModal.vue b/client/components/modals/changelog/ViewModal.vue index 270c2d5f9..5525bab38 100644 --- a/client/components/modals/changelog/ViewModal.vue +++ b/client/components/modals/changelog/ViewModal.vue @@ -6,7 +6,7 @@
-

Changelog v{{ currentVersionNumber }}

+

Changelog v{{ currentVersionNumber }}

@@ -53,11 +53,13 @@ export default { } \ No newline at end of file From a22ebb257fea320a4974d33f6cf9f22d336987c4 Mon Sep 17 00:00:00 2001 From: jmt-gh <13617455+jmt-gh@users.noreply.github.com> Date: Fri, 8 Jul 2022 20:45:09 -0700 Subject: [PATCH 016/100] add style comments --- client/components/modals/changelog/ViewModal.vue | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/client/components/modals/changelog/ViewModal.vue b/client/components/modals/changelog/ViewModal.vue index 5525bab38..8fd6551a6 100644 --- a/client/components/modals/changelog/ViewModal.vue +++ b/client/components/modals/changelog/ViewModal.vue @@ -53,6 +53,12 @@ export default { } \ No newline at end of file diff --git a/client/package-lock.json b/client/package-lock.json index f9665cb6e..960d50505 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -1,8 +1,17404 @@ { "name": "audiobookshelf-client", "version": "2.0.23", - "lockfileVersion": 1, + "lockfileVersion": 2, "requires": true, + "packages": { + "": { + "name": "audiobookshelf-client", + "version": "2.0.23", + "license": "ISC", + "dependencies": { + "@nuxtjs/axios": "^5.13.6", + "@nuxtjs/proxy": "^2.1.0", + "core-js": "^3.16.0", + "date-fns": "^2.25.0", + "epubjs": "^0.3.88", + "hls.js": "^1.0.7", + "libarchive.js": "^1.3.0", + "marked": "^4.0.17", + "nuxt": "^2.15.8", + "nuxt-socket-io": "^1.1.18", + "trix": "^1.3.1", + "v-click-outside": "^3.1.2", + "vue-pdf": "^4.3.0", + "vue-toastification": "^1.7.11", + "vuedraggable": "^2.24.3" + }, + "devDependencies": { + "@nuxt/postcss8": "^1.1.3", + "@nuxtjs/pwa": "^3.3.5", + "@nuxtjs/tailwindcss": "^4.2.1", + "autoprefixer": "^10.4.7", + "postcss": "^8.3.6", + "tailwindcss": "^3.1.4" + } + }, + "node_modules/@ampproject/remapping": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz", + "integrity": "sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==", + "dependencies": { + "@jridgewell/gen-mapping": "^0.1.0", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.7.tgz", + "integrity": "sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg==", + "dependencies": { + "@babel/highlight": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.17.10", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.17.10.tgz", + "integrity": "sha512-GZt/TCsG70Ms19gfZO1tM4CVnXsPgEPBCpJu+Qz3L0LUDsY5nZqFZglIoPC1kIYOtNBZlrnFT+klg12vFGZXrw==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.17.10", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.17.10.tgz", + "integrity": "sha512-liKoppandF3ZcBnIYFjfSDHZLKdLHGJRkoWtG8zQyGJBQfIYobpnVGI5+pLBNtS6psFLDzyq8+h5HiVljW9PNA==", + "dependencies": { + "@ampproject/remapping": "^2.1.0", + "@babel/code-frame": "^7.16.7", + "@babel/generator": "^7.17.10", + "@babel/helper-compilation-targets": "^7.17.10", + "@babel/helper-module-transforms": "^7.17.7", + "@babel/helpers": "^7.17.9", + "@babel/parser": "^7.17.10", + "@babel/template": "^7.16.7", + "@babel/traverse": "^7.17.10", + "@babel/types": "^7.17.10", + "convert-source-map": "^1.7.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.1", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/core/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/generator": { + "version": "7.17.10", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.17.10.tgz", + "integrity": "sha512-46MJZZo9y3o4kmhBVc7zW7i8dtR1oIK/sdO5NcfcZRhTGYi+KKJRtHNgsU6c4VUcJmUNV/LQdebD/9Dlv4K+Tg==", + "dependencies": { + "@babel/types": "^7.17.10", + "@jridgewell/gen-mapping": "^0.1.0", + "jsesc": "^2.5.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-annotate-as-pure": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.16.7.tgz", + "integrity": "sha512-s6t2w/IPQVTAET1HitoowRGXooX8mCgtuP5195wD/QJPV6wYjpujCGF7JuMODVX2ZAJOf1GT6DT9MHEZvLOFSw==", + "dependencies": { + "@babel/types": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-builder-binary-assignment-operator-visitor": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.16.7.tgz", + "integrity": "sha512-C6FdbRaxYjwVu/geKW4ZeQ0Q31AftgRcdSnZ5/jsH6BzCJbtvXvhpfkbkThYSuutZA7nCXpPR6AD9zd1dprMkA==", + "dependencies": { + "@babel/helper-explode-assignable-expression": "^7.16.7", + "@babel/types": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.17.10", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.17.10.tgz", + "integrity": "sha512-gh3RxjWbauw/dFiU/7whjd0qN9K6nPJMqe6+Er7rOavFh0CQUSwhAE3IcTho2rywPJFxej6TUUHDkWcYI6gGqQ==", + "dependencies": { + "@babel/compat-data": "^7.17.10", + "@babel/helper-validator-option": "^7.16.7", + "browserslist": "^4.20.2", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-create-class-features-plugin": { + "version": "7.17.9", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.17.9.tgz", + "integrity": "sha512-kUjip3gruz6AJKOq5i3nC6CoCEEF/oHH3cp6tOZhB+IyyyPyW0g1Gfsxn3mkk6S08pIA2y8GQh609v9G/5sHVQ==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.16.7", + "@babel/helper-environment-visitor": "^7.16.7", + "@babel/helper-function-name": "^7.17.9", + "@babel/helper-member-expression-to-functions": "^7.17.7", + "@babel/helper-optimise-call-expression": "^7.16.7", + "@babel/helper-replace-supers": "^7.16.7", + "@babel/helper-split-export-declaration": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-create-regexp-features-plugin": { + "version": "7.17.0", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.17.0.tgz", + "integrity": "sha512-awO2So99wG6KnlE+TPs6rn83gCz5WlEePJDTnLEqbchMVrBeAujURVphRdigsk094VhvZehFoNOihSlcBjwsXA==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.16.7", + "regexpu-core": "^5.0.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-define-polyfill-provider": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.3.1.tgz", + "integrity": "sha512-J9hGMpJQmtWmj46B3kBHmL38UhJGhYX7eqkcq+2gsstyYt341HmPeWspihX43yVRA0mS+8GGk2Gckc7bY/HCmA==", + "dependencies": { + "@babel/helper-compilation-targets": "^7.13.0", + "@babel/helper-module-imports": "^7.12.13", + "@babel/helper-plugin-utils": "^7.13.0", + "@babel/traverse": "^7.13.0", + "debug": "^4.1.1", + "lodash.debounce": "^4.0.8", + "resolve": "^1.14.2", + "semver": "^6.1.2" + }, + "peerDependencies": { + "@babel/core": "^7.4.0-0" + } + }, + "node_modules/@babel/helper-define-polyfill-provider/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-environment-visitor": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.16.7.tgz", + "integrity": "sha512-SLLb0AAn6PkUeAfKJCCOl9e1R53pQlGAfc4y4XuMRZfqeMYLE0dM1LMhqbGAlGQY0lfw5/ohoYWAe9V1yibRag==", + "dependencies": { + "@babel/types": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-explode-assignable-expression": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.16.7.tgz", + "integrity": "sha512-KyUenhWMC8VrxzkGP0Jizjo4/Zx+1nNZhgocs+gLzyZyB8SHidhoq9KK/8Ato4anhwsivfkBLftky7gvzbZMtQ==", + "dependencies": { + "@babel/types": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-function-name": { + "version": "7.17.9", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.17.9.tgz", + "integrity": "sha512-7cRisGlVtiVqZ0MW0/yFB4atgpGLWEHUVYnb448hZK4x+vih0YO5UoS11XIYtZYqHd0dIPMdUSv8q5K4LdMnIg==", + "dependencies": { + "@babel/template": "^7.16.7", + "@babel/types": "^7.17.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-hoist-variables": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.16.7.tgz", + "integrity": "sha512-m04d/0Op34H5v7pbZw6pSKP7weA6lsMvfiIAMeIvkY/R4xQtBSMFEigu9QTZ2qB/9l22vsxtM8a+Q8CzD255fg==", + "dependencies": { + "@babel/types": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-member-expression-to-functions": { + "version": "7.17.7", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.17.7.tgz", + "integrity": "sha512-thxXgnQ8qQ11W2wVUObIqDL4p148VMxkt5T/qpN5k2fboRyzFGFmKsTGViquyM5QHKUy48OZoca8kw4ajaDPyw==", + "dependencies": { + "@babel/types": "^7.17.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.16.7.tgz", + "integrity": "sha512-LVtS6TqjJHFc+nYeITRo6VLXve70xmq7wPhWTqDJusJEgGmkAACWwMiTNrvfoQo6hEhFwAIixNkvB0jPXDL8Wg==", + "dependencies": { + "@babel/types": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.17.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.17.7.tgz", + "integrity": "sha512-VmZD99F3gNTYB7fJRDTi+u6l/zxY0BE6OIxPSU7a50s6ZUQkHwSDmV92FfM+oCG0pZRVojGYhkR8I0OGeCVREw==", + "dependencies": { + "@babel/helper-environment-visitor": "^7.16.7", + "@babel/helper-module-imports": "^7.16.7", + "@babel/helper-simple-access": "^7.17.7", + "@babel/helper-split-export-declaration": "^7.16.7", + "@babel/helper-validator-identifier": "^7.16.7", + "@babel/template": "^7.16.7", + "@babel/traverse": "^7.17.3", + "@babel/types": "^7.17.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-optimise-call-expression": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.16.7.tgz", + "integrity": "sha512-EtgBhg7rd/JcnpZFXpBy0ze1YRfdm7BnBX4uKMBd3ixa3RGAE002JZB66FJyNH7g0F38U05pXmA5P8cBh7z+1w==", + "dependencies": { + "@babel/types": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.16.7.tgz", + "integrity": "sha512-Qg3Nk7ZxpgMrsox6HreY1ZNKdBq7K72tDSliA6dCl5f007jR4ne8iD5UzuNnCJH2xBf2BEEVGr+/OL6Gdp7RxA==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-remap-async-to-generator": { + "version": "7.16.8", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.16.8.tgz", + "integrity": "sha512-fm0gH7Flb8H51LqJHy3HJ3wnE1+qtYR2A99K06ahwrawLdOFsCEWjZOrYricXJHoPSudNKxrMBUPEIPxiIIvBw==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.16.7", + "@babel/helper-wrap-function": "^7.16.8", + "@babel/types": "^7.16.8" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-replace-supers": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.16.7.tgz", + "integrity": "sha512-y9vsWilTNaVnVh6xiJfABzsNpgDPKev9HnAgz6Gb1p6UUwf9NepdlsV7VXGCftJM+jqD5f7JIEubcpLjZj5dBw==", + "dependencies": { + "@babel/helper-environment-visitor": "^7.16.7", + "@babel/helper-member-expression-to-functions": "^7.16.7", + "@babel/helper-optimise-call-expression": "^7.16.7", + "@babel/traverse": "^7.16.7", + "@babel/types": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-simple-access": { + "version": "7.17.7", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.17.7.tgz", + "integrity": "sha512-txyMCGroZ96i+Pxr3Je3lzEJjqwaRC9buMUgtomcrLe5Nd0+fk1h0LLA+ixUF5OW7AhHuQ7Es1WcQJZmZsz2XA==", + "dependencies": { + "@babel/types": "^7.17.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-skip-transparent-expression-wrappers": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.16.0.tgz", + "integrity": "sha512-+il1gTy0oHwUsBQZyJvukbB4vPMdcYBrFHa0Uc4AizLxbq6BOYC51Rv4tWocX9BLBDLZ4kc6qUFpQ6HRgL+3zw==", + "dependencies": { + "@babel/types": "^7.16.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-split-export-declaration": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.7.tgz", + "integrity": "sha512-xbWoy/PFoxSWazIToT9Sif+jJTlrMcndIsaOKvTA6u7QEo7ilkRZpjew18/W3c7nm8fXdUDXh02VXTbZ0pGDNw==", + "dependencies": { + "@babel/types": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz", + "integrity": "sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.16.7.tgz", + "integrity": "sha512-TRtenOuRUVo9oIQGPC5G9DgK4743cdxvtOw0weQNpZXaS16SCBi5MNjZF8vba3ETURjZpTbVn7Vvcf2eAwFozQ==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-wrap-function": { + "version": "7.16.8", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.16.8.tgz", + "integrity": "sha512-8RpyRVIAW1RcDDGTA+GpPAwV22wXCfKOoM9bet6TLkGIFTkRQSkH1nMQ5Yet4MpoXe1ZwHPVtNasc2w0uZMqnw==", + "dependencies": { + "@babel/helper-function-name": "^7.16.7", + "@babel/template": "^7.16.7", + "@babel/traverse": "^7.16.8", + "@babel/types": "^7.16.8" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.17.9", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.17.9.tgz", + "integrity": "sha512-cPCt915ShDWUEzEp3+UNRktO2n6v49l5RSnG9M5pS24hA+2FAc5si+Pn1i4VVbQQ+jh+bIZhPFQOJOzbrOYY1Q==", + "dependencies": { + "@babel/template": "^7.16.7", + "@babel/traverse": "^7.17.9", + "@babel/types": "^7.17.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight": { + "version": "7.17.9", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.17.9.tgz", + "integrity": "sha512-J9PfEKCbFIv2X5bjTMiZu6Vf341N05QIY+d6FvVKynkG1S7G0j3I0QoRtWIrXhZ+/Nlb5Q0MzqL7TokEJ5BNHg==", + "dependencies": { + "@babel/helper-validator-identifier": "^7.16.7", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/@babel/highlight/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" + }, + "node_modules/@babel/highlight/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/parser": { + "version": "7.17.10", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.17.10.tgz", + "integrity": "sha512-n2Q6i+fnJqzOaq2VkdXxy2TCPCWQZHiCo0XqmrCvDWcZQKRyZzYi4Z0yxlBuN0w+r2ZHmre+Q087DSrw3pbJDQ==", + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.16.7.tgz", + "integrity": "sha512-anv/DObl7waiGEnC24O9zqL0pSuI9hljihqiDuFHC8d7/bjr/4RLGPWuc8rYOff/QPzbEPSkzG8wGG9aDuhHRg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.16.7.tgz", + "integrity": "sha512-di8vUHRdf+4aJ7ltXhaDbPoszdkh59AQtJM5soLsuHpQJdFQZOA4uGj0V2u/CZ8bJ/u8ULDL5yq6FO/bCXnKHw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.16.0", + "@babel/plugin-proposal-optional-chaining": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.13.0" + } + }, + "node_modules/@babel/plugin-proposal-async-generator-functions": { + "version": "7.16.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.16.8.tgz", + "integrity": "sha512-71YHIvMuiuqWJQkebWJtdhQTfd4Q4mF76q2IX37uZPkG9+olBxsX+rH1vkhFto4UeJZ9dPY2s+mDvhDm1u2BGQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/helper-remap-async-to-generator": "^7.16.8", + "@babel/plugin-syntax-async-generators": "^7.8.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-class-properties": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.16.7.tgz", + "integrity": "sha512-IobU0Xme31ewjYOShSIqd/ZGM/r/cuOz2z0MDbNrhF5FW+ZVgi0f2lyeoj9KFPDOAqsYxmLWZte1WOwlvY9aww==", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-class-static-block": { + "version": "7.17.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.17.6.tgz", + "integrity": "sha512-X/tididvL2zbs7jZCeeRJ8167U/+Ac135AM6jCAx6gYXDUviZV5Ku9UDvWS2NCuWlFjIRXklYhwo6HhAC7ETnA==", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.17.6", + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/plugin-syntax-class-static-block": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.12.0" + } + }, + "node_modules/@babel/plugin-proposal-decorators": { + "version": "7.17.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.17.9.tgz", + "integrity": "sha512-EfH2LZ/vPa2wuPwJ26j+kYRkaubf89UlwxKXtxqEm57HrgSEYDB8t4swFP+p8LcI9yiP9ZRJJjo/58hS6BnaDA==", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.17.9", + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/helper-replace-supers": "^7.16.7", + "@babel/helper-split-export-declaration": "^7.16.7", + "@babel/plugin-syntax-decorators": "^7.17.0", + "charcodes": "^0.2.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-dynamic-import": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.16.7.tgz", + "integrity": "sha512-I8SW9Ho3/8DRSdmDdH3gORdyUuYnk1m4cMxUAdu5oy4n3OfN8flDEH+d60iG7dUfi0KkYwSvoalHzzdRzpWHTg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/plugin-syntax-dynamic-import": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-export-namespace-from": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.16.7.tgz", + "integrity": "sha512-ZxdtqDXLRGBL64ocZcs7ovt71L3jhC1RGSyR996svrCi3PYqHNkb3SwPJCs8RIzD86s+WPpt2S73+EHCGO+NUA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-json-strings": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.16.7.tgz", + "integrity": "sha512-lNZ3EEggsGY78JavgbHsK9u5P3pQaW7k4axlgFLYkMd7UBsiNahCITShLjNQschPyjtO6dADrL24757IdhBrsQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/plugin-syntax-json-strings": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-logical-assignment-operators": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.16.7.tgz", + "integrity": "sha512-K3XzyZJGQCr00+EtYtrDjmwX7o7PLK6U9bi1nCwkQioRFVUv6dJoxbQjtWVtP+bCPy82bONBKG8NPyQ4+i6yjg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-nullish-coalescing-operator": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.16.7.tgz", + "integrity": "sha512-aUOrYU3EVtjf62jQrCj63pYZ7k6vns2h/DQvHPWGmsJRYzWXZ6/AsfgpiRy6XiuIDADhJzP2Q9MwSMKauBQ+UQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-numeric-separator": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.16.7.tgz", + "integrity": "sha512-vQgPMknOIgiuVqbokToyXbkY/OmmjAzr/0lhSIbG/KmnzXPGwW/AdhdKpi+O4X/VkWiWjnkKOBiqJrTaC98VKw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/plugin-syntax-numeric-separator": "^7.10.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-object-rest-spread": { + "version": "7.17.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.17.3.tgz", + "integrity": "sha512-yuL5iQA/TbZn+RGAfxQXfi7CNLmKi1f8zInn4IgobuCWcAb7i+zj4TYzQ9l8cEzVyJ89PDGuqxK1xZpUDISesw==", + "dependencies": { + "@babel/compat-data": "^7.17.0", + "@babel/helper-compilation-targets": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-transform-parameters": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-optional-catch-binding": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.16.7.tgz", + "integrity": "sha512-eMOH/L4OvWSZAE1VkHbr1vckLG1WUcHGJSLqqQwl2GaUqG6QjddvrOaTUMNYiv77H5IKPMZ9U9P7EaHwvAShfA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-optional-chaining": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.16.7.tgz", + "integrity": "sha512-eC3xy+ZrUcBtP7x+sq62Q/HYd674pPTb/77XZMb5wbDPGWIdUbSr4Agr052+zaUPSb+gGRnjxXfKFvx5iMJ+DA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.16.0", + "@babel/plugin-syntax-optional-chaining": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-private-methods": { + "version": "7.16.11", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.16.11.tgz", + "integrity": "sha512-F/2uAkPlXDr8+BHpZvo19w3hLFKge+k75XUprE6jaqKxjGkSYcK+4c+bup5PdW/7W/Rpjwql7FTVEDW+fRAQsw==", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.16.10", + "@babel/helper-plugin-utils": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-private-property-in-object": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.16.7.tgz", + "integrity": "sha512-rMQkjcOFbm+ufe3bTZLyOfsOUOxyvLXZJCTARhJr+8UMSoZmqTe1K1BgkFcrW37rAchWg57yI69ORxiWvUINuQ==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.16.7", + "@babel/helper-create-class-features-plugin": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-unicode-property-regex": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.16.7.tgz", + "integrity": "sha512-QRK0YI/40VLhNVGIjRNAAQkEHws0cswSdFFjpFyt943YmJIU1da9uW63Iu6NFV6CxTZW5eTDCrwZUstBWgp/Rg==", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-properties": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", + "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.12.13" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-static-block": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", + "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-decorators": { + "version": "7.17.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.17.0.tgz", + "integrity": "sha512-qWe85yCXsvDEluNP0OyeQjH63DlhAR3W7K9BxxU1MvbDb48tgBG+Ao6IJJ6smPDrrVzSQZrbF6donpkFBMcs3A==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-dynamic-import": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", + "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-export-namespace-from": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz", + "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.3" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-jsx": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.16.7.tgz", + "integrity": "sha512-Esxmk7YjA8QysKeT3VhTXvF6y77f/a91SIs4pWb4H2eWGQkCKFgQaG6hdoEVZtGsrAcb2K5BW66XsOErD4WU3Q==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-private-property-in-object": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", + "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-top-level-await": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", + "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-arrow-functions": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.16.7.tgz", + "integrity": "sha512-9ffkFFMbvzTvv+7dTp/66xvZAWASuPD5Tl9LK3Z9vhOmANo6j94rik+5YMBt4CwHVMWLWpMsriIc2zsa3WW3xQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-async-to-generator": { + "version": "7.16.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.16.8.tgz", + "integrity": "sha512-MtmUmTJQHCnyJVrScNzNlofQJ3dLFuobYn3mwOTKHnSCMtbNsqvF71GQmJfFjdrXSsAA7iysFmYWw4bXZ20hOg==", + "dependencies": { + "@babel/helper-module-imports": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/helper-remap-async-to-generator": "^7.16.8" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-block-scoped-functions": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.16.7.tgz", + "integrity": "sha512-JUuzlzmF40Z9cXyytcbZEZKckgrQzChbQJw/5PuEHYeqzCsvebDx0K0jWnIIVcmmDOAVctCgnYs0pMcrYj2zJg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-block-scoping": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.16.7.tgz", + "integrity": "sha512-ObZev2nxVAYA4bhyusELdo9hb3H+A56bxH3FZMbEImZFiEDYVHXQSJ1hQKFlDnlt8G9bBrCZ5ZpURZUrV4G5qQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-classes": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.16.7.tgz", + "integrity": "sha512-WY7og38SFAGYRe64BrjKf8OrE6ulEHtr5jEYaZMwox9KebgqPi67Zqz8K53EKk1fFEJgm96r32rkKZ3qA2nCWQ==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.16.7", + "@babel/helper-environment-visitor": "^7.16.7", + "@babel/helper-function-name": "^7.16.7", + "@babel/helper-optimise-call-expression": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/helper-replace-supers": "^7.16.7", + "@babel/helper-split-export-declaration": "^7.16.7", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-computed-properties": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.16.7.tgz", + "integrity": "sha512-gN72G9bcmenVILj//sv1zLNaPyYcOzUho2lIJBMh/iakJ9ygCo/hEF9cpGb61SCMEDxbbyBoVQxrt+bWKu5KGw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-destructuring": { + "version": "7.17.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.17.7.tgz", + "integrity": "sha512-XVh0r5yq9sLR4vZ6eVZe8FKfIcSgaTBxVBRSYokRj2qksf6QerYnTxz9/GTuKTH/n/HwLP7t6gtlybHetJ/6hQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-dotall-regex": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.16.7.tgz", + "integrity": "sha512-Lyttaao2SjZF6Pf4vk1dVKv8YypMpomAbygW+mU5cYP3S5cWTfCJjG8xV6CFdzGFlfWK81IjL9viiTvpb6G7gQ==", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-duplicate-keys": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.16.7.tgz", + "integrity": "sha512-03DvpbRfvWIXyK0/6QiR1KMTWeT6OcQ7tbhjrXyFS02kjuX/mu5Bvnh5SDSWHxyawit2g5aWhKwI86EE7GUnTw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-exponentiation-operator": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.16.7.tgz", + "integrity": "sha512-8UYLSlyLgRixQvlYH3J2ekXFHDFLQutdy7FfFAMm3CPZ6q9wHCwnUyiXpQCe3gVVnQlHc5nsuiEVziteRNTXEA==", + "dependencies": { + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-for-of": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.16.7.tgz", + "integrity": "sha512-/QZm9W92Ptpw7sjI9Nx1mbcsWz33+l8kuMIQnDwgQBG5s3fAfQvkRjQ7NqXhtNcKOnPkdICmUHyCaWW06HCsqg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-function-name": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.16.7.tgz", + "integrity": "sha512-SU/C68YVwTRxqWj5kgsbKINakGag0KTgq9f2iZEXdStoAbOzLHEBRYzImmA6yFo8YZhJVflvXmIHUO7GWHmxxA==", + "dependencies": { + "@babel/helper-compilation-targets": "^7.16.7", + "@babel/helper-function-name": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-literals": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.16.7.tgz", + "integrity": "sha512-6tH8RTpTWI0s2sV6uq3e/C9wPo4PTqqZps4uF0kzQ9/xPLFQtipynvmT1g/dOfEJ+0EQsHhkQ/zyRId8J2b8zQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-member-expression-literals": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.16.7.tgz", + "integrity": "sha512-mBruRMbktKQwbxaJof32LT9KLy2f3gH+27a5XSuXo6h7R3vqltl0PgZ80C8ZMKw98Bf8bqt6BEVi3svOh2PzMw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-amd": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.16.7.tgz", + "integrity": "sha512-KaaEtgBL7FKYwjJ/teH63oAmE3lP34N3kshz8mm4VMAw7U3PxjVwwUmxEFksbgsNUaO3wId9R2AVQYSEGRa2+g==", + "dependencies": { + "@babel/helper-module-transforms": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7", + "babel-plugin-dynamic-import-node": "^2.3.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-commonjs": { + "version": "7.17.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.17.9.tgz", + "integrity": "sha512-2TBFd/r2I6VlYn0YRTz2JdazS+FoUuQ2rIFHoAxtyP/0G3D82SBLaRq9rnUkpqlLg03Byfl/+M32mpxjO6KaPw==", + "dependencies": { + "@babel/helper-module-transforms": "^7.17.7", + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/helper-simple-access": "^7.17.7", + "babel-plugin-dynamic-import-node": "^2.3.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-systemjs": { + "version": "7.17.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.17.8.tgz", + "integrity": "sha512-39reIkMTUVagzgA5x88zDYXPCMT6lcaRKs1+S9K6NKBPErbgO/w/kP8GlNQTC87b412ZTlmNgr3k2JrWgHH+Bw==", + "dependencies": { + "@babel/helper-hoist-variables": "^7.16.7", + "@babel/helper-module-transforms": "^7.17.7", + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/helper-validator-identifier": "^7.16.7", + "babel-plugin-dynamic-import-node": "^2.3.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-umd": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.16.7.tgz", + "integrity": "sha512-EMh7uolsC8O4xhudF2F6wedbSHm1HHZ0C6aJ7K67zcDNidMzVcxWdGr+htW9n21klm+bOn+Rx4CBsAntZd3rEQ==", + "dependencies": { + "@babel/helper-module-transforms": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { + "version": "7.17.10", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.17.10.tgz", + "integrity": "sha512-v54O6yLaJySCs6mGzaVOUw9T967GnH38T6CQSAtnzdNPwu84l2qAjssKzo/WSO8Yi7NF+7ekm5cVbF/5qiIgNA==", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.17.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-new-target": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.16.7.tgz", + "integrity": "sha512-xiLDzWNMfKoGOpc6t3U+etCE2yRnn3SM09BXqWPIZOBpL2gvVrBWUKnsJx0K/ADi5F5YC5f8APFfWrz25TdlGg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-object-super": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.16.7.tgz", + "integrity": "sha512-14J1feiQVWaGvRxj2WjyMuXS2jsBkgB3MdSN5HuC2G5nRspa5RK9COcs82Pwy5BuGcjb+fYaUj94mYcOj7rCvw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/helper-replace-supers": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-parameters": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.16.7.tgz", + "integrity": "sha512-AT3MufQ7zZEhU2hwOA11axBnExW0Lszu4RL/tAlUJBuNoRak+wehQW8h6KcXOcgjY42fHtDxswuMhMjFEuv/aw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-property-literals": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.16.7.tgz", + "integrity": "sha512-z4FGr9NMGdoIl1RqavCqGG+ZuYjfZ/hkCIeuH6Do7tXmSm0ls11nYVSJqFEUOSJbDab5wC6lRE/w6YjVcr6Hqw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-regenerator": { + "version": "7.17.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.17.9.tgz", + "integrity": "sha512-Lc2TfbxR1HOyn/c6b4Y/b6NHoTb67n/IoWLxTu4kC7h4KQnWlhCq2S8Tx0t2SVvv5Uu87Hs+6JEJ5kt2tYGylQ==", + "dependencies": { + "regenerator-transform": "^0.15.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-reserved-words": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.16.7.tgz", + "integrity": "sha512-KQzzDnZ9hWQBjwi5lpY5v9shmm6IVG0U9pB18zvMu2i4H90xpT4gmqwPYsn8rObiadYe2M0gmgsiOIF5A/2rtg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-runtime": { + "version": "7.17.10", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.17.10.tgz", + "integrity": "sha512-6jrMilUAJhktTr56kACL8LnWC5hx3Lf27BS0R0DSyW/OoJfb/iTHeE96V3b1dgKG3FSFdd/0culnYWMkjcKCig==", + "dependencies": { + "@babel/helper-module-imports": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7", + "babel-plugin-polyfill-corejs2": "^0.3.0", + "babel-plugin-polyfill-corejs3": "^0.5.0", + "babel-plugin-polyfill-regenerator": "^0.3.0", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-runtime/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/plugin-transform-shorthand-properties": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.16.7.tgz", + "integrity": "sha512-hah2+FEnoRoATdIb05IOXf+4GzXYTq75TVhIn1PewihbpyrNWUt2JbudKQOETWw6QpLe+AIUpJ5MVLYTQbeeUg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-spread": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.16.7.tgz", + "integrity": "sha512-+pjJpgAngb53L0iaA5gU/1MLXJIfXcYepLgXB3esVRf4fqmj8f2cxM3/FKaHsZms08hFQJkFccEWuIpm429TXg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.16.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-sticky-regex": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.16.7.tgz", + "integrity": "sha512-NJa0Bd/87QV5NZZzTuZG5BPJjLYadeSZ9fO6oOUoL4iQx+9EEuw/eEM92SrsT19Yc2jgB1u1hsjqDtH02c3Drw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-template-literals": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.16.7.tgz", + "integrity": "sha512-VwbkDDUeenlIjmfNeDX/V0aWrQH2QiVyJtwymVQSzItFDTpxfyJh3EVaQiS0rIN/CqbLGr0VcGmuwyTdZtdIsA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-typeof-symbol": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.16.7.tgz", + "integrity": "sha512-p2rOixCKRJzpg9JB4gjnG4gjWkWa89ZoYUnl9snJ1cWIcTH/hvxZqfO+WjG6T8DRBpctEol5jw1O5rA8gkCokQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-escapes": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.16.7.tgz", + "integrity": "sha512-TAV5IGahIz3yZ9/Hfv35TV2xEm+kaBDaZQCn2S/hG9/CZ0DktxJv9eKfPc7yYCvOYR4JGx1h8C+jcSOvgaaI/Q==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-regex": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.16.7.tgz", + "integrity": "sha512-oC5tYYKw56HO75KZVLQ+R/Nl3Hro9kf8iG0hXoaHP7tjAyCpvqBiSNe6vGrZni1Z6MggmUOC6A7VP7AVmw225Q==", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/preset-env": { + "version": "7.17.10", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.17.10.tgz", + "integrity": "sha512-YNgyBHZQpeoBSRBg0xixsZzfT58Ze1iZrajvv0lJc70qDDGuGfonEnMGfWeSY0mQ3JTuCWFbMkzFRVafOyJx4g==", + "dependencies": { + "@babel/compat-data": "^7.17.10", + "@babel/helper-compilation-targets": "^7.17.10", + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/helper-validator-option": "^7.16.7", + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.16.7", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.16.7", + "@babel/plugin-proposal-async-generator-functions": "^7.16.8", + "@babel/plugin-proposal-class-properties": "^7.16.7", + "@babel/plugin-proposal-class-static-block": "^7.17.6", + "@babel/plugin-proposal-dynamic-import": "^7.16.7", + "@babel/plugin-proposal-export-namespace-from": "^7.16.7", + "@babel/plugin-proposal-json-strings": "^7.16.7", + "@babel/plugin-proposal-logical-assignment-operators": "^7.16.7", + "@babel/plugin-proposal-nullish-coalescing-operator": "^7.16.7", + "@babel/plugin-proposal-numeric-separator": "^7.16.7", + "@babel/plugin-proposal-object-rest-spread": "^7.17.3", + "@babel/plugin-proposal-optional-catch-binding": "^7.16.7", + "@babel/plugin-proposal-optional-chaining": "^7.16.7", + "@babel/plugin-proposal-private-methods": "^7.16.11", + "@babel/plugin-proposal-private-property-in-object": "^7.16.7", + "@babel/plugin-proposal-unicode-property-regex": "^7.16.7", + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-class-properties": "^7.12.13", + "@babel/plugin-syntax-class-static-block": "^7.14.5", + "@babel/plugin-syntax-dynamic-import": "^7.8.3", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5", + "@babel/plugin-syntax-top-level-await": "^7.14.5", + "@babel/plugin-transform-arrow-functions": "^7.16.7", + "@babel/plugin-transform-async-to-generator": "^7.16.8", + "@babel/plugin-transform-block-scoped-functions": "^7.16.7", + "@babel/plugin-transform-block-scoping": "^7.16.7", + "@babel/plugin-transform-classes": "^7.16.7", + "@babel/plugin-transform-computed-properties": "^7.16.7", + "@babel/plugin-transform-destructuring": "^7.17.7", + "@babel/plugin-transform-dotall-regex": "^7.16.7", + "@babel/plugin-transform-duplicate-keys": "^7.16.7", + "@babel/plugin-transform-exponentiation-operator": "^7.16.7", + "@babel/plugin-transform-for-of": "^7.16.7", + "@babel/plugin-transform-function-name": "^7.16.7", + "@babel/plugin-transform-literals": "^7.16.7", + "@babel/plugin-transform-member-expression-literals": "^7.16.7", + "@babel/plugin-transform-modules-amd": "^7.16.7", + "@babel/plugin-transform-modules-commonjs": "^7.17.9", + "@babel/plugin-transform-modules-systemjs": "^7.17.8", + "@babel/plugin-transform-modules-umd": "^7.16.7", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.17.10", + "@babel/plugin-transform-new-target": "^7.16.7", + "@babel/plugin-transform-object-super": "^7.16.7", + "@babel/plugin-transform-parameters": "^7.16.7", + "@babel/plugin-transform-property-literals": "^7.16.7", + "@babel/plugin-transform-regenerator": "^7.17.9", + "@babel/plugin-transform-reserved-words": "^7.16.7", + "@babel/plugin-transform-shorthand-properties": "^7.16.7", + "@babel/plugin-transform-spread": "^7.16.7", + "@babel/plugin-transform-sticky-regex": "^7.16.7", + "@babel/plugin-transform-template-literals": "^7.16.7", + "@babel/plugin-transform-typeof-symbol": "^7.16.7", + "@babel/plugin-transform-unicode-escapes": "^7.16.7", + "@babel/plugin-transform-unicode-regex": "^7.16.7", + "@babel/preset-modules": "^0.1.5", + "@babel/types": "^7.17.10", + "babel-plugin-polyfill-corejs2": "^0.3.0", + "babel-plugin-polyfill-corejs3": "^0.5.0", + "babel-plugin-polyfill-regenerator": "^0.3.0", + "core-js-compat": "^3.22.1", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/preset-env/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/preset-modules": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.5.tgz", + "integrity": "sha512-A57th6YRG7oR3cq/yt/Y84MvGgE0eJG2F1JLhKuyG+jFxEgrd/HAMJatiFtmOiZurz+0DkrvbheCLaV5f2JfjA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/plugin-proposal-unicode-property-regex": "^7.4.4", + "@babel/plugin-transform-dotall-regex": "^7.4.4", + "@babel/types": "^7.4.4", + "esutils": "^2.0.2" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/runtime": { + "version": "7.17.9", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.17.9.tgz", + "integrity": "sha512-lSiBBvodq29uShpWGNbgFdKYNiFDo5/HIYsaCEY9ff4sb10x9jizo2+pRrSyF4jKZCXqgzuqBOQKbUm90gQwJg==", + "dependencies": { + "regenerator-runtime": "^0.13.4" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/template": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.16.7.tgz", + "integrity": "sha512-I8j/x8kHUrbYRTUxXrrMbfCa7jxkE7tZre39x3kjr9hvI82cK1FfqLygotcWN5kdPGWcLdWMHpSBavse5tWw3w==", + "dependencies": { + "@babel/code-frame": "^7.16.7", + "@babel/parser": "^7.16.7", + "@babel/types": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.17.10", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.17.10.tgz", + "integrity": "sha512-VmbrTHQteIdUUQNTb+zE12SHS/xQVIShmBPhlNP12hD5poF2pbITW1Z4172d03HegaQWhLffdkRJYtAzp0AGcw==", + "dependencies": { + "@babel/code-frame": "^7.16.7", + "@babel/generator": "^7.17.10", + "@babel/helper-environment-visitor": "^7.16.7", + "@babel/helper-function-name": "^7.17.9", + "@babel/helper-hoist-variables": "^7.16.7", + "@babel/helper-split-export-declaration": "^7.16.7", + "@babel/parser": "^7.17.10", + "@babel/types": "^7.17.10", + "debug": "^4.1.0", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.17.10", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.17.10.tgz", + "integrity": "sha512-9O26jG0mBYfGkUYCYZRnBwbVLd1UZOICEr2Em6InB6jVfsAv1GKgwXHmrSg+WFWDmeKTA6vyTZiN8tCSM5Oo3A==", + "dependencies": { + "@babel/helper-validator-identifier": "^7.16.7", + "to-fast-properties": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@csstools/convert-colors": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@csstools/convert-colors/-/convert-colors-1.4.0.tgz", + "integrity": "sha512-5a6wqoJV/xEdbRNKVo6I4hO3VjyDq//8q2f9I6PBAvMesJHFauXDorcNCsr9RzvsZnaWi5NYCcfyqP1QeFHFbw==", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/@gar/promisify": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz", + "integrity": "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==" + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz", + "integrity": "sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==", + "dependencies": { + "@jridgewell/set-array": "^1.0.0", + "@jridgewell/sourcemap-codec": "^1.4.10" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.0.7.tgz", + "integrity": "sha512-8cXDaBBHOr2pQ7j77Y6Vp5VDT2sIqWyWQ56TjEq4ih/a4iST3dItRe8Q9fp0rrIl9DoKhWQtUQz/YpOxLkXbNA==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.1.tgz", + "integrity": "sha512-Ct5MqZkLGEXTVmQYbGtx9SVqD2fqwvdubdps5D3djjAkgkKwT918VNOz65pEHFaYTeWcukmJmH5SwsA9Tn2ObQ==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.13", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.13.tgz", + "integrity": "sha512-GryiOJmNcWbovBxTfZSF71V/mXbgcV3MewDe3kIMCLyIh5e7SKAeUZs+rMnJ8jkMolZ/4/VsdBmMrw3l+VdZ3w==" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.13.tgz", + "integrity": "sha512-o1xbKhp9qnIAoHJSWd6KlCZfqslL4valSF81H8ImioOAxluWYWOpWkpyktY2vnt4tbrX9XYaxovq6cgowaJp2w==", + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "node_modules/@koa/router": { + "version": "9.4.0", + "resolved": "https://registry.npmjs.org/@koa/router/-/router-9.4.0.tgz", + "integrity": "sha512-dOOXgzqaDoHu5qqMEPLKEgLz5CeIA7q8+1W62mCvFVCOqeC71UoTGJ4u1xUSOpIl2J1x2pqrNULkFteUeZW3/A==", + "dev": true, + "dependencies": { + "debug": "^4.1.1", + "http-errors": "^1.7.3", + "koa-compose": "^4.1.0", + "methods": "^1.1.2", + "path-to-regexp": "^6.1.0" + }, + "engines": { + "node": ">= 8.0.0" + } + }, + "node_modules/@koa/router/node_modules/depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/@koa/router/node_modules/http-errors": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz", + "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==", + "dev": true, + "dependencies": { + "depd": "~1.1.2", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@npmcli/fs": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-1.1.1.tgz", + "integrity": "sha512-8KG5RD0GVP4ydEzRn/I4BNDuxDtqVbOdm8675T49OIG/NGhaK0pjPX7ZcDlvKYbA+ulvVK3ztfcF4uBdOxuJbQ==", + "dependencies": { + "@gar/promisify": "^1.0.1", + "semver": "^7.3.5" + } + }, + "node_modules/@npmcli/move-file": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-1.1.2.tgz", + "integrity": "sha512-1SUf/Cg2GzGDyaf15aR9St9TWlb+XvbZXWpDx8YKs7MLzMH/BCeopv+y9vzrzgkfykCGuWOlSu3mZhj2+FQcrg==", + "dependencies": { + "mkdirp": "^1.0.4", + "rimraf": "^3.0.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@npmcli/move-file/node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@npmcli/move-file/node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@nuxt/babel-preset-app": { + "version": "2.15.8", + "resolved": "https://registry.npmjs.org/@nuxt/babel-preset-app/-/babel-preset-app-2.15.8.tgz", + "integrity": "sha512-z23bY5P7dLTmIbk0ZZ95mcEXIEER/mQCOqEp2vxnzG2nurks+vq6tNcUAXqME1Wl6aXWTXlqky5plBe7RQHzhQ==", + "dependencies": { + "@babel/compat-data": "^7.14.0", + "@babel/core": "^7.14.0", + "@babel/helper-compilation-targets": "^7.13.16", + "@babel/helper-module-imports": "^7.13.12", + "@babel/plugin-proposal-class-properties": "^7.13.0", + "@babel/plugin-proposal-decorators": "^7.13.15", + "@babel/plugin-proposal-nullish-coalescing-operator": "^7.13.8", + "@babel/plugin-proposal-optional-chaining": "^7.13.12", + "@babel/plugin-proposal-private-methods": "^7.13.0", + "@babel/plugin-transform-runtime": "^7.13.15", + "@babel/preset-env": "^7.14.1", + "@babel/runtime": "^7.14.0", + "@vue/babel-preset-jsx": "^1.2.4", + "core-js": "^2.6.5", + "core-js-compat": "^3.12.1", + "regenerator-runtime": "^0.13.7" + } + }, + "node_modules/@nuxt/babel-preset-app/node_modules/core-js": { + "version": "2.6.12", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz", + "integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==", + "deprecated": "core-js@<3.23.3 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Some versions have web compatibility issues. Please, upgrade your dependencies to the actual version of core-js.", + "hasInstallScript": true + }, + "node_modules/@nuxt/builder": { + "version": "2.15.8", + "resolved": "https://registry.npmjs.org/@nuxt/builder/-/builder-2.15.8.tgz", + "integrity": "sha512-WVhN874LFMdgRiJqpxmeKI+vh5lhCUBVOyR9PhL1m1V/GV3fb+Dqc1BKS6XgayrWAWavPLveCJmQ/FID0puOfQ==", + "dependencies": { + "@nuxt/devalue": "^1.2.5", + "@nuxt/utils": "2.15.8", + "@nuxt/vue-app": "2.15.8", + "@nuxt/webpack": "2.15.8", + "chalk": "^4.1.1", + "chokidar": "^3.5.1", + "consola": "^2.15.3", + "fs-extra": "^9.1.0", + "glob": "^7.1.7", + "hash-sum": "^2.0.0", + "ignore": "^5.1.8", + "lodash": "^4.17.21", + "pify": "^5.0.0", + "serialize-javascript": "^5.0.1", + "upath": "^2.0.1" + } + }, + "node_modules/@nuxt/cli": { + "version": "2.15.8", + "resolved": "https://registry.npmjs.org/@nuxt/cli/-/cli-2.15.8.tgz", + "integrity": "sha512-KcGIILW/dAjBKea1DHsuLCG1sNzhzETShwT23DhXWO304qL8ljf4ndYKzn2RenzauGRGz7MREta80CbJCkLSHw==", + "dependencies": { + "@nuxt/config": "2.15.8", + "@nuxt/utils": "2.15.8", + "boxen": "^5.0.1", + "chalk": "^4.1.1", + "compression": "^1.7.4", + "connect": "^3.7.0", + "consola": "^2.15.3", + "crc": "^3.8.0", + "defu": "^4.0.1", + "destr": "^1.1.0", + "execa": "^5.0.0", + "exit": "^0.1.2", + "fs-extra": "^9.1.0", + "globby": "^11.0.3", + "hable": "^3.0.0", + "lodash": "^4.17.21", + "minimist": "^1.2.5", + "opener": "1.5.2", + "pretty-bytes": "^5.6.0", + "semver": "^7.3.5", + "serve-static": "^1.14.1", + "std-env": "^2.3.0", + "upath": "^2.0.1", + "wrap-ansi": "^7.0.0" + }, + "bin": { + "nuxt-cli": "bin/nuxt-cli.js" + } + }, + "node_modules/@nuxt/cli/node_modules/defu": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/defu/-/defu-4.0.1.tgz", + "integrity": "sha512-lC+G0KvvWRbisQa50+iFelm3/eMmwo4IlBmfASOVlw9MZpHHyQeVsZxc5j23+TQy5ydgEoTVSrWl7ptou1kzJQ==" + }, + "node_modules/@nuxt/components": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@nuxt/components/-/components-2.2.1.tgz", + "integrity": "sha512-r1LHUzifvheTnJtYrMuA+apgsrEJbxcgFKIimeXKb+jl8TnPWdV3egmrxBCaDJchrtY/wmHyP47tunsft7AWwg==", + "dependencies": { + "chalk": "^4.1.2", + "chokidar": "^3.5.2", + "glob": "^7.1.7", + "globby": "^11.0.4", + "scule": "^0.2.1", + "semver": "^7.3.5", + "upath": "^2.0.1", + "vue-template-compiler": "^2.6.14" + }, + "peerDependencies": { + "consola": "*" + } + }, + "node_modules/@nuxt/config": { + "version": "2.15.8", + "resolved": "https://registry.npmjs.org/@nuxt/config/-/config-2.15.8.tgz", + "integrity": "sha512-KMQbjmUf9RVHeTZEf7zcuFnh03XKZioYhok6GOCY+leu3g5n/UhyPvLnTsgTfsLWohqoRoOm94u4A+tNYwn9VQ==", + "dependencies": { + "@nuxt/utils": "2.15.8", + "consola": "^2.15.3", + "defu": "^4.0.1", + "destr": "^1.1.0", + "dotenv": "^9.0.2", + "lodash": "^4.17.21", + "rc9": "^1.2.0", + "std-env": "^2.3.0", + "ufo": "^0.7.4" + } + }, + "node_modules/@nuxt/config/node_modules/defu": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/defu/-/defu-4.0.1.tgz", + "integrity": "sha512-lC+G0KvvWRbisQa50+iFelm3/eMmwo4IlBmfASOVlw9MZpHHyQeVsZxc5j23+TQy5ydgEoTVSrWl7ptou1kzJQ==" + }, + "node_modules/@nuxt/core": { + "version": "2.15.8", + "resolved": "https://registry.npmjs.org/@nuxt/core/-/core-2.15.8.tgz", + "integrity": "sha512-31pipWRvwHiyB5VDqffgSO7JtmHxyzgshIzuZzSinxMbVmK3BKsOwacD/51oEyELgrPlUgLqcY9dg+RURgmHGQ==", + "dependencies": { + "@nuxt/config": "2.15.8", + "@nuxt/server": "2.15.8", + "@nuxt/utils": "2.15.8", + "consola": "^2.15.3", + "fs-extra": "^9.1.0", + "hable": "^3.0.0", + "hash-sum": "^2.0.0", + "lodash": "^4.17.21" + } + }, + "node_modules/@nuxt/devalue": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/@nuxt/devalue/-/devalue-1.2.5.tgz", + "integrity": "sha512-Tg86C7tqzvZtZli2BQVqgzZN136mZDTgauvJXagglKkP2xt5Kw3NUIiJyjX0Ww/IZy2xVmD0LN+CEPpij4dB2g==", + "dependencies": { + "consola": "^2.9.0" + } + }, + "node_modules/@nuxt/friendly-errors-webpack-plugin": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/@nuxt/friendly-errors-webpack-plugin/-/friendly-errors-webpack-plugin-2.5.2.tgz", + "integrity": "sha512-LLc+90lnxVbpKkMqk5z1EWpXoODhc6gRkqqXJCInJwF5xabHAE7biFvbULfvTRmtaTzAaP8IV4HQDLUgeAUTTw==", + "dependencies": { + "chalk": "^2.3.2", + "consola": "^2.6.0", + "error-stack-parser": "^2.0.0", + "string-width": "^4.2.3" + }, + "engines": { + "node": ">=8.0.0", + "npm": ">=5.0.0" + }, + "peerDependencies": { + "webpack": "^2.0.0 || ^3.0.0 || ^4.0.0 || ^5.0.0" + } + }, + "node_modules/@nuxt/friendly-errors-webpack-plugin/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@nuxt/friendly-errors-webpack-plugin/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@nuxt/friendly-errors-webpack-plugin/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/@nuxt/friendly-errors-webpack-plugin/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" + }, + "node_modules/@nuxt/friendly-errors-webpack-plugin/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "engines": { + "node": ">=4" + } + }, + "node_modules/@nuxt/friendly-errors-webpack-plugin/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@nuxt/generator": { + "version": "2.15.8", + "resolved": "https://registry.npmjs.org/@nuxt/generator/-/generator-2.15.8.tgz", + "integrity": "sha512-hreLdYbBIe3SWcP8LsMG7OlDTx2ZVucX8+f8Vrjft3Q4r8iCwLMYC1s1N5etxeHAZfS2kZiLmF92iscOdfbgMQ==", + "dependencies": { + "@nuxt/utils": "2.15.8", + "chalk": "^4.1.1", + "consola": "^2.15.3", + "defu": "^4.0.1", + "devalue": "^2.0.1", + "fs-extra": "^9.1.0", + "html-minifier": "^4.0.0", + "node-html-parser": "^3.2.0", + "ufo": "^0.7.4" + } + }, + "node_modules/@nuxt/generator/node_modules/defu": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/defu/-/defu-4.0.1.tgz", + "integrity": "sha512-lC+G0KvvWRbisQa50+iFelm3/eMmwo4IlBmfASOVlw9MZpHHyQeVsZxc5j23+TQy5ydgEoTVSrWl7ptou1kzJQ==" + }, + "node_modules/@nuxt/loading-screen": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@nuxt/loading-screen/-/loading-screen-2.0.4.tgz", + "integrity": "sha512-xpEDAoRu75tLUYCkUJCIvJkWJSuwr8pqomvQ+fkXpSrkxZ/9OzlBFjAbVdOAWTMj4aV/LVQso4vcEdircKeFIQ==", + "dependencies": { + "connect": "^3.7.0", + "defu": "^5.0.0", + "get-port-please": "^2.2.0", + "node-res": "^5.0.1", + "serve-static": "^1.14.1" + } + }, + "node_modules/@nuxt/opencollective": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@nuxt/opencollective/-/opencollective-0.3.2.tgz", + "integrity": "sha512-XG7rUdXG9fcafu9KTDIYjJSkRO38EwjlKYIb5TQ/0WDbiTUTtUtgncMscKOYzfsY86kGs05pAuMOR+3Fi0aN3A==", + "dependencies": { + "chalk": "^4.1.0", + "consola": "^2.15.0", + "node-fetch": "^2.6.1" + }, + "bin": { + "opencollective": "bin/opencollective.js" + }, + "engines": { + "node": ">=8.0.0", + "npm": ">=5.0.0" + } + }, + "node_modules/@nuxt/postcss8": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@nuxt/postcss8/-/postcss8-1.1.3.tgz", + "integrity": "sha512-CdHtErhvQwueNZPBOmlAAKrNCK7aIpZDYhtS7TzXlSgPHHox1g3cSlf+Ke9oB/8t4mNNjdB+prclme2ibuCOEA==", + "dev": true, + "dependencies": { + "autoprefixer": "^10.2.5", + "css-loader": "^5.0.0", + "defu": "^3.2.2", + "postcss": "^8.1.10", + "postcss-import": "^13.0.0", + "postcss-loader": "^4.1.0", + "postcss-url": "^10.1.1", + "semver": "^7.3.4" + } + }, + "node_modules/@nuxt/postcss8/node_modules/defu": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/defu/-/defu-3.2.2.tgz", + "integrity": "sha512-8UWj5lNv7HD+kB0e9w77Z7TdQlbUYDVWqITLHNqFIn6khrNHv5WQo38Dcm1f6HeNyZf0U7UbPf6WeZDSdCzGDQ==", + "dev": true + }, + "node_modules/@nuxt/server": { + "version": "2.15.8", + "resolved": "https://registry.npmjs.org/@nuxt/server/-/server-2.15.8.tgz", + "integrity": "sha512-E4EtXudxtWQBUHMHOxFwm5DlPOkJbW+iF1+zc0dGmXLscep1KWPrlP+4nrpZj8/UKzpupamE8ZTS9I4IbnExVA==", + "dependencies": { + "@nuxt/utils": "2.15.8", + "@nuxt/vue-renderer": "2.15.8", + "@nuxtjs/youch": "^4.2.3", + "compression": "^1.7.4", + "connect": "^3.7.0", + "consola": "^2.15.3", + "etag": "^1.8.1", + "fresh": "^0.5.2", + "fs-extra": "^9.1.0", + "ip": "^1.1.5", + "launch-editor-middleware": "^2.2.1", + "on-headers": "^1.0.2", + "pify": "^5.0.0", + "serve-placeholder": "^1.2.3", + "serve-static": "^1.14.1", + "server-destroy": "^1.0.1", + "ufo": "^0.7.4" + } + }, + "node_modules/@nuxt/telemetry": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/@nuxt/telemetry/-/telemetry-1.3.6.tgz", + "integrity": "sha512-sZpLf/rU3cvN8/alR1HpJIl3mHPA1GOg41GKdOOrtw7Gi/lCEVk4hK+lpXgYInZ2n6i1JyknpKhM9YzX2RU33w==", + "dependencies": { + "arg": "^5.0.0", + "chalk": "^4.1.1", + "ci-info": "^3.1.1", + "consola": "^2.15.3", + "create-require": "^1.1.1", + "defu": "^5.0.0", + "destr": "^1.1.0", + "dotenv": "^9.0.2", + "fs-extra": "^8.1.0", + "git-url-parse": "^11.4.4", + "inquirer": "^7.3.3", + "is-docker": "^2.2.1", + "jiti": "^1.9.2", + "nanoid": "^3.1.23", + "node-fetch": "^2.6.1", + "parse-git-config": "^3.0.0", + "rc9": "^1.2.0", + "std-env": "^2.3.0" + }, + "bin": { + "nuxt-telemetry": "bin/nuxt-telemetry.js" + } + }, + "node_modules/@nuxt/telemetry/node_modules/fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "engines": { + "node": ">=6 <7 || >=8" + } + }, + "node_modules/@nuxt/telemetry/node_modules/jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/@nuxt/telemetry/node_modules/universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/@nuxt/types": { + "version": "2.15.8", + "resolved": "https://registry.npmjs.org/@nuxt/types/-/types-2.15.8.tgz", + "integrity": "sha512-zBAG5Fy+SIaZIerOVF1vxy1zz16ZK07QSbsuQAjdtEFlvr+vKK+0AqCv8r8DBY5IVqdMIaw5FgNUz5py0xWdPg==", + "dependencies": { + "@types/autoprefixer": "9.7.2", + "@types/babel__core": "7.1.14", + "@types/compression": "1.7.0", + "@types/connect": "3.4.34", + "@types/etag": "1.8.0", + "@types/file-loader": "5.0.0", + "@types/html-minifier": "4.0.0", + "@types/less": "3.0.2", + "@types/node": "12.20.12", + "@types/optimize-css-assets-webpack-plugin": "5.0.3", + "@types/pug": "2.0.4", + "@types/sass-loader": "8.0.1", + "@types/serve-static": "1.13.9", + "@types/terser-webpack-plugin": "4.2.1", + "@types/webpack": "4.41.28", + "@types/webpack-bundle-analyzer": "3.9.3", + "@types/webpack-dev-middleware": "4.1.2", + "@types/webpack-hot-middleware": "2.25.4", + "sass-loader": "10.1.1" + } + }, + "node_modules/@nuxt/utils": { + "version": "2.15.8", + "resolved": "https://registry.npmjs.org/@nuxt/utils/-/utils-2.15.8.tgz", + "integrity": "sha512-e0VBarUbPiQ4ZO1T58puoFIuXme7L5gk1QfwyxOONlp2ryE7aRyZ8X/mryuOiIeyP64c4nwSUtN7q9EUWRb7Lg==", + "dependencies": { + "consola": "^2.15.3", + "create-require": "^1.1.1", + "fs-extra": "^9.1.0", + "hash-sum": "^2.0.0", + "jiti": "^1.9.2", + "lodash": "^4.17.21", + "proper-lockfile": "^4.1.2", + "semver": "^7.3.5", + "serialize-javascript": "^5.0.1", + "signal-exit": "^3.0.3", + "ua-parser-js": "^0.7.28", + "ufo": "^0.7.4" + } + }, + "node_modules/@nuxt/vue-app": { + "version": "2.15.8", + "resolved": "https://registry.npmjs.org/@nuxt/vue-app/-/vue-app-2.15.8.tgz", + "integrity": "sha512-FJf9FSMPsWT3BqkS37zEuPTxLKzSg2EIwp1sP8Eou25eE08qxRfe2PwTVA8HnXUPNdpz2uk/T9DlNw+JraiFRQ==", + "dependencies": { + "node-fetch": "^2.6.1", + "ufo": "^0.7.4", + "unfetch": "^4.2.0", + "vue": "^2.6.12", + "vue-client-only": "^2.0.0", + "vue-meta": "^2.4.0", + "vue-no-ssr": "^1.1.1", + "vue-router": "^3.5.1", + "vue-template-compiler": "^2.6.12", + "vuex": "^3.6.2" + } + }, + "node_modules/@nuxt/vue-renderer": { + "version": "2.15.8", + "resolved": "https://registry.npmjs.org/@nuxt/vue-renderer/-/vue-renderer-2.15.8.tgz", + "integrity": "sha512-54I/k+4G6axP9XVYYdtH6M1S6T49OIkarpF6/yIJj0yi3S/2tdJ9eUyfoLZ9EbquZFDDRHBxSswTtr2l/eakPw==", + "dependencies": { + "@nuxt/devalue": "^1.2.5", + "@nuxt/utils": "2.15.8", + "consola": "^2.15.3", + "defu": "^4.0.1", + "fs-extra": "^9.1.0", + "lodash": "^4.17.21", + "lru-cache": "^5.1.1", + "ufo": "^0.7.4", + "vue": "^2.6.12", + "vue-meta": "^2.4.0", + "vue-server-renderer": "^2.6.12" + } + }, + "node_modules/@nuxt/vue-renderer/node_modules/defu": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/defu/-/defu-4.0.1.tgz", + "integrity": "sha512-lC+G0KvvWRbisQa50+iFelm3/eMmwo4IlBmfASOVlw9MZpHHyQeVsZxc5j23+TQy5ydgEoTVSrWl7ptou1kzJQ==" + }, + "node_modules/@nuxt/webpack": { + "version": "2.15.8", + "resolved": "https://registry.npmjs.org/@nuxt/webpack/-/webpack-2.15.8.tgz", + "integrity": "sha512-CzJYFed23Ow/UK0+cI1FVthDre1p2qc8Q97oizG39d3/SIh3aUHjgj8c60wcR+RSxVO0FzZMXkmq02NmA7vWJg==", + "dependencies": { + "@babel/core": "^7.14.0", + "@nuxt/babel-preset-app": "2.15.8", + "@nuxt/friendly-errors-webpack-plugin": "^2.5.1", + "@nuxt/utils": "2.15.8", + "babel-loader": "^8.2.2", + "cache-loader": "^4.1.0", + "caniuse-lite": "^1.0.30001228", + "consola": "^2.15.3", + "css-loader": "^4.3.0", + "cssnano": "^4.1.11", + "eventsource-polyfill": "^0.9.6", + "extract-css-chunks-webpack-plugin": "^4.9.0", + "file-loader": "^6.2.0", + "glob": "^7.1.7", + "hard-source-webpack-plugin": "^0.13.1", + "hash-sum": "^2.0.0", + "html-webpack-plugin": "^4.5.1", + "lodash": "^4.17.21", + "memory-fs": "^0.5.0", + "optimize-css-assets-webpack-plugin": "^5.0.4", + "pify": "^5.0.0", + "pnp-webpack-plugin": "^1.6.4", + "postcss": "^7.0.32", + "postcss-import": "^12.0.1", + "postcss-import-resolver": "^2.0.0", + "postcss-loader": "^3.0.0", + "postcss-preset-env": "^6.7.0", + "postcss-url": "^8.0.0", + "semver": "^7.3.5", + "std-env": "^2.3.0", + "style-resources-loader": "^1.4.1", + "terser-webpack-plugin": "^4.2.3", + "thread-loader": "^3.0.4", + "time-fix-plugin": "^2.0.7", + "ufo": "^0.7.4", + "url-loader": "^4.1.1", + "vue-loader": "^15.9.7", + "vue-style-loader": "^4.1.3", + "vue-template-compiler": "^2.6.12", + "webpack": "^4.46.0", + "webpack-bundle-analyzer": "^4.4.1", + "webpack-dev-middleware": "^4.2.0", + "webpack-hot-middleware": "^2.25.0", + "webpack-node-externals": "^3.0.0", + "webpackbar": "^4.0.0" + } + }, + "node_modules/@nuxt/webpack/node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@nuxt/webpack/node_modules/css-loader": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-4.3.0.tgz", + "integrity": "sha512-rdezjCjScIrsL8BSYszgT4s476IcNKt6yX69t0pHjJVnPUTDpn4WfIpDQTN3wCJvUvfsz/mFjuGOekf3PY3NUg==", + "dependencies": { + "camelcase": "^6.0.0", + "cssesc": "^3.0.0", + "icss-utils": "^4.1.1", + "loader-utils": "^2.0.0", + "postcss": "^7.0.32", + "postcss-modules-extract-imports": "^2.0.0", + "postcss-modules-local-by-default": "^3.0.3", + "postcss-modules-scope": "^2.2.0", + "postcss-modules-values": "^3.0.0", + "postcss-value-parser": "^4.1.0", + "schema-utils": "^2.7.1", + "semver": "^7.3.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^4.27.0 || ^5.0.0" + } + }, + "node_modules/@nuxt/webpack/node_modules/icss-utils": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-4.1.1.tgz", + "integrity": "sha512-4aFq7wvWyMHKgxsH8QQtGpvbASCf+eM3wPRLI6R+MgAnTCZ6STYsRvttLvRWK0Nfif5piF394St3HeJDaljGPA==", + "dependencies": { + "postcss": "^7.0.14" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/@nuxt/webpack/node_modules/json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" + } + }, + "node_modules/@nuxt/webpack/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "node_modules/@nuxt/webpack/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/@nuxt/webpack/node_modules/postcss-import": { + "version": "12.0.1", + "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-12.0.1.tgz", + "integrity": "sha512-3Gti33dmCjyKBgimqGxL3vcV8w9+bsHwO5UrBawp796+jdardbcFl4RP5w/76BwNL7aGzpKstIfF9I+kdE8pTw==", + "dependencies": { + "postcss": "^7.0.1", + "postcss-value-parser": "^3.2.3", + "read-cache": "^1.0.0", + "resolve": "^1.1.7" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@nuxt/webpack/node_modules/postcss-import/node_modules/postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==" + }, + "node_modules/@nuxt/webpack/node_modules/postcss-load-config": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-2.1.2.tgz", + "integrity": "sha512-/rDeGV6vMUo3mwJZmeHfEDvwnTKKqQ0S7OHUi/kJvvtx3aWtyWG2/0ZWnzCt2keEclwN6Tf0DST2v9kITdOKYw==", + "dependencies": { + "cosmiconfig": "^5.0.0", + "import-cwd": "^2.0.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/@nuxt/webpack/node_modules/postcss-loader": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-3.0.0.tgz", + "integrity": "sha512-cLWoDEY5OwHcAjDnkyRQzAXfs2jrKjXpO/HQFcc5b5u/r7aa471wdmChmwfnv7x2u840iat/wi0lQ5nbRgSkUA==", + "dependencies": { + "loader-utils": "^1.1.0", + "postcss": "^7.0.0", + "postcss-load-config": "^2.0.0", + "schema-utils": "^1.0.0" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/@nuxt/webpack/node_modules/postcss-loader/node_modules/loader-utils": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", + "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", + "dependencies": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^1.0.1" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/@nuxt/webpack/node_modules/postcss-loader/node_modules/schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "dependencies": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + }, + "engines": { + "node": ">= 4" + } + }, + "node_modules/@nuxt/webpack/node_modules/postcss-modules-extract-imports": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-2.0.0.tgz", + "integrity": "sha512-LaYLDNS4SG8Q5WAWqIJgdHPJrDDr/Lv775rMBFUbgjTz6j34lUznACHcdRWroPvXANP2Vj7yNK57vp9eFqzLWQ==", + "dependencies": { + "postcss": "^7.0.5" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/@nuxt/webpack/node_modules/postcss-modules-local-by-default": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-3.0.3.tgz", + "integrity": "sha512-e3xDq+LotiGesympRlKNgaJ0PCzoUIdpH0dj47iWAui/kyTgh3CiAr1qP54uodmJhl6p9rN6BoNcdEDVJx9RDw==", + "dependencies": { + "icss-utils": "^4.1.1", + "postcss": "^7.0.32", + "postcss-selector-parser": "^6.0.2", + "postcss-value-parser": "^4.1.0" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/@nuxt/webpack/node_modules/postcss-modules-scope": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-2.2.0.tgz", + "integrity": "sha512-YyEgsTMRpNd+HmyC7H/mh3y+MeFWevy7V1evVhJWewmMbjDHIbZbOXICC2y+m1xI1UVfIT1HMW/O04Hxyu9oXQ==", + "dependencies": { + "postcss": "^7.0.6", + "postcss-selector-parser": "^6.0.0" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/@nuxt/webpack/node_modules/postcss-modules-values": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-3.0.0.tgz", + "integrity": "sha512-1//E5jCBrZ9DmRX+zCtmQtRSV6PV42Ix7Bzj9GbwJceduuf7IqP8MgeTXuRDHOWj2m0VzZD5+roFWDuU8RQjcg==", + "dependencies": { + "icss-utils": "^4.0.0", + "postcss": "^7.0.6" + } + }, + "node_modules/@nuxt/webpack/node_modules/postcss-url": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/postcss-url/-/postcss-url-8.0.0.tgz", + "integrity": "sha512-E2cbOQ5aii2zNHh8F6fk1cxls7QVFZjLPSrqvmiza8OuXLzIpErij8BDS5Y3STPfJgpIMNCPEr8JlKQWEoozUw==", + "dependencies": { + "mime": "^2.3.1", + "minimatch": "^3.0.4", + "mkdirp": "^0.5.0", + "postcss": "^7.0.2", + "xxhashjs": "^0.2.1" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@nuxt/webpack/node_modules/schema-utils": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz", + "integrity": "sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==", + "dependencies": { + "@types/json-schema": "^7.0.5", + "ajv": "^6.12.4", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 8.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/@nuxtjs/axios": { + "version": "5.13.6", + "resolved": "https://registry.npmjs.org/@nuxtjs/axios/-/axios-5.13.6.tgz", + "integrity": "sha512-XS+pOE0xsDODs1zAIbo95A0LKlilvJi8YW0NoXYuq3/jjxGgWDxizZ6Yx0AIIjZOoGsXJOPc0/BcnSEUQ2mFBA==", + "dependencies": { + "@nuxtjs/proxy": "^2.1.0", + "axios": "^0.21.1", + "axios-retry": "^3.1.9", + "consola": "^2.15.3", + "defu": "^5.0.0" + } + }, + "node_modules/@nuxtjs/proxy": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@nuxtjs/proxy/-/proxy-2.1.0.tgz", + "integrity": "sha512-/qtoeqXgZ4Mg6LRg/gDUZQrFpOlOdHrol/vQYMnKu3aN3bP90UfOUB3QSDghUUK7OISAJ0xp8Ld78aHyCTcKCQ==", + "dependencies": { + "http-proxy-middleware": "^1.0.6" + } + }, + "node_modules/@nuxtjs/pwa": { + "version": "3.3.5", + "resolved": "https://registry.npmjs.org/@nuxtjs/pwa/-/pwa-3.3.5.tgz", + "integrity": "sha512-8tTmW8DBspWxlJwTimOHTkwfkwPpL9wIcGmy75Gcmin+c9YtX2Ehxmhgt/TLFOC9XsLAqojqynw3/Agr/9OE1w==", + "dev": true, + "dependencies": { + "clone-deep": "^4.0.1", + "defu": "^3.2.2", + "execa": "^5.0.0", + "fs-extra": "^9.1.0", + "hasha": "^5.2.2", + "jimp-compact": "^0.16.1", + "lodash.template": "^4.5.0", + "serve-static": "^1.14.1", + "workbox-cdn": "^5.1.4" + } + }, + "node_modules/@nuxtjs/pwa/node_modules/defu": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/defu/-/defu-3.2.2.tgz", + "integrity": "sha512-8UWj5lNv7HD+kB0e9w77Z7TdQlbUYDVWqITLHNqFIn6khrNHv5WQo38Dcm1f6HeNyZf0U7UbPf6WeZDSdCzGDQ==", + "dev": true + }, + "node_modules/@nuxtjs/tailwindcss": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@nuxtjs/tailwindcss/-/tailwindcss-4.2.1.tgz", + "integrity": "sha512-Sku7VETunn5YmvzkXFDuRdP1gUGau02eh5HtcAsI9//1hpSuEN49n3XhatBrPOXQ57WhUlnjXf0/LjT9KQH0+A==", + "dev": true, + "dependencies": { + "@nuxt/postcss8": "^1.1.3", + "autoprefixer": "^10.2.5", + "chalk": "^4.1.1", + "clear-module": "^4.1.1", + "consola": "^2.15.3", + "defu": "^5.0.0", + "postcss": "^8.3.5", + "postcss-custom-properties": "^11.0.0", + "postcss-nesting": "^8.0.1", + "tailwind-config-viewer": "^1.6.2", + "tailwindcss": "^2.2.2", + "ufo": "^0.7.5" + } + }, + "node_modules/@nuxtjs/tailwindcss/node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/@nuxtjs/tailwindcss/node_modules/color": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz", + "integrity": "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1", + "color-string": "^1.9.0" + }, + "engines": { + "node": ">=12.5.0" + } + }, + "node_modules/@nuxtjs/tailwindcss/node_modules/cosmiconfig": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.0.1.tgz", + "integrity": "sha512-a1YWNUV2HwGimB7dU2s1wUMurNKjpx60HxBB6xUM8Re+2s1g1IIfJvFR0/iCF+XHdE0GMTKTuLR32UQff4TEyQ==", + "dev": true, + "dependencies": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.2.1", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.10.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@nuxtjs/tailwindcss/node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@nuxtjs/tailwindcss/node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/@nuxtjs/tailwindcss/node_modules/html-tags": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-3.2.0.tgz", + "integrity": "sha512-vy7ClnArOZwCnqZgvv+ddgHgJiAFXe3Ge9ML5/mBctVJoUoYPCdxVucOywjDARn6CVoh3dRSFdPHy2sX80L0Wg==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@nuxtjs/tailwindcss/node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@nuxtjs/tailwindcss/node_modules/object-hash": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-2.2.0.tgz", + "integrity": "sha512-gScRMn0bS5fH+IuwyIFgnh9zBdo4DV+6GhygmWM9HyNJSgS0hScp1f5vjtm7oIIOiT9trXrShAkLFSc2IqKNgw==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/@nuxtjs/tailwindcss/node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@nuxtjs/tailwindcss/node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@nuxtjs/tailwindcss/node_modules/postcss-js": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-3.0.3.tgz", + "integrity": "sha512-gWnoWQXKFw65Hk/mi2+WTQTHdPD5UJdDXZmX073EY/B3BWnYjO4F4t0VneTCnCGQ5E5GsCdMkzPaTXwl3r5dJw==", + "dev": true, + "dependencies": { + "camelcase-css": "^2.0.1", + "postcss": "^8.1.6" + }, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/@nuxtjs/tailwindcss/node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@nuxtjs/tailwindcss/node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@nuxtjs/tailwindcss/node_modules/tailwindcss": { + "version": "2.2.19", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-2.2.19.tgz", + "integrity": "sha512-6Ui7JSVtXadtTUo2NtkBBacobzWiQYVjYW0ZnKaP9S1ZCKQ0w7KVNz+YSDI/j7O7KCMHbOkz94ZMQhbT9pOqjw==", + "dev": true, + "dependencies": { + "arg": "^5.0.1", + "bytes": "^3.0.0", + "chalk": "^4.1.2", + "chokidar": "^3.5.2", + "color": "^4.0.1", + "cosmiconfig": "^7.0.1", + "detective": "^5.2.0", + "didyoumean": "^1.2.2", + "dlv": "^1.1.3", + "fast-glob": "^3.2.7", + "fs-extra": "^10.0.0", + "glob-parent": "^6.0.1", + "html-tags": "^3.1.0", + "is-color-stop": "^1.1.0", + "is-glob": "^4.0.1", + "lodash": "^4.17.21", + "lodash.topath": "^4.5.2", + "modern-normalize": "^1.1.0", + "node-emoji": "^1.11.0", + "normalize-path": "^3.0.0", + "object-hash": "^2.2.0", + "postcss-js": "^3.0.3", + "postcss-load-config": "^3.1.0", + "postcss-nested": "5.0.6", + "postcss-selector-parser": "^6.0.6", + "postcss-value-parser": "^4.1.0", + "pretty-hrtime": "^1.0.3", + "purgecss": "^4.0.3", + "quick-lru": "^5.1.1", + "reduce-css-calc": "^2.1.8", + "resolve": "^1.20.0", + "tmp": "^0.2.1" + }, + "bin": { + "tailwind": "lib/cli.js", + "tailwindcss": "lib/cli.js" + }, + "engines": { + "node": ">=12.13.0" + }, + "peerDependencies": { + "autoprefixer": "^10.0.2", + "postcss": "^8.0.9" + } + }, + "node_modules/@nuxtjs/tailwindcss/node_modules/tmp": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", + "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==", + "dev": true, + "dependencies": { + "rimraf": "^3.0.0" + }, + "engines": { + "node": ">=8.17.0" + } + }, + "node_modules/@nuxtjs/youch": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/@nuxtjs/youch/-/youch-4.2.3.tgz", + "integrity": "sha512-XiTWdadTwtmL/IGkNqbVe+dOlT+IMvcBu7TvKI7plWhVQeBCQ9iKhk3jgvVWFyiwL2yHJDlEwOM5v9oVES5Xmw==", + "dependencies": { + "cookie": "^0.3.1", + "mustache": "^2.3.0", + "stack-trace": "0.0.10" + } + }, + "node_modules/@polka/url": { + "version": "1.0.0-next.21", + "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.21.tgz", + "integrity": "sha512-a5Sab1C4/icpTZVzZc5Ghpz88yQtGOyNqYXcZgOssB2uuAr+wF/MvN6bgtW32q7HHrvBki+BsZ0OuNv6EV3K9g==" + }, + "node_modules/@socket.io/component-emitter": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.0.tgz", + "integrity": "sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg==" + }, + "node_modules/@types/anymatch": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/anymatch/-/anymatch-3.0.0.tgz", + "integrity": "sha512-qLChUo6yhpQ9k905NwL74GU7TxH+9UODwwQ6ICNI+O6EDMExqH/Cv9NsbmcZ7yC/rRXJ/AHCzfgjsFRY5fKjYw==", + "deprecated": "This is a stub types definition. anymatch provides its own type definitions, so you do not need this installed.", + "dependencies": { + "anymatch": "*" + } + }, + "node_modules/@types/autoprefixer": { + "version": "9.7.2", + "resolved": "https://registry.npmjs.org/@types/autoprefixer/-/autoprefixer-9.7.2.tgz", + "integrity": "sha512-QX7U7YW3zX3ex6MECtWO9folTGsXeP4b8bSjTq3I1ODM+H+sFHwGKuof+T+qBcDClGlCGtDb3SVfiTVfmcxw4g==", + "dependencies": { + "@types/browserslist": "*", + "postcss": "7.x.x" + } + }, + "node_modules/@types/autoprefixer/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "node_modules/@types/autoprefixer/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/@types/babel__core": { + "version": "7.1.14", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.14.tgz", + "integrity": "sha512-zGZJzzBUVDo/eV6KgbE0f0ZI7dInEYvo12Rb70uNQDshC3SkRMb67ja0GgRHZgAX3Za6rhaWlvbDO8rrGyAb1g==", + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "node_modules/@types/babel__generator": { + "version": "7.6.4", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.4.tgz", + "integrity": "sha512-tFkciB9j2K755yrTALxD44McOrk+gfpIpvC3sxHjRawj6PfnQxrse4Clq5y/Rq+G3mrBurMax/lG8Qn2t9mSsg==", + "dependencies": { + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__template": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.1.tgz", + "integrity": "sha512-azBFKemX6kMg5Io+/rdGT0dkGreboUVR0Cdm3fz9QJWpaQGJRQXl7C+6hOTCZcMll7KFyEQpgbYI2lHdsS4U7g==", + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__traverse": { + "version": "7.17.1", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.17.1.tgz", + "integrity": "sha512-kVzjari1s2YVi77D3w1yuvohV2idweYXMCDzqBiVNN63TcDWrIlTVOYpqVrvbbyOE/IyzBoTKF0fdnLPEORFxA==", + "dependencies": { + "@babel/types": "^7.3.0" + } + }, + "node_modules/@types/body-parser": { + "version": "1.19.2", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz", + "integrity": "sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==", + "dependencies": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "node_modules/@types/browserslist": { + "version": "4.15.0", + "resolved": "https://registry.npmjs.org/@types/browserslist/-/browserslist-4.15.0.tgz", + "integrity": "sha512-h9LyKErRGZqMsHh9bd+FE8yCIal4S0DxKTOeui56VgVXqa66TKiuaIUxCAI7c1O0LjaUzOTcsMyOpO9GetozRA==", + "deprecated": "This is a stub types definition. browserslist provides its own type definitions, so you do not need this installed.", + "dependencies": { + "browserslist": "*" + } + }, + "node_modules/@types/clean-css": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/@types/clean-css/-/clean-css-4.2.5.tgz", + "integrity": "sha512-NEzjkGGpbs9S9fgC4abuBvTpVwE3i+Acu9BBod3PUyjDVZcNsGx61b8r2PphR61QGPnn0JHVs5ey6/I4eTrkxw==", + "dependencies": { + "@types/node": "*", + "source-map": "^0.6.0" + } + }, + "node_modules/@types/component-emitter": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/@types/component-emitter/-/component-emitter-1.2.11.tgz", + "integrity": "sha512-SRXjM+tfsSlA9VuG8hGO2nft2p8zjXCK1VcC6N4NXbBbYbSia9kzCChYQajIjzIqOOOuh5Ock6MmV2oux4jDZQ==" + }, + "node_modules/@types/compression": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@types/compression/-/compression-1.7.0.tgz", + "integrity": "sha512-3LzWUM+3k3XdWOUk/RO+uSjv7YWOatYq2QADJntK1pjkk4DfVP0KrIEPDnXRJxAAGKe0VpIPRmlINLDuCedZWw==", + "dependencies": { + "@types/express": "*" + } + }, + "node_modules/@types/connect": { + "version": "3.4.34", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.34.tgz", + "integrity": "sha512-ePPA/JuI+X0vb+gSWlPKOY0NdNAie/rPUqX2GUPpbZwiKTkSPhjXWuee47E4MtE54QVzGCQMQkAL6JhV2E1+cQ==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/cookie": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.4.1.tgz", + "integrity": "sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==" + }, + "node_modules/@types/cors": { + "version": "2.8.12", + "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.12.tgz", + "integrity": "sha512-vt+kDhq/M2ayberEtJcIN/hxXy1Pk+59g2FV/ZQceeaTyCtCucjL2Q7FXlFjtWn4n15KCr1NE2lNNFhp0lEThw==" + }, + "node_modules/@types/etag": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@types/etag/-/etag-1.8.0.tgz", + "integrity": "sha512-EdSN0x+Y0/lBv7YAb8IU4Jgm6DWM+Bqtz7o5qozl96fzaqdqbdfHS5qjdpFeIv7xQ8jSLyjMMNShgYtMajEHyQ==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/express": { + "version": "4.17.13", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.13.tgz", + "integrity": "sha512-6bSZTPaTIACxn48l50SR+axgrqm6qXFIxrdAKaG6PaJk3+zuUr35hBlgT7vOmJcum+OEaIBLtHV/qloEAFITeA==", + "dependencies": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^4.17.18", + "@types/qs": "*", + "@types/serve-static": "*" + } + }, + "node_modules/@types/express-serve-static-core": { + "version": "4.17.28", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.28.tgz", + "integrity": "sha512-P1BJAEAW3E2DJUlkgq4tOL3RyMunoWXqbSCygWo5ZIWTjUgN1YnaXWW4VWl/oc8vs/XoYibEGBKP0uZyF4AHig==", + "dependencies": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*" + } + }, + "node_modules/@types/file-loader": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@types/file-loader/-/file-loader-5.0.0.tgz", + "integrity": "sha512-evodFzM0PLOXmMZy8DhPN+toP6QgJiIteF6e8iD9T0xGBUllQA/DAb1nZwCIoNh7vuLvqCGPUdsLf3GSbcHd4g==", + "dependencies": { + "@types/webpack": "^4" + } + }, + "node_modules/@types/html-minifier": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@types/html-minifier/-/html-minifier-4.0.0.tgz", + "integrity": "sha512-eFnGhrKmjWBlnSGNtunetE3UU2Tc/LUl92htFslSSTmpp9EKHQVcYQadCyYfnzUEFB5G/3wLWo/USQS/mEPKrA==", + "dependencies": { + "@types/clean-css": "*", + "@types/relateurl": "*", + "@types/uglify-js": "*" + } + }, + "node_modules/@types/html-minifier-terser": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-5.1.2.tgz", + "integrity": "sha512-h4lTMgMJctJybDp8CQrxTUiiYmedihHWkjnF/8Pxseu2S6Nlfcy8kwboQ8yejh456rP2yWoEVm1sS/FVsfM48w==" + }, + "node_modules/@types/http-proxy": { + "version": "1.17.9", + "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.9.tgz", + "integrity": "sha512-QsbSjA/fSk7xB+UXlCT3wHBy5ai9wOcNDWwZAtud+jXhwOM3l+EYZh8Lng4+/6n8uar0J7xILzqftJdJ/Wdfkw==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/json-schema": { + "version": "7.0.11", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz", + "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==" + }, + "node_modules/@types/less": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/less/-/less-3.0.2.tgz", + "integrity": "sha512-62vfe65cMSzYaWmpmhqCMMNl0khen89w57mByPi1OseGfcV/LV03fO8YVrNj7rFQsRWNJo650WWyh6m7p8vZmA==" + }, + "node_modules/@types/localforage": { + "version": "0.0.34", + "resolved": "https://registry.npmjs.org/@types/localforage/-/localforage-0.0.34.tgz", + "integrity": "sha1-XjHDLdh5HsS5/z70fJy1Wy0NlDg=", + "deprecated": "This is a stub types definition for localforage (https://github.com/localForage/localForage). localforage provides its own type definitions, so you don't need @types/localforage installed!", + "dependencies": { + "localforage": "*" + } + }, + "node_modules/@types/mime": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz", + "integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==" + }, + "node_modules/@types/node": { + "version": "12.20.12", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.12.tgz", + "integrity": "sha512-KQZ1al2hKOONAs2MFv+yTQP1LkDWMrRJ9YCVRalXltOfXsBmH5IownLxQaiq0lnAHwAViLnh2aTYqrPcRGEbgg==" + }, + "node_modules/@types/node-sass": { + "version": "4.11.2", + "resolved": "https://registry.npmjs.org/@types/node-sass/-/node-sass-4.11.2.tgz", + "integrity": "sha512-pOFlTw/OtZda4e+yMjq6/QYuvY0RDMQ+mxXdWj7rfSyf18V8hS4SfgurO+MasAkQsv6Wt6edOGlwh5QqJml9gw==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/optimize-css-assets-webpack-plugin": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/@types/optimize-css-assets-webpack-plugin/-/optimize-css-assets-webpack-plugin-5.0.3.tgz", + "integrity": "sha512-PJgbI4KplJfyxKWVrBbEL+rePEBqeozJRMT0mBL3ynhvngASBV/XJ+BneLuJN74RjjMzO0gA5ns80mgubQdZAA==", + "dependencies": { + "@types/webpack": "^4" + } + }, + "node_modules/@types/parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==", + "dev": true + }, + "node_modules/@types/pug": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@types/pug/-/pug-2.0.4.tgz", + "integrity": "sha1-h3L80EGOPNLMFxVV1zAHQVBR9LI=" + }, + "node_modules/@types/q": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@types/q/-/q-1.5.5.tgz", + "integrity": "sha512-L28j2FcJfSZOnL1WBjDYp2vUHCeIFlyYI/53EwD/rKUBQ7MtUUfbQWiyKJGpcnv4/WgrhWsFKrcPstcAt/J0tQ==" + }, + "node_modules/@types/qs": { + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz", + "integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==" + }, + "node_modules/@types/range-parser": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz", + "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==" + }, + "node_modules/@types/relateurl": { + "version": "0.2.29", + "resolved": "https://registry.npmjs.org/@types/relateurl/-/relateurl-0.2.29.tgz", + "integrity": "sha512-QSvevZ+IRww2ldtfv1QskYsqVVVwCKQf1XbwtcyyoRvLIQzfyPhj/C+3+PKzSDRdiyejaiLgnq//XTkleorpLg==" + }, + "node_modules/@types/sass": { + "version": "1.43.1", + "resolved": "https://registry.npmjs.org/@types/sass/-/sass-1.43.1.tgz", + "integrity": "sha512-BPdoIt1lfJ6B7rw35ncdwBZrAssjcwzI5LByIrYs+tpXlj/CAkuVdRsgZDdP4lq5EjyWzwxZCqAoFyHKFwp32g==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/sass-loader": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@types/sass-loader/-/sass-loader-8.0.1.tgz", + "integrity": "sha512-kum0/5Im5K2WdDTRsLtrXXvX2VJc3rgq9favK+vIdWLn35miWUIYuPkiQlLCHks9//sZ3GWYs4uYzCdmoKKLcQ==", + "dependencies": { + "@types/node-sass": "*", + "@types/sass": "*", + "@types/webpack": "^4" + } + }, + "node_modules/@types/serve-static": { + "version": "1.13.9", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.9.tgz", + "integrity": "sha512-ZFqF6qa48XsPdjXV5Gsz0Zqmux2PerNd3a/ktL45mHpa19cuMi/cL8tcxdAx497yRh+QtYPuofjT9oWw9P7nkA==", + "dependencies": { + "@types/mime": "^1", + "@types/node": "*" + } + }, + "node_modules/@types/source-list-map": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/@types/source-list-map/-/source-list-map-0.1.2.tgz", + "integrity": "sha512-K5K+yml8LTo9bWJI/rECfIPrGgxdpeNbj+d53lwN4QjW1MCwlkhUms+gtdzigTeUyBr09+u8BwOIY3MXvHdcsA==" + }, + "node_modules/@types/tapable": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/tapable/-/tapable-1.0.8.tgz", + "integrity": "sha512-ipixuVrh2OdNmauvtT51o3d8z12p6LtFW9in7U79der/kwejjdNchQC5UMn5u/KxNoM7VHHOs/l8KS8uHxhODQ==" + }, + "node_modules/@types/terser-webpack-plugin": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@types/terser-webpack-plugin/-/terser-webpack-plugin-4.2.1.tgz", + "integrity": "sha512-x688KsgQKJF8PPfv4qSvHQztdZNHLlWJdolN9/ptAGimHVy3rY+vHdfglQDFh1Z39h7eMWOd6fQ7ke3PKQcdyA==", + "dependencies": { + "@types/webpack": "^4", + "terser": "^4.6.13" + } + }, + "node_modules/@types/uglify-js": { + "version": "3.13.2", + "resolved": "https://registry.npmjs.org/@types/uglify-js/-/uglify-js-3.13.2.tgz", + "integrity": "sha512-/xFrPIo+4zOeNGtVMbf9rUm0N+i4pDf1ynExomqtokIJmVzR3962lJ1UE+MmexMkA0cmN9oTzg5Xcbwge0Ij2Q==", + "dependencies": { + "source-map": "^0.6.1" + } + }, + "node_modules/@types/webpack": { + "version": "4.41.28", + "resolved": "https://registry.npmjs.org/@types/webpack/-/webpack-4.41.28.tgz", + "integrity": "sha512-Nn84RAiJjKRfPFFCVR8LC4ueTtTdfWAMZ03THIzZWRJB+rX24BD3LqPSFnbMscWauEsT4segAsylPDIaZyZyLQ==", + "dependencies": { + "@types/anymatch": "*", + "@types/node": "*", + "@types/tapable": "^1", + "@types/uglify-js": "*", + "@types/webpack-sources": "*", + "source-map": "^0.6.0" + } + }, + "node_modules/@types/webpack-bundle-analyzer": { + "version": "3.9.3", + "resolved": "https://registry.npmjs.org/@types/webpack-bundle-analyzer/-/webpack-bundle-analyzer-3.9.3.tgz", + "integrity": "sha512-l/vaDMWGcXiMB3CbczpyICivLTB07/JNtn1xebsRXE9tPaUDEHgX3x7YP6jfznG5TOu7I4w0Qx1tZz61znmPmg==", + "dependencies": { + "@types/webpack": "^4" + } + }, + "node_modules/@types/webpack-dev-middleware": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/@types/webpack-dev-middleware/-/webpack-dev-middleware-4.1.2.tgz", + "integrity": "sha512-SxXzPCqeZ03fJ2dg3iD7cSXvqZymmS5/2GD9fANRcyWN7HYK1H3ty6q7IInXZKvPrdUqij831G3RLIeKK6aGdw==", + "dependencies": { + "@types/connect": "*", + "@types/webpack": "^4" + } + }, + "node_modules/@types/webpack-hot-middleware": { + "version": "2.25.4", + "resolved": "https://registry.npmjs.org/@types/webpack-hot-middleware/-/webpack-hot-middleware-2.25.4.tgz", + "integrity": "sha512-6tQb9EBKIANZYUVLQYWiWfDFVe7FhXSj4bB2EF5QB7VtYWL3HDR+y/zqjZPAnCorv0spLqVMRqjRK8AmhfocMw==", + "dependencies": { + "@types/connect": "*", + "@types/webpack": "^4" + } + }, + "node_modules/@types/webpack-sources": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@types/webpack-sources/-/webpack-sources-3.2.0.tgz", + "integrity": "sha512-Ft7YH3lEVRQ6ls8k4Ff1oB4jN6oy/XmU6tQISKdhfh+1mR+viZFphS6WL0IrtDOzvefmJg5a0s7ZQoRXwqTEFg==", + "dependencies": { + "@types/node": "*", + "@types/source-list-map": "*", + "source-map": "^0.7.3" + } + }, + "node_modules/@types/webpack-sources/node_modules/source-map": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", + "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@vue/babel-helper-vue-jsx-merge-props": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@vue/babel-helper-vue-jsx-merge-props/-/babel-helper-vue-jsx-merge-props-1.2.1.tgz", + "integrity": "sha512-QOi5OW45e2R20VygMSNhyQHvpdUwQZqGPc748JLGCYEy+yp8fNFNdbNIGAgZmi9e+2JHPd6i6idRuqivyicIkA==" + }, + "node_modules/@vue/babel-plugin-transform-vue-jsx": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@vue/babel-plugin-transform-vue-jsx/-/babel-plugin-transform-vue-jsx-1.2.1.tgz", + "integrity": "sha512-HJuqwACYehQwh1fNT8f4kyzqlNMpBuUK4rSiSES5D4QsYncv5fxFsLyrxFPG2ksO7t5WP+Vgix6tt6yKClwPzA==", + "dependencies": { + "@babel/helper-module-imports": "^7.0.0", + "@babel/plugin-syntax-jsx": "^7.2.0", + "@vue/babel-helper-vue-jsx-merge-props": "^1.2.1", + "html-tags": "^2.0.0", + "lodash.kebabcase": "^4.1.1", + "svg-tags": "^1.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@vue/babel-preset-jsx": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@vue/babel-preset-jsx/-/babel-preset-jsx-1.2.4.tgz", + "integrity": "sha512-oRVnmN2a77bYDJzeGSt92AuHXbkIxbf/XXSE3klINnh9AXBmVS1DGa1f0d+dDYpLfsAKElMnqKTQfKn7obcL4w==", + "dependencies": { + "@vue/babel-helper-vue-jsx-merge-props": "^1.2.1", + "@vue/babel-plugin-transform-vue-jsx": "^1.2.1", + "@vue/babel-sugar-composition-api-inject-h": "^1.2.1", + "@vue/babel-sugar-composition-api-render-instance": "^1.2.4", + "@vue/babel-sugar-functional-vue": "^1.2.2", + "@vue/babel-sugar-inject-h": "^1.2.2", + "@vue/babel-sugar-v-model": "^1.2.3", + "@vue/babel-sugar-v-on": "^1.2.3" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@vue/babel-sugar-composition-api-inject-h": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@vue/babel-sugar-composition-api-inject-h/-/babel-sugar-composition-api-inject-h-1.2.1.tgz", + "integrity": "sha512-4B3L5Z2G+7s+9Bwbf+zPIifkFNcKth7fQwekVbnOA3cr3Pq71q71goWr97sk4/yyzH8phfe5ODVzEjX7HU7ItQ==", + "dependencies": { + "@babel/plugin-syntax-jsx": "^7.2.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@vue/babel-sugar-composition-api-render-instance": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@vue/babel-sugar-composition-api-render-instance/-/babel-sugar-composition-api-render-instance-1.2.4.tgz", + "integrity": "sha512-joha4PZznQMsxQYXtR3MnTgCASC9u3zt9KfBxIeuI5g2gscpTsSKRDzWQt4aqNIpx6cv8On7/m6zmmovlNsG7Q==", + "dependencies": { + "@babel/plugin-syntax-jsx": "^7.2.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@vue/babel-sugar-functional-vue": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@vue/babel-sugar-functional-vue/-/babel-sugar-functional-vue-1.2.2.tgz", + "integrity": "sha512-JvbgGn1bjCLByIAU1VOoepHQ1vFsroSA/QkzdiSs657V79q6OwEWLCQtQnEXD/rLTA8rRit4rMOhFpbjRFm82w==", + "dependencies": { + "@babel/plugin-syntax-jsx": "^7.2.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@vue/babel-sugar-inject-h": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@vue/babel-sugar-inject-h/-/babel-sugar-inject-h-1.2.2.tgz", + "integrity": "sha512-y8vTo00oRkzQTgufeotjCLPAvlhnpSkcHFEp60+LJUwygGcd5Chrpn5480AQp/thrxVm8m2ifAk0LyFel9oCnw==", + "dependencies": { + "@babel/plugin-syntax-jsx": "^7.2.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@vue/babel-sugar-v-model": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@vue/babel-sugar-v-model/-/babel-sugar-v-model-1.2.3.tgz", + "integrity": "sha512-A2jxx87mySr/ulAsSSyYE8un6SIH0NWHiLaCWpodPCVOlQVODCaSpiR4+IMsmBr73haG+oeCuSvMOM+ttWUqRQ==", + "dependencies": { + "@babel/plugin-syntax-jsx": "^7.2.0", + "@vue/babel-helper-vue-jsx-merge-props": "^1.2.1", + "@vue/babel-plugin-transform-vue-jsx": "^1.2.1", + "camelcase": "^5.0.0", + "html-tags": "^2.0.0", + "svg-tags": "^1.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@vue/babel-sugar-v-on": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@vue/babel-sugar-v-on/-/babel-sugar-v-on-1.2.3.tgz", + "integrity": "sha512-kt12VJdz/37D3N3eglBywV8GStKNUhNrsxChXIV+o0MwVXORYuhDTHJRKPgLJRb/EY3vM2aRFQdxJBp9CLikjw==", + "dependencies": { + "@babel/plugin-syntax-jsx": "^7.2.0", + "@vue/babel-plugin-transform-vue-jsx": "^1.2.1", + "camelcase": "^5.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@vue/component-compiler-utils": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/@vue/component-compiler-utils/-/component-compiler-utils-3.3.0.tgz", + "integrity": "sha512-97sfH2mYNU+2PzGrmK2haqffDpVASuib9/w2/noxiFi31Z54hW+q3izKQXXQZSNhtiUpAI36uSuYepeBe4wpHQ==", + "dependencies": { + "consolidate": "^0.15.1", + "hash-sum": "^1.0.2", + "lru-cache": "^4.1.2", + "merge-source-map": "^1.1.0", + "postcss": "^7.0.36", + "postcss-selector-parser": "^6.0.2", + "source-map": "~0.6.1", + "vue-template-es2015-compiler": "^1.9.0" + }, + "optionalDependencies": { + "prettier": "^1.18.2 || ^2.0.0" + } + }, + "node_modules/@vue/component-compiler-utils/node_modules/hash-sum": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/hash-sum/-/hash-sum-1.0.2.tgz", + "integrity": "sha1-M7QHd3VMZDJXPBIMw4CLvRDUfwQ=" + }, + "node_modules/@vue/component-compiler-utils/node_modules/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==", + "dependencies": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + }, + "node_modules/@vue/component-compiler-utils/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "node_modules/@vue/component-compiler-utils/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/@vue/component-compiler-utils/node_modules/yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=" + }, + "node_modules/@webassemblyjs/ast": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.9.0.tgz", + "integrity": "sha512-C6wW5L+b7ogSDVqymbkkvuW9kruN//YisMED04xzeBBqjHa2FYnmvOlS6Xj68xWQRgWvI9cIglsjFowH/RJyEA==", + "dependencies": { + "@webassemblyjs/helper-module-context": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/wast-parser": "1.9.0" + } + }, + "node_modules/@webassemblyjs/floating-point-hex-parser": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.9.0.tgz", + "integrity": "sha512-TG5qcFsS8QB4g4MhrxK5TqfdNe7Ey/7YL/xN+36rRjl/BlGE/NcBvJcqsRgCP6Z92mRE+7N50pRIi8SmKUbcQA==" + }, + "node_modules/@webassemblyjs/helper-api-error": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.9.0.tgz", + "integrity": "sha512-NcMLjoFMXpsASZFxJ5h2HZRcEhDkvnNFOAKneP5RbKRzaWJN36NC4jqQHKwStIhGXu5mUWlUUk7ygdtrO8lbmw==" + }, + "node_modules/@webassemblyjs/helper-buffer": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.9.0.tgz", + "integrity": "sha512-qZol43oqhq6yBPx7YM3m9Bv7WMV9Eevj6kMi6InKOuZxhw+q9hOkvq5e/PpKSiLfyetpaBnogSbNCfBwyB00CA==" + }, + "node_modules/@webassemblyjs/helper-code-frame": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.9.0.tgz", + "integrity": "sha512-ERCYdJBkD9Vu4vtjUYe8LZruWuNIToYq/ME22igL+2vj2dQ2OOujIZr3MEFvfEaqKoVqpsFKAGsRdBSBjrIvZA==", + "dependencies": { + "@webassemblyjs/wast-printer": "1.9.0" + } + }, + "node_modules/@webassemblyjs/helper-fsm": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-fsm/-/helper-fsm-1.9.0.tgz", + "integrity": "sha512-OPRowhGbshCb5PxJ8LocpdX9Kl0uB4XsAjl6jH/dWKlk/mzsANvhwbiULsaiqT5GZGT9qinTICdj6PLuM5gslw==" + }, + "node_modules/@webassemblyjs/helper-module-context": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-module-context/-/helper-module-context-1.9.0.tgz", + "integrity": "sha512-MJCW8iGC08tMk2enck1aPW+BE5Cw8/7ph/VGZxwyvGbJwjktKkDK7vy7gAmMDx88D7mhDTCNKAW5tED+gZ0W8g==", + "dependencies": { + "@webassemblyjs/ast": "1.9.0" + } + }, + "node_modules/@webassemblyjs/helper-wasm-bytecode": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.9.0.tgz", + "integrity": "sha512-R7FStIzyNcd7xKxCZH5lE0Bqy+hGTwS3LJjuv1ZVxd9O7eHCedSdrId/hMOd20I+v8wDXEn+bjfKDLzTepoaUw==" + }, + "node_modules/@webassemblyjs/helper-wasm-section": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.9.0.tgz", + "integrity": "sha512-XnMB8l3ek4tvrKUUku+IVaXNHz2YsJyOOmz+MMkZvh8h1uSJpSen6vYnw3IoQ7WwEuAhL8Efjms1ZWjqh2agvw==", + "dependencies": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-buffer": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/wasm-gen": "1.9.0" + } + }, + "node_modules/@webassemblyjs/ieee754": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.9.0.tgz", + "integrity": "sha512-dcX8JuYU/gvymzIHc9DgxTzUUTLexWwt8uCTWP3otys596io0L5aW02Gb1RjYpx2+0Jus1h4ZFqjla7umFniTg==", + "dependencies": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "node_modules/@webassemblyjs/leb128": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.9.0.tgz", + "integrity": "sha512-ENVzM5VwV1ojs9jam6vPys97B/S65YQtv/aanqnU7D8aSoHFX8GyhGg0CMfyKNIHBuAVjy3tlzd5QMMINa7wpw==", + "dependencies": { + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/utf8": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.9.0.tgz", + "integrity": "sha512-GZbQlWtopBTP0u7cHrEx+73yZKrQoBMpwkGEIqlacljhXCkVM1kMQge/Mf+csMJAjEdSwhOyLAS0AoR3AG5P8w==" + }, + "node_modules/@webassemblyjs/wasm-edit": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.9.0.tgz", + "integrity": "sha512-FgHzBm80uwz5M8WKnMTn6j/sVbqilPdQXTWraSjBwFXSYGirpkSWE2R9Qvz9tNiTKQvoKILpCuTjBKzOIm0nxw==", + "dependencies": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-buffer": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/helper-wasm-section": "1.9.0", + "@webassemblyjs/wasm-gen": "1.9.0", + "@webassemblyjs/wasm-opt": "1.9.0", + "@webassemblyjs/wasm-parser": "1.9.0", + "@webassemblyjs/wast-printer": "1.9.0" + } + }, + "node_modules/@webassemblyjs/wasm-gen": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.9.0.tgz", + "integrity": "sha512-cPE3o44YzOOHvlsb4+E9qSqjc9Qf9Na1OO/BHFy4OI91XDE14MjFN4lTMezzaIWdPqHnsTodGGNP+iRSYfGkjA==", + "dependencies": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/ieee754": "1.9.0", + "@webassemblyjs/leb128": "1.9.0", + "@webassemblyjs/utf8": "1.9.0" + } + }, + "node_modules/@webassemblyjs/wasm-opt": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.9.0.tgz", + "integrity": "sha512-Qkjgm6Anhm+OMbIL0iokO7meajkzQD71ioelnfPEj6r4eOFuqm4YC3VBPqXjFyyNwowzbMD+hizmprP/Fwkl2A==", + "dependencies": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-buffer": "1.9.0", + "@webassemblyjs/wasm-gen": "1.9.0", + "@webassemblyjs/wasm-parser": "1.9.0" + } + }, + "node_modules/@webassemblyjs/wasm-parser": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.9.0.tgz", + "integrity": "sha512-9+wkMowR2AmdSWQzsPEjFU7njh8HTO5MqO8vjwEHuM+AMHioNqSBONRdr0NQQ3dVQrzp0s8lTcYqzUdb7YgELA==", + "dependencies": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-api-error": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/ieee754": "1.9.0", + "@webassemblyjs/leb128": "1.9.0", + "@webassemblyjs/utf8": "1.9.0" + } + }, + "node_modules/@webassemblyjs/wast-parser": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-parser/-/wast-parser-1.9.0.tgz", + "integrity": "sha512-qsqSAP3QQ3LyZjNC/0jBJ/ToSxfYJ8kYyuiGvtn/8MK89VrNEfwj7BPQzJVHi0jGTRK2dGdJ5PRqhtjzoww+bw==", + "dependencies": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/floating-point-hex-parser": "1.9.0", + "@webassemblyjs/helper-api-error": "1.9.0", + "@webassemblyjs/helper-code-frame": "1.9.0", + "@webassemblyjs/helper-fsm": "1.9.0", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/wast-printer": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.9.0.tgz", + "integrity": "sha512-2J0nE95rHXHyQ24cWjMKJ1tqB/ds8z/cyeOZxJhcb+rW+SQASVjuznUSmdz5GpVJTzU8JkhYut0D3siFDD6wsA==", + "dependencies": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/wast-parser": "1.9.0", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@xmldom/xmldom": { + "version": "0.7.5", + "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.7.5.tgz", + "integrity": "sha512-V3BIhmY36fXZ1OtVcI9W+FxQqxVLsPKcNjWigIaa81dLC9IolJl5Mt4Cvhmr0flUnjSpTdrbMTSbXqYqV5dT6A==", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/@xtuc/ieee754": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==" + }, + "node_modules/@xtuc/long": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==" + }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-node": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/acorn-node/-/acorn-node-1.8.2.tgz", + "integrity": "sha512-8mt+fslDufLYntIoPAaIMUe/lrbrehIiwmR3t2k9LljIzoigEPF27eLk2hy8zSGzmR/ogr7zbRKINMo1u0yh5A==", + "dev": true, + "dependencies": { + "acorn": "^7.0.0", + "acorn-walk": "^7.0.0", + "xtend": "^4.0.2" + } + }, + "node_modules/acorn-walk": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz", + "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/aggregate-error": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "dependencies": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-errors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ajv-errors/-/ajv-errors-1.0.1.tgz", + "integrity": "sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ==", + "peerDependencies": { + "ajv": ">=5.0.0" + } + }, + "node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/alphanum-sort": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/alphanum-sort/-/alphanum-sort-1.0.2.tgz", + "integrity": "sha1-l6ERlkmyEa0zaR2fn0hqjsn74KM=" + }, + "node_modules/ansi-align": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", + "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==", + "dependencies": { + "string-width": "^4.1.0" + } + }, + "node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-escapes/node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-html-community": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/ansi-html-community/-/ansi-html-community-0.0.8.tgz", + "integrity": "sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==", + "engines": [ + "node >= 0.8.0" + ], + "bin": { + "ansi-html": "bin/ansi-html" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/anymatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", + "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" + }, + "node_modules/arg": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", + "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==" + }, + "node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/arr-flatten": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/arr-union": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", + "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "engines": { + "node": ">=8" + } + }, + "node_modules/array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/asn1.js": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz", + "integrity": "sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==", + "dependencies": { + "bn.js": "^4.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0", + "safer-buffer": "^2.1.0" + } + }, + "node_modules/asn1.js/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + }, + "node_modules/assert": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/assert/-/assert-1.5.0.tgz", + "integrity": "sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA==", + "dependencies": { + "object-assign": "^4.1.1", + "util": "0.10.3" + } + }, + "node_modules/assert/node_modules/inherits": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=" + }, + "node_modules/assert/node_modules/util": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", + "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", + "dependencies": { + "inherits": "2.0.1" + } + }, + "node_modules/assign-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", + "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/async": { + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", + "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", + "dev": true, + "dependencies": { + "lodash": "^4.17.14" + } + }, + "node_modules/async-each": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz", + "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==", + "optional": true + }, + "node_modules/at-least-node": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", + "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/atob": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", + "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", + "bin": { + "atob": "bin/atob.js" + }, + "engines": { + "node": ">= 4.5.0" + } + }, + "node_modules/autoprefixer": { + "version": "10.4.7", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.7.tgz", + "integrity": "sha512-ypHju4Y2Oav95SipEcCcI5J7CGPuvz8oat7sUtYj3ClK44bldfvtvcxK6IEK++7rqB7YchDGzweZIBG+SD0ZAA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/autoprefixer" + } + ], + "dependencies": { + "browserslist": "^4.20.3", + "caniuse-lite": "^1.0.30001335", + "fraction.js": "^4.2.0", + "normalize-range": "^0.1.2", + "picocolors": "^1.0.0", + "postcss-value-parser": "^4.2.0" + }, + "bin": { + "autoprefixer": "bin/autoprefixer" + }, + "engines": { + "node": "^10 || ^12 || >=14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/axios": { + "version": "0.21.4", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz", + "integrity": "sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==", + "dependencies": { + "follow-redirects": "^1.14.0" + } + }, + "node_modules/axios-retry": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/axios-retry/-/axios-retry-3.2.5.tgz", + "integrity": "sha512-a8umkKbfIkTiYJQLx3v3TzKM85TGKB8ZQYz4zwykt2fpO64TsRlUhjaPaAb3fqMWCXFm2YhWcd8V5FHDKO9bSA==", + "dependencies": { + "@babel/runtime": "^7.15.4", + "is-retry-allowed": "^2.2.0" + } + }, + "node_modules/babel-loader": { + "version": "8.2.5", + "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.2.5.tgz", + "integrity": "sha512-OSiFfH89LrEMiWd4pLNqGz4CwJDtbs2ZVc+iGu2HrkRfPxId9F2anQj38IxWpmRfsUY0aBZYi1EFcd3mhtRMLQ==", + "dependencies": { + "find-cache-dir": "^3.3.1", + "loader-utils": "^2.0.0", + "make-dir": "^3.1.0", + "schema-utils": "^2.6.5" + }, + "engines": { + "node": ">= 8.9" + }, + "peerDependencies": { + "@babel/core": "^7.0.0", + "webpack": ">=2" + } + }, + "node_modules/babel-loader/node_modules/schema-utils": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz", + "integrity": "sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==", + "dependencies": { + "@types/json-schema": "^7.0.5", + "ajv": "^6.12.4", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 8.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/babel-plugin-dynamic-import-node": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz", + "integrity": "sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ==", + "dependencies": { + "object.assign": "^4.1.0" + } + }, + "node_modules/babel-plugin-polyfill-corejs2": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.3.1.tgz", + "integrity": "sha512-v7/T6EQcNfVLfcN2X8Lulb7DjprieyLWJK/zOWH5DUYcAgex9sP3h25Q+DLsX9TloXe3y1O8l2q2Jv9q8UVB9w==", + "dependencies": { + "@babel/compat-data": "^7.13.11", + "@babel/helper-define-polyfill-provider": "^0.3.1", + "semver": "^6.1.1" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/babel-plugin-polyfill-corejs2/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/babel-plugin-polyfill-corejs3": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.5.2.tgz", + "integrity": "sha512-G3uJih0XWiID451fpeFaYGVuxHEjzKTHtc9uGFEjR6hHrvNzeS/PX+LLLcetJcytsB5m4j+K3o/EpXJNb/5IEQ==", + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.3.1", + "core-js-compat": "^3.21.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/babel-plugin-polyfill-regenerator": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.3.1.tgz", + "integrity": "sha512-Y2B06tvgHYt1x0yz17jGkGeeMr5FeKUu+ASJ+N6nB5lQ8Dapfg42i0OVrf8PNGJ3zKL4A23snMi1IRwrqqND7A==", + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.3.1" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/babel-plugin-syntax-dynamic-import": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-dynamic-import/-/babel-plugin-syntax-dynamic-import-6.18.0.tgz", + "integrity": "sha1-jWomIpyDdFqZgqRBBRVyyqF5sdo=" + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "node_modules/base": { + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", + "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", + "dependencies": { + "cache-base": "^1.0.1", + "class-utils": "^0.3.5", + "component-emitter": "^1.2.1", + "define-property": "^1.0.0", + "isobject": "^3.0.1", + "mixin-deep": "^1.2.0", + "pascalcase": "^0.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/base/node_modules/define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dependencies": { + "is-descriptor": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/base/node_modules/is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dependencies": { + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/base/node_modules/is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dependencies": { + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/base/node_modules/is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dependencies": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/base64id": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz", + "integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==", + "engines": { + "node": "^4.5.0 || >= 5.9" + } + }, + "node_modules/big.js": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", + "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", + "engines": { + "node": "*" + } + }, + "node_modules/binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "engines": { + "node": ">=8" + } + }, + "node_modules/bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "optional": true, + "dependencies": { + "file-uri-to-path": "1.0.0" + } + }, + "node_modules/bluebird": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" + }, + "node_modules/bn.js": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.0.tgz", + "integrity": "sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw==" + }, + "node_modules/boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=" + }, + "node_modules/boxen": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/boxen/-/boxen-5.1.2.tgz", + "integrity": "sha512-9gYgQKXx+1nP8mP7CzFyaUARhg7D3n1dF/FnErWmu9l6JvGpNUN278h0aSb+QjoiKSWG+iZ3uHrcqk0qrY9RQQ==", + "dependencies": { + "ansi-align": "^3.0.0", + "camelcase": "^6.2.0", + "chalk": "^4.1.0", + "cli-boxes": "^2.2.1", + "string-width": "^4.2.2", + "type-fest": "^0.20.2", + "widest-line": "^3.1.0", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/boxen/node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/boxen/node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/brorand": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", + "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=" + }, + "node_modules/browserify-aes": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", + "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", + "dependencies": { + "buffer-xor": "^1.0.3", + "cipher-base": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.3", + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/browserify-cipher": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz", + "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==", + "dependencies": { + "browserify-aes": "^1.0.4", + "browserify-des": "^1.0.0", + "evp_bytestokey": "^1.0.0" + } + }, + "node_modules/browserify-des": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz", + "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==", + "dependencies": { + "cipher-base": "^1.0.1", + "des.js": "^1.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "node_modules/browserify-rsa": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.1.0.tgz", + "integrity": "sha512-AdEER0Hkspgno2aR97SAf6vi0y0k8NuOpGnVH3O99rcA5Q6sh8QxcngtHuJ6uXwnfAXNM4Gn1Gb7/MV1+Ymbog==", + "dependencies": { + "bn.js": "^5.0.0", + "randombytes": "^2.0.1" + } + }, + "node_modules/browserify-sign": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.1.tgz", + "integrity": "sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg==", + "dependencies": { + "bn.js": "^5.1.1", + "browserify-rsa": "^4.0.1", + "create-hash": "^1.2.0", + "create-hmac": "^1.1.7", + "elliptic": "^6.5.3", + "inherits": "^2.0.4", + "parse-asn1": "^5.1.5", + "readable-stream": "^3.6.0", + "safe-buffer": "^5.2.0" + } + }, + "node_modules/browserify-sign/node_modules/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==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/browserify-sign/node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/browserify-zlib": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz", + "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==", + "dependencies": { + "pako": "~1.0.5" + } + }, + "node_modules/browserslist": { + "version": "4.20.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.20.3.tgz", + "integrity": "sha512-NBhymBQl1zM0Y5dQT/O+xiLP9/rzOIQdKM/eMJBAq7yBgaB6krIYLGejrwVYnSHZdqjscB1SPuAjHwxjvN6Wdg==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + } + ], + "dependencies": { + "caniuse-lite": "^1.0.30001332", + "electron-to-chromium": "^1.4.118", + "escalade": "^3.1.1", + "node-releases": "^2.0.3", + "picocolors": "^1.0.0" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" + }, + "node_modules/buffer-json": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/buffer-json/-/buffer-json-2.0.0.tgz", + "integrity": "sha512-+jjPFVqyfF1esi9fvfUs3NqM0pH1ziZ36VP4hmA/y/Ssfo/5w5xHKfTw9BwQjoJ1w/oVtpLomqwUHKdefGyuHw==" + }, + "node_modules/buffer-xor": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", + "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=" + }, + "node_modules/builtin-status-codes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", + "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=" + }, + "node_modules/bytes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/cacache": { + "version": "15.3.0", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-15.3.0.tgz", + "integrity": "sha512-VVdYzXEn+cnbXpFgWs5hTT7OScegHVmLhJIR8Ufqk3iFD6A6j5iSX1KuBTfNEv4tdJWE2PzA6IVFtcLC7fN9wQ==", + "dependencies": { + "@npmcli/fs": "^1.0.0", + "@npmcli/move-file": "^1.0.1", + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "glob": "^7.1.4", + "infer-owner": "^1.0.4", + "lru-cache": "^6.0.0", + "minipass": "^3.1.1", + "minipass-collect": "^1.0.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.2", + "mkdirp": "^1.0.3", + "p-map": "^4.0.0", + "promise-inflight": "^1.0.1", + "rimraf": "^3.0.2", + "ssri": "^8.0.1", + "tar": "^6.0.2", + "unique-filename": "^1.1.1" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/cacache/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/cacache/node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/cacache/node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/cacache/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "node_modules/cache-base": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", + "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", + "dependencies": { + "collection-visit": "^1.0.0", + "component-emitter": "^1.2.1", + "get-value": "^2.0.6", + "has-value": "^1.0.0", + "isobject": "^3.0.1", + "set-value": "^2.0.0", + "to-object-path": "^0.3.0", + "union-value": "^1.0.0", + "unset-value": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/cache-content-type": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cache-content-type/-/cache-content-type-1.0.1.tgz", + "integrity": "sha512-IKufZ1o4Ut42YUrZSo8+qnMTrFuKkvyoLXUywKz9GJ5BrhOFGhLdkx9sG4KAnVvbY6kEcSFjLQul+DVmBm2bgA==", + "dev": true, + "dependencies": { + "mime-types": "^2.1.18", + "ylru": "^1.2.0" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/cache-loader": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cache-loader/-/cache-loader-4.1.0.tgz", + "integrity": "sha512-ftOayxve0PwKzBF/GLsZNC9fJBXl8lkZE3TOsjkboHfVHVkL39iUEs1FO07A33mizmci5Dudt38UZrrYXDtbhw==", + "dependencies": { + "buffer-json": "^2.0.0", + "find-cache-dir": "^3.0.0", + "loader-utils": "^1.2.3", + "mkdirp": "^0.5.1", + "neo-async": "^2.6.1", + "schema-utils": "^2.0.0" + }, + "engines": { + "node": ">= 8.9.0" + }, + "peerDependencies": { + "webpack": "^4.0.0" + } + }, + "node_modules/cache-loader/node_modules/json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" + } + }, + "node_modules/cache-loader/node_modules/loader-utils": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", + "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", + "dependencies": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^1.0.1" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/cache-loader/node_modules/schema-utils": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz", + "integrity": "sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==", + "dependencies": { + "@types/json-schema": "^7.0.5", + "ajv": "^6.12.4", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 8.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dependencies": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/caller-callsite": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/caller-callsite/-/caller-callsite-2.0.0.tgz", + "integrity": "sha1-hH4PzgoiN1CpoCfFSzNzGtMVQTQ=", + "dependencies": { + "callsites": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/caller-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-2.0.0.tgz", + "integrity": "sha1-Ro+DBE42mrIBD6xfBs7uFbsssfQ=", + "dependencies": { + "caller-callsite": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/callsites": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-2.0.0.tgz", + "integrity": "sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA=", + "engines": { + "node": ">=4" + } + }, + "node_modules/camel-case": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-3.0.0.tgz", + "integrity": "sha1-yjw2iKTpzzpM2nd9xNy8cTJJz3M=", + "dependencies": { + "no-case": "^2.2.0", + "upper-case": "^1.1.1" + } + }, + "node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase-css": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", + "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/caniuse-api": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-3.0.0.tgz", + "integrity": "sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==", + "dependencies": { + "browserslist": "^4.0.0", + "caniuse-lite": "^1.0.0", + "lodash.memoize": "^4.1.2", + "lodash.uniq": "^4.5.0" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001340", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001340.tgz", + "integrity": "sha512-jUNz+a9blQTQVu4uFcn17uAD8IDizPzQkIKh3LCJfg9BkyIqExYYdyc/ZSlWUSKb8iYiXxKsxbv4zYSvkqjrxw==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + } + ] + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/charcodes": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/charcodes/-/charcodes-0.2.0.tgz", + "integrity": "sha512-Y4kiDb+AM4Ecy58YkuZrrSRJBDQdQ2L+NyS1vHHFtNtUjgutcZfx3yp1dAONI/oPaPmyGfCLx5CxL+zauIMyKQ==", + "engines": { + "node": ">=6" + } + }, + "node_modules/chardet": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", + "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==" + }, + "node_modules/chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "engines": { + "node": ">=10" + } + }, + "node_modules/chrome-trace-event": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", + "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==", + "engines": { + "node": ">=6.0" + } + }, + "node_modules/ci-info": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.3.1.tgz", + "integrity": "sha512-SXgeMX9VwDe7iFFaEWkA5AstuER9YKqy4EhHqr4DVqkwmD9rpVimkMKWHdjn30Ja45txyjhSn63lVX69eVCckg==" + }, + "node_modules/cipher-base": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", + "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", + "dependencies": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/class-utils": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", + "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", + "dependencies": { + "arr-union": "^3.1.0", + "define-property": "^0.2.5", + "isobject": "^3.0.0", + "static-extend": "^0.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/clean-css": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.4.tgz", + "integrity": "sha512-EJUDT7nDVFDvaQgAo2G/PJvxmp1o/c6iXLbswsBbUFXi1Nr+AjA2cKmfbKDMjMvzEe75g3P6JkaDDAKk96A85A==", + "dependencies": { + "source-map": "~0.6.0" + }, + "engines": { + "node": ">= 4.0" + } + }, + "node_modules/clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "engines": { + "node": ">=6" + } + }, + "node_modules/clear-module": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/clear-module/-/clear-module-4.1.2.tgz", + "integrity": "sha512-LWAxzHqdHsAZlPlEyJ2Poz6AIs384mPeqLVCru2p0BrP9G/kVGuhNyZYClLO6cXlnuJjzC8xtsJIuMjKqLXoAw==", + "dev": true, + "dependencies": { + "parent-module": "^2.0.0", + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-boxes": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.1.tgz", + "integrity": "sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==", + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "dependencies": { + "restore-cursor": "^3.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cli-width": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz", + "integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==", + "engines": { + "node": ">= 10" + } + }, + "node_modules/cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "node_modules/clone-deep": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", + "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", + "dev": true, + "dependencies": { + "is-plain-object": "^2.0.4", + "kind-of": "^6.0.2", + "shallow-clone": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", + "dev": true, + "engines": { + "iojs": ">= 1.0.0", + "node": ">= 0.12.0" + } + }, + "node_modules/coa": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/coa/-/coa-2.0.2.tgz", + "integrity": "sha512-q5/jG+YQnSy4nRTV4F7lPepBJZ8qBNJJDBuJdoejDyLXgmL7IEo+Le2JDZudFTFt7mrCqIRaSjws4ygRCTCAXA==", + "dependencies": { + "@types/q": "^1.5.1", + "chalk": "^2.4.1", + "q": "^1.1.2" + }, + "engines": { + "node": ">= 4.0" + } + }, + "node_modules/coa/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/coa/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/coa/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/coa/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" + }, + "node_modules/coa/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "engines": { + "node": ">=4" + } + }, + "node_modules/coa/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/collection-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", + "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", + "dependencies": { + "map-visit": "^1.0.0", + "object-visit": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/color": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/color/-/color-3.2.1.tgz", + "integrity": "sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA==", + "dependencies": { + "color-convert": "^1.9.3", + "color-string": "^1.6.0" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/color-string": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz", + "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==", + "dependencies": { + "color-name": "^1.0.0", + "simple-swizzle": "^0.2.2" + } + }, + "node_modules/color/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/color/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" + }, + "node_modules/colorette": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.4.0.tgz", + "integrity": "sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g==" + }, + "node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" + }, + "node_modules/commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=" + }, + "node_modules/component-emitter": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", + "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==" + }, + "node_modules/compressible": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", + "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", + "dependencies": { + "mime-db": ">= 1.43.0 < 2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/compression": { + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz", + "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==", + "dependencies": { + "accepts": "~1.3.5", + "bytes": "3.0.0", + "compressible": "~2.0.16", + "debug": "2.6.9", + "on-headers": "~1.0.2", + "safe-buffer": "5.1.2", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/compression/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/compression/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + }, + "node_modules/concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "engines": [ + "node >= 0.8" + ], + "dependencies": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, + "node_modules/connect": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/connect/-/connect-3.7.0.tgz", + "integrity": "sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ==", + "dependencies": { + "debug": "2.6.9", + "finalhandler": "1.1.2", + "parseurl": "~1.3.3", + "utils-merge": "1.0.1" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/connect/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/connect/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "node_modules/consola": { + "version": "2.15.3", + "resolved": "https://registry.npmjs.org/consola/-/consola-2.15.3.tgz", + "integrity": "sha512-9vAdYbHj6x2fLKC4+oPH0kFzY/orMZyG2Aj+kNylHxKGJ/Ed4dpNyAQYwJOdqO4zdM7XpVHmyejQDcQHrnuXbw==" + }, + "node_modules/console-browserify": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.2.0.tgz", + "integrity": "sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA==" + }, + "node_modules/consolidate": { + "version": "0.15.1", + "resolved": "https://registry.npmjs.org/consolidate/-/consolidate-0.15.1.tgz", + "integrity": "sha512-DW46nrsMJgy9kqAbPt5rKaCr7uFtpo4mSUvLHIUbJEjm0vo+aY5QLwBUq3FK4tRnJr/X0Psc0C4jf/h+HtXSMw==", + "dependencies": { + "bluebird": "^3.1.1" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/constants-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", + "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=" + }, + "node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "dev": true, + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-disposition/node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/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==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/convert-source-map": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz", + "integrity": "sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==", + "dependencies": { + "safe-buffer": "~5.1.1" + } + }, + "node_modules/cookie": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", + "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookies": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/cookies/-/cookies-0.8.0.tgz", + "integrity": "sha512-8aPsApQfebXnuI+537McwYsDtjVxGm8gTIzQI3FDW6t5t/DAhERxtnbEPN/8RX+uZthoz4eCOgloXaE5cYyNow==", + "dev": true, + "dependencies": { + "depd": "~2.0.0", + "keygrip": "~1.1.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/copy-concurrently": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/copy-concurrently/-/copy-concurrently-1.0.5.tgz", + "integrity": "sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A==", + "dependencies": { + "aproba": "^1.1.1", + "fs-write-stream-atomic": "^1.0.8", + "iferr": "^0.1.5", + "mkdirp": "^0.5.1", + "rimraf": "^2.5.4", + "run-queue": "^1.0.0" + } + }, + "node_modules/copy-descriptor": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", + "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/core-js": { + "version": "3.22.5", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.22.5.tgz", + "integrity": "sha512-VP/xYuvJ0MJWRAobcmQ8F2H6Bsn+s7zqAAjFaHGBMc5AQm7zaelhD1LGduFn2EehEcQcU+br6t+fwbpQ5d1ZWA==", + "deprecated": "core-js@<3.23.3 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Some versions have web compatibility issues. Please, upgrade your dependencies to the actual version of core-js.", + "hasInstallScript": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/core-js-compat": { + "version": "3.22.5", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.22.5.tgz", + "integrity": "sha512-rEF75n3QtInrYICvJjrAgV03HwKiYvtKHdPtaba1KucG+cNZ4NJnH9isqt979e67KZlhpbCOTwnsvnIr+CVeOg==", + "dependencies": { + "browserslist": "^4.20.3", + "semver": "7.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/core-js-compat/node_modules/semver": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz", + "integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" + }, + "node_modules/cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "dependencies": { + "object-assign": "^4", + "vary": "^1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/cosmiconfig": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.2.1.tgz", + "integrity": "sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA==", + "dependencies": { + "import-fresh": "^2.0.0", + "is-directory": "^0.3.1", + "js-yaml": "^3.13.1", + "parse-json": "^4.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/crc": { + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/crc/-/crc-3.8.0.tgz", + "integrity": "sha512-iX3mfgcTMIq3ZKLIsVFAbv7+Mc10kxabAGQb8HvjA1o3T1PIYprbakQ65d3I+2HGHt6nSKkM9PYjgoJO2KcFBQ==", + "dependencies": { + "buffer": "^5.1.0" + } + }, + "node_modules/create-ecdh": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz", + "integrity": "sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==", + "dependencies": { + "bn.js": "^4.1.0", + "elliptic": "^6.5.3" + } + }, + "node_modules/create-ecdh/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + }, + "node_modules/create-hash": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", + "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", + "dependencies": { + "cipher-base": "^1.0.1", + "inherits": "^2.0.1", + "md5.js": "^1.3.4", + "ripemd160": "^2.0.1", + "sha.js": "^2.4.0" + } + }, + "node_modules/create-hmac": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", + "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", + "dependencies": { + "cipher-base": "^1.0.3", + "create-hash": "^1.1.0", + "inherits": "^2.0.1", + "ripemd160": "^2.0.0", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, + "node_modules/create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==" + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/crypto-browserify": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", + "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", + "dependencies": { + "browserify-cipher": "^1.0.0", + "browserify-sign": "^4.0.0", + "create-ecdh": "^4.0.0", + "create-hash": "^1.1.0", + "create-hmac": "^1.1.0", + "diffie-hellman": "^5.0.0", + "inherits": "^2.0.1", + "pbkdf2": "^3.0.3", + "public-encrypt": "^4.0.0", + "randombytes": "^2.0.0", + "randomfill": "^1.0.3" + }, + "engines": { + "node": "*" + } + }, + "node_modules/css-blank-pseudo": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/css-blank-pseudo/-/css-blank-pseudo-0.1.4.tgz", + "integrity": "sha512-LHz35Hr83dnFeipc7oqFDmsjHdljj3TQtxGGiNWSOsTLIAubSm4TEz8qCaKFpk7idaQ1GfWscF4E6mgpBysA1w==", + "dependencies": { + "postcss": "^7.0.5" + }, + "bin": { + "css-blank-pseudo": "cli.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/css-blank-pseudo/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "node_modules/css-blank-pseudo/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/css-color-names": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/css-color-names/-/css-color-names-0.0.4.tgz", + "integrity": "sha1-gIrcLnnPhHOAabZGyyDsJ762KeA=", + "engines": { + "node": "*" + } + }, + "node_modules/css-declaration-sorter": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-4.0.1.tgz", + "integrity": "sha512-BcxQSKTSEEQUftYpBVnsH4SF05NTuBokb19/sBt6asXGKZ/6VP7PLG1CBCkFDYOnhXhPh0jMhO6xZ71oYHXHBA==", + "dependencies": { + "postcss": "^7.0.1", + "timsort": "^0.3.0" + }, + "engines": { + "node": ">4" + } + }, + "node_modules/css-declaration-sorter/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "node_modules/css-declaration-sorter/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/css-has-pseudo": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/css-has-pseudo/-/css-has-pseudo-0.10.0.tgz", + "integrity": "sha512-Z8hnfsZu4o/kt+AuFzeGpLVhFOGO9mluyHBaA2bA8aCGTwah5sT3WV/fTHH8UNZUytOIImuGPrl/prlb4oX4qQ==", + "dependencies": { + "postcss": "^7.0.6", + "postcss-selector-parser": "^5.0.0-rc.4" + }, + "bin": { + "css-has-pseudo": "cli.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/css-has-pseudo/node_modules/cssesc": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-2.0.0.tgz", + "integrity": "sha512-MsCAG1z9lPdoO/IUMLSBWBSVxVtJ1395VGIQ+Fc2gNdkQ1hNDnQdw3YhA71WJCBW1vdwA0cAnk/DnW6bqoEUYg==", + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/css-has-pseudo/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "node_modules/css-has-pseudo/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/css-has-pseudo/node_modules/postcss-selector-parser": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-5.0.0.tgz", + "integrity": "sha512-w+zLE5Jhg6Liz8+rQOWEAwtwkyqpfnmsinXjXg6cY7YIONZZtgvE0v2O0uhQBs0peNomOJwWRKt6JBfTdTd3OQ==", + "dependencies": { + "cssesc": "^2.0.0", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/css-loader": { + "version": "5.2.7", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-5.2.7.tgz", + "integrity": "sha512-Q7mOvpBNBG7YrVGMxRxcBJZFL75o+cH2abNASdibkj/fffYD8qWbInZrD0S9ccI6vZclF3DsHE7njGlLtaHbhg==", + "dependencies": { + "icss-utils": "^5.1.0", + "loader-utils": "^2.0.0", + "postcss": "^8.2.15", + "postcss-modules-extract-imports": "^3.0.0", + "postcss-modules-local-by-default": "^4.0.0", + "postcss-modules-scope": "^3.0.0", + "postcss-modules-values": "^4.0.0", + "postcss-value-parser": "^4.1.0", + "schema-utils": "^3.0.0", + "semver": "^7.3.5" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^4.27.0 || ^5.0.0" + } + }, + "node_modules/css-prefers-color-scheme": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/css-prefers-color-scheme/-/css-prefers-color-scheme-3.1.1.tgz", + "integrity": "sha512-MTu6+tMs9S3EUqzmqLXEcgNRbNkkD/TGFvowpeoWJn5Vfq7FMgsmRQs9X5NXAURiOBmOxm/lLjsDNXDE6k9bhg==", + "dependencies": { + "postcss": "^7.0.5" + }, + "bin": { + "css-prefers-color-scheme": "cli.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/css-prefers-color-scheme/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "node_modules/css-prefers-color-scheme/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/css-select": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz", + "integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==", + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^6.0.1", + "domhandler": "^4.3.1", + "domutils": "^2.8.0", + "nth-check": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/css-select-base-adapter": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/css-select-base-adapter/-/css-select-base-adapter-0.1.1.tgz", + "integrity": "sha512-jQVeeRG70QI08vSTwf1jHxp74JoZsr2XSgETae8/xC8ovSnL2WF87GTLO86Sbwdt2lK4Umg4HnnwMO4YF3Ce7w==" + }, + "node_modules/css-tree": { + "version": "1.0.0-alpha.37", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.0.0-alpha.37.tgz", + "integrity": "sha512-DMxWJg0rnz7UgxKT0Q1HU/L9BeJI0M6ksor0OgqOnF+aRCDWg/N2641HmVyU9KVIu0OVVWOb2IpC9A+BJRnejg==", + "dependencies": { + "mdn-data": "2.0.4", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/css-unit-converter": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/css-unit-converter/-/css-unit-converter-1.1.2.tgz", + "integrity": "sha512-IiJwMC8rdZE0+xiEZHeru6YoONC4rfPMqGm2W85jMIbkFvv5nFTwJVFHam2eFrN6txmoUYFAFXiv8ICVeTO0MA==", + "dev": true + }, + "node_modules/css-what": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", + "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/cssdb": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/cssdb/-/cssdb-4.4.0.tgz", + "integrity": "sha512-LsTAR1JPEM9TpGhl/0p3nQecC2LJ0kD8X5YARu1hk/9I1gril5vDtMZyNxcEpxxDj34YNck/ucjuoUd66K03oQ==" + }, + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/cssnano": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-4.1.11.tgz", + "integrity": "sha512-6gZm2htn7xIPJOHY824ERgj8cNPgPxyCSnkXc4v7YvNW+TdVfzgngHcEhy/8D11kUWRUMbke+tC+AUcUsnMz2g==", + "dependencies": { + "cosmiconfig": "^5.0.0", + "cssnano-preset-default": "^4.0.8", + "is-resolvable": "^1.0.0", + "postcss": "^7.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/cssnano-preset-default": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-4.0.8.tgz", + "integrity": "sha512-LdAyHuq+VRyeVREFmuxUZR1TXjQm8QQU/ktoo/x7bz+SdOge1YKc5eMN6pRW7YWBmyq59CqYba1dJ5cUukEjLQ==", + "dependencies": { + "css-declaration-sorter": "^4.0.1", + "cssnano-util-raw-cache": "^4.0.1", + "postcss": "^7.0.0", + "postcss-calc": "^7.0.1", + "postcss-colormin": "^4.0.3", + "postcss-convert-values": "^4.0.1", + "postcss-discard-comments": "^4.0.2", + "postcss-discard-duplicates": "^4.0.2", + "postcss-discard-empty": "^4.0.1", + "postcss-discard-overridden": "^4.0.1", + "postcss-merge-longhand": "^4.0.11", + "postcss-merge-rules": "^4.0.3", + "postcss-minify-font-values": "^4.0.2", + "postcss-minify-gradients": "^4.0.2", + "postcss-minify-params": "^4.0.2", + "postcss-minify-selectors": "^4.0.2", + "postcss-normalize-charset": "^4.0.1", + "postcss-normalize-display-values": "^4.0.2", + "postcss-normalize-positions": "^4.0.2", + "postcss-normalize-repeat-style": "^4.0.2", + "postcss-normalize-string": "^4.0.2", + "postcss-normalize-timing-functions": "^4.0.2", + "postcss-normalize-unicode": "^4.0.1", + "postcss-normalize-url": "^4.0.1", + "postcss-normalize-whitespace": "^4.0.2", + "postcss-ordered-values": "^4.1.2", + "postcss-reduce-initial": "^4.0.3", + "postcss-reduce-transforms": "^4.0.2", + "postcss-svgo": "^4.0.3", + "postcss-unique-selectors": "^4.0.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/cssnano-preset-default/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "node_modules/cssnano-preset-default/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/cssnano-util-get-arguments": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cssnano-util-get-arguments/-/cssnano-util-get-arguments-4.0.0.tgz", + "integrity": "sha1-7ToIKZ8h11dBsg87gfGU7UnMFQ8=", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/cssnano-util-get-match": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cssnano-util-get-match/-/cssnano-util-get-match-4.0.0.tgz", + "integrity": "sha1-wOTKB/U4a7F+xeUiULT1lhNlFW0=", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/cssnano-util-raw-cache": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/cssnano-util-raw-cache/-/cssnano-util-raw-cache-4.0.1.tgz", + "integrity": "sha512-qLuYtWK2b2Dy55I8ZX3ky1Z16WYsx544Q0UWViebptpwn/xDBmog2TLg4f+DBMg1rJ6JDWtn96WHbOKDWt1WQA==", + "dependencies": { + "postcss": "^7.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/cssnano-util-raw-cache/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "node_modules/cssnano-util-raw-cache/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/cssnano-util-same-parent": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/cssnano-util-same-parent/-/cssnano-util-same-parent-4.0.1.tgz", + "integrity": "sha512-WcKx5OY+KoSIAxBW6UBBRay1U6vkYheCdjyVNDm85zt5K9mHoGOfsOsqIszfAqrQQFIIKgjh2+FDgIj/zsl21Q==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/cssnano/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "node_modules/cssnano/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/csso": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/csso/-/csso-4.2.0.tgz", + "integrity": "sha512-wvlcdIbf6pwKEk7vHj8/Bkc0B4ylXZruLvOgs9doS5eOsOpuodOV2zJChSpkp+pRpYQLQMeF04nr3Z68Sta9jA==", + "dependencies": { + "css-tree": "^1.1.2" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/csso/node_modules/css-tree": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.1.3.tgz", + "integrity": "sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==", + "dependencies": { + "mdn-data": "2.0.14", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/csso/node_modules/mdn-data": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz", + "integrity": "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==" + }, + "node_modules/cuint": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/cuint/-/cuint-0.2.2.tgz", + "integrity": "sha1-QICG1AlVDCYxFVYZ6fp7ytw7mRs=" + }, + "node_modules/cyclist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-1.0.1.tgz", + "integrity": "sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk=" + }, + "node_modules/d": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", + "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", + "dependencies": { + "es5-ext": "^0.10.50", + "type": "^1.0.1" + } + }, + "node_modules/date-fns": { + "version": "2.28.0", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.28.0.tgz", + "integrity": "sha512-8d35hViGYx/QH0icHYCeLmsLmMUheMmTyV9Fcm6gvNwdw31yXXH+O85sOBJ+OLnLQMKZowvpKb6FgMIQjcpvQw==", + "engines": { + "node": ">=0.11" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/date-fns" + } + }, + "node_modules/de-indent": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/de-indent/-/de-indent-1.0.2.tgz", + "integrity": "sha1-sgOOhG3DO6pXlhKNCAS0VbjB4h0=" + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decode-uri-component": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", + "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", + "engines": { + "node": ">=0.10" + } + }, + "node_modules/deep-equal": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz", + "integrity": "sha512-bHtC0iYvWhyaTzvV3CZgPeZQqCOBGyGsVV7v4eevpdkLHfiSrXUdBG+qAuSz4RI70sszvjQ1QSZ98An1yNwpSw==", + "dev": true + }, + "node_modules/deepmerge": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz", + "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/define-properties": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.4.tgz", + "integrity": "sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==", + "dependencies": { + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dependencies": { + "is-descriptor": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/defined": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", + "integrity": "sha512-Y2caI5+ZwS5c3RiNDJ6u53VhQHv+hHKwhkI1iHvceKUHw9Df6EK2zRLfjejRgMuCuxK7PfSWIMwWecceVvThjQ==", + "dev": true + }, + "node_modules/defu": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/defu/-/defu-5.0.1.tgz", + "integrity": "sha512-EPS1carKg+dkEVy3qNTqIdp2qV7mUP08nIsupfwQpz++slCVRw7qbQyWvSTig+kFPwz2XXp5/kIIkH+CwrJKkQ==" + }, + "node_modules/delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==", + "dev": true + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/des.js": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.1.tgz", + "integrity": "sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA==", + "dependencies": { + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" + } + }, + "node_modules/destr": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/destr/-/destr-1.1.1.tgz", + "integrity": "sha512-QqkneF8LrYmwATMdnuD2MLI3GHQIcBnG6qFC2q9bSH430VTCDAVjcspPmUaKhPGtAtPAftIUFqY1obQYQuwmbg==" + }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/detect-indent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-5.0.0.tgz", + "integrity": "sha1-OHHMCmoALow+Wzz38zYmRnXwa50=", + "engines": { + "node": ">=4" + } + }, + "node_modules/detective": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/detective/-/detective-5.2.1.tgz", + "integrity": "sha512-v9XE1zRnz1wRtgurGu0Bs8uHKFSTdteYZNbIPFVhUZ39L/S79ppMpdmVOZAnoz1jfEFodc48n6MX483Xo3t1yw==", + "dev": true, + "dependencies": { + "acorn-node": "^1.8.2", + "defined": "^1.0.0", + "minimist": "^1.2.6" + }, + "bin": { + "detective": "bin/detective.js" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/devalue": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/devalue/-/devalue-2.0.1.tgz", + "integrity": "sha512-I2TiqT5iWBEyB8GRfTDP0hiLZ0YeDJZ+upDxjBfOC2lebO5LezQMv7QvIUTzdb64jQyAKLf1AHADtGN+jw6v8Q==" + }, + "node_modules/didyoumean": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", + "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==", + "dev": true + }, + "node_modules/diffie-hellman": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", + "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", + "dependencies": { + "bn.js": "^4.1.0", + "miller-rabin": "^4.0.0", + "randombytes": "^2.0.0" + } + }, + "node_modules/diffie-hellman/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/dlv": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", + "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", + "dev": true + }, + "node_modules/dom-converter": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/dom-converter/-/dom-converter-0.2.0.tgz", + "integrity": "sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA==", + "dependencies": { + "utila": "~0.4" + } + }, + "node_modules/dom-serializer": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", + "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", + "dependencies": { + "domelementtype": "^2.0.1", + "domhandler": "^4.2.0", + "entities": "^2.0.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/domain-browser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz", + "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==", + "engines": { + "node": ">=0.4", + "npm": ">=1.2" + } + }, + "node_modules/domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ] + }, + "node_modules/domhandler": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", + "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", + "dependencies": { + "domelementtype": "^2.2.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/domutils": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", + "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", + "dependencies": { + "dom-serializer": "^1.0.1", + "domelementtype": "^2.2.0", + "domhandler": "^4.2.0" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, + "node_modules/dot-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", + "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==", + "dependencies": { + "no-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/dot-case/node_modules/lower-case": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", + "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==", + "dependencies": { + "tslib": "^2.0.3" + } + }, + "node_modules/dot-case/node_modules/no-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", + "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", + "dependencies": { + "lower-case": "^2.0.2", + "tslib": "^2.0.3" + } + }, + "node_modules/dot-case/node_modules/tslib": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" + }, + "node_modules/dot-prop": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", + "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", + "dependencies": { + "is-obj": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/dotenv": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-9.0.2.tgz", + "integrity": "sha512-I9OvvrHp4pIARv4+x9iuewrWycX6CcZtoAu1XrzPxc5UygMJXJZYmBsynku8IkrJwgypE5DGNjDPmPRhDCptUg==", + "engines": { + "node": ">=10" + } + }, + "node_modules/duplexer": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", + "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==" + }, + "node_modules/duplexify": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", + "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==", + "dependencies": { + "end-of-stream": "^1.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.0.0", + "stream-shift": "^1.0.0" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" + }, + "node_modules/electron-to-chromium": { + "version": "1.4.137", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.137.tgz", + "integrity": "sha512-0Rcpald12O11BUogJagX3HsCN3FE83DSqWjgXoHo5a72KUKMSfI39XBgJpgNNxS9fuGzytaFjE06kZkiVFy2qA==" + }, + "node_modules/elliptic": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz", + "integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==", + "dependencies": { + "bn.js": "^4.11.9", + "brorand": "^1.1.0", + "hash.js": "^1.0.0", + "hmac-drbg": "^1.0.1", + "inherits": "^2.0.4", + "minimalistic-assert": "^1.0.1", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "node_modules/elliptic/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "node_modules/emojis-list": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", + "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", + "engines": { + "node": ">= 4" + } + }, + "node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/engine.io": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.2.0.tgz", + "integrity": "sha512-4KzwW3F3bk+KlzSOY57fj/Jx6LyRQ1nbcyIadehl+AnXjKT7gDO0ORdRi/84ixvMKTym6ZKuxvbzN62HDDU1Lg==", + "dependencies": { + "@types/cookie": "^0.4.1", + "@types/cors": "^2.8.12", + "@types/node": ">=10.0.0", + "accepts": "~1.3.4", + "base64id": "2.0.0", + "cookie": "~0.4.1", + "cors": "~2.8.5", + "debug": "~4.3.1", + "engine.io-parser": "~5.0.3", + "ws": "~8.2.3" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/engine.io-client": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.2.2.tgz", + "integrity": "sha512-8ZQmx0LQGRTYkHuogVZuGSpDqYZtCM/nv8zQ68VZ+JkOpazJ7ICdsSpaO6iXwvaU30oFg5QJOJWj8zWqhbKjkQ==", + "dependencies": { + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.3.1", + "engine.io-parser": "~5.0.3", + "ws": "~8.2.3", + "xmlhttprequest-ssl": "~2.0.0" + } + }, + "node_modules/engine.io-parser": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.0.4.tgz", + "integrity": "sha512-+nVFp+5z1E3HcToEnO7ZIj3g+3k9389DvWtvJZz0T6/eOCPIyyxehFcedoYrZQrp0LgQbD9pPXhpMBKMd5QURg==", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/engine.io/node_modules/cookie": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", + "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/enhanced-resolve": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.5.0.tgz", + "integrity": "sha512-Nv9m36S/vxpsI+Hc4/ZGRs0n9mXqSWGGq49zxb/cJfPAQMbUtttJAlNPS4AQzaBdw/pKskw5bMbekT/Y7W/Wlg==", + "dependencies": { + "graceful-fs": "^4.1.2", + "memory-fs": "^0.5.0", + "tapable": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/entities": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", + "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/epubjs": { + "version": "0.3.93", + "resolved": "https://registry.npmjs.org/epubjs/-/epubjs-0.3.93.tgz", + "integrity": "sha512-c06pNSdBxcXv3dZSbXAVLE1/pmleRhOT6mXNZo6INKmvuKpYB65MwU/lO7830czCtjIiK9i+KR+3S+p0wtljrw==", + "dependencies": { + "@types/localforage": "0.0.34", + "@xmldom/xmldom": "^0.7.5", + "core-js": "^3.18.3", + "event-emitter": "^0.3.5", + "jszip": "^3.7.1", + "localforage": "^1.10.0", + "lodash": "^4.17.21", + "marks-pane": "^1.0.9", + "path-webpack": "0.0.3" + } + }, + "node_modules/errno": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.8.tgz", + "integrity": "sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==", + "dependencies": { + "prr": "~1.0.1" + }, + "bin": { + "errno": "cli.js" + } + }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/error-stack-parser": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/error-stack-parser/-/error-stack-parser-2.0.7.tgz", + "integrity": "sha512-chLOW0ZGRf4s8raLrDxa5sdkvPec5YdvwbFnqJme4rk0rFajP8mPtrDL1+I+CwrQDCjswDA5sREX7jYQDQs9vA==", + "dependencies": { + "stackframe": "^1.1.1" + } + }, + "node_modules/es-abstract": { + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.20.0.tgz", + "integrity": "sha512-URbD8tgRthKD3YcC39vbvSDrX23upXnPcnGAjQfgxXF5ID75YcENawc9ZX/9iTP9ptUyfCLIxTTuMYoRfiOVKA==", + "dependencies": { + "call-bind": "^1.0.2", + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "function.prototype.name": "^1.1.5", + "get-intrinsic": "^1.1.1", + "get-symbol-description": "^1.0.0", + "has": "^1.0.3", + "has-property-descriptors": "^1.0.0", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.3", + "is-callable": "^1.2.4", + "is-negative-zero": "^2.0.2", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.2", + "is-string": "^1.0.7", + "is-weakref": "^1.0.2", + "object-inspect": "^1.12.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.2", + "regexp.prototype.flags": "^1.4.1", + "string.prototype.trimend": "^1.0.5", + "string.prototype.trimstart": "^1.0.5", + "unbox-primitive": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dependencies": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es5-ext": { + "version": "0.10.61", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.61.tgz", + "integrity": "sha512-yFhIqQAzu2Ca2I4SE2Au3rxVfmohU9Y7wqGR+s7+H7krk26NXhIRAZDgqd6xqjCEFUomDEA3/Bo/7fKmIkW1kA==", + "hasInstallScript": true, + "dependencies": { + "es6-iterator": "^2.0.3", + "es6-symbol": "^3.1.3", + "next-tick": "^1.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/es6-iterator": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", + "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", + "dependencies": { + "d": "1", + "es5-ext": "^0.10.35", + "es6-symbol": "^3.1.1" + } + }, + "node_modules/es6-symbol": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", + "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", + "dependencies": { + "d": "^1.0.1", + "ext": "^1.1.2" + } + }, + "node_modules/escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" + }, + "node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/eslint-scope": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz", + "integrity": "sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==", + "dependencies": { + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esrecurse/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/event-emitter": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", + "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=", + "dependencies": { + "d": "1", + "es5-ext": "~0.10.14" + } + }, + "node_modules/eventemitter3": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==" + }, + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "engines": { + "node": ">=0.8.x" + } + }, + "node_modules/eventsource-polyfill": { + "version": "0.9.6", + "resolved": "https://registry.npmjs.org/eventsource-polyfill/-/eventsource-polyfill-0.9.6.tgz", + "integrity": "sha1-EODRh/ERsWfyj9q5GIQ859gY8Tw=" + }, + "node_modules/evp_bytestokey": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", + "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", + "dependencies": { + "md5.js": "^1.3.4", + "safe-buffer": "^5.1.1" + } + }, + "node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "dependencies": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/expand-brackets/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/expand-brackets/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "node_modules/ext": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/ext/-/ext-1.6.0.tgz", + "integrity": "sha512-sdBImtzkq2HpkdRLtlLWDa6w4DX22ijZLKx8BMPUuKe1c5lbN6xwQDQCxSfxBQnHZ13ls/FH0MQZx/q/gr6FQg==", + "dependencies": { + "type": "^2.5.0" + } + }, + "node_modules/ext/node_modules/type": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/type/-/type-2.6.0.tgz", + "integrity": "sha512-eiDBDOmkih5pMbo9OqsqPRGMljLodLcwd5XD5JbtNB0o89xZAwynY9EdCDsJU7LtcVCClu9DvM7/0Ep1hYX3EQ==" + }, + "node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/external-editor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", + "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", + "dependencies": { + "chardet": "^0.7.0", + "iconv-lite": "^0.4.24", + "tmp": "^0.0.33" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dependencies": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/extglob/node_modules/define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dependencies": { + "is-descriptor": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/extglob/node_modules/is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dependencies": { + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/extglob/node_modules/is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dependencies": { + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/extglob/node_modules/is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dependencies": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/extract-css-chunks-webpack-plugin": { + "version": "4.9.0", + "resolved": "https://registry.npmjs.org/extract-css-chunks-webpack-plugin/-/extract-css-chunks-webpack-plugin-4.9.0.tgz", + "integrity": "sha512-HNuNPCXRMqJDQ1OHAUehoY+0JVCnw9Y/H22FQzYVwo8Ulgew98AGDu0grnY5c7xwiXHjQa6yJ/1dxLCI/xqTyQ==", + "dependencies": { + "loader-utils": "^2.0.0", + "normalize-url": "1.9.1", + "schema-utils": "^1.0.0", + "webpack-sources": "^1.1.0" + }, + "engines": { + "node": ">= 6.9.0" + }, + "peerDependencies": { + "webpack": "^4.4.0 || ^5.0.0" + } + }, + "node_modules/extract-css-chunks-webpack-plugin/node_modules/schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "dependencies": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + }, + "engines": { + "node": ">= 4" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + }, + "node_modules/fast-glob": { + "version": "3.2.11", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz", + "integrity": "sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" + }, + "node_modules/fastq": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", + "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/figgy-pudding": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.2.tgz", + "integrity": "sha512-0btnI/H8f2pavGMN8w40mlSKOfTK2SVJmBfBeVIj3kNw0swwgzyRq0d5TJVOwodFmtvpPeWPN/MCcfuWF0Ezbw==" + }, + "node_modules/figures": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", + "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", + "dependencies": { + "escape-string-regexp": "^1.0.5" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/file-loader": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-6.2.0.tgz", + "integrity": "sha512-qo3glqyTa61Ytg4u73GultjHGjdRyig3tG6lPtyX/jOEJvHif9uB0/OCI2Kif6ctF3caQTW2G5gym21oAsI4pw==", + "dependencies": { + "loader-utils": "^2.0.0", + "schema-utils": "^3.0.0" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^4.0.0 || ^5.0.0" + } + }, + "node_modules/file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", + "optional": true + }, + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/filter-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/filter-obj/-/filter-obj-1.1.0.tgz", + "integrity": "sha1-mzERErxsYSehbgFsbF1/GeCAXFs=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/finalhandler": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", + "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", + "dependencies": { + "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" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/finalhandler/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/finalhandler/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "node_modules/find-cache-dir": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz", + "integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==", + "dependencies": { + "commondir": "^1.0.1", + "make-dir": "^3.0.2", + "pkg-dir": "^4.1.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/avajs/find-cache-dir?sponsor=1" + } + }, + "node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/flat": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", + "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", + "bin": { + "flat": "cli.js" + } + }, + "node_modules/flatten": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/flatten/-/flatten-1.0.3.tgz", + "integrity": "sha512-dVsPA/UwQ8+2uoFe5GHtiBMu48dWLTdsuEd7CKGlZlD78r1TTWBvDuFaFGKCo/ZfEr95Uk56vZoX86OsHkUeIg==", + "deprecated": "flatten is deprecated in favor of utility frameworks such as lodash." + }, + "node_modules/flush-write-stream": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz", + "integrity": "sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w==", + "dependencies": { + "inherits": "^2.0.3", + "readable-stream": "^2.3.6" + } + }, + "node_modules/follow-redirects": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.0.tgz", + "integrity": "sha512-aExlJShTV4qOUOL7yF1U5tvLCB0xQuudbf6toyYA0E/acBNw71mvjFTnLaRp50aQaYocMR0a/RMMBIHeZnGyjQ==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fraction.js": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.2.0.tgz", + "integrity": "sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA==", + "dev": true, + "engines": { + "node": "*" + }, + "funding": { + "type": "patreon", + "url": "https://www.patreon.com/infusion" + } + }, + "node_modules/fragment-cache": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", + "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", + "dependencies": { + "map-cache": "^0.2.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/from2": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", + "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=", + "dependencies": { + "inherits": "^2.0.1", + "readable-stream": "^2.0.0" + } + }, + "node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/fs-memo": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/fs-memo/-/fs-memo-1.2.0.tgz", + "integrity": "sha512-YEexkCpL4j03jn5SxaMHqcO6IuWuqm8JFUYhyCep7Ao89JIYmB8xoKhK7zXXJ9cCaNXpyNH5L3QtAmoxjoHW2w==" + }, + "node_modules/fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/fs-monkey": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.3.tgz", + "integrity": "sha512-cybjIfiiE+pTWicSCLFHSrXZ6EilF30oh91FDP9S2B051prEa7QWfrVTQm10/dDpswBDXZugPa1Ogu8Yh+HV0Q==" + }, + "node_modules/fs-write-stream-atomic": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz", + "integrity": "sha1-tH31NJPvkR33VzHnCp3tAYnbQMk=", + "dependencies": { + "graceful-fs": "^4.1.2", + "iferr": "^0.1.5", + "imurmurhash": "^0.1.4", + "readable-stream": "1 || 2" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + }, + "node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + }, + "node_modules/function.prototype.name": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.5.tgz", + "integrity": "sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.0", + "functions-have-names": "^1.2.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", + "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", + "dependencies": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-port-please": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/get-port-please/-/get-port-please-2.5.0.tgz", + "integrity": "sha512-NblPebBznYARC1R2r1qmusbJAAgBr954gWhEZgwTerzR8r3ud6U5PI1SG4Lue43r87aikPPjObs85VieIDK99A==", + "dependencies": { + "fs-memo": "^1.2.0" + } + }, + "node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/get-symbol-description": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", + "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-value": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", + "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/git-config-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/git-config-path/-/git-config-path-2.0.0.tgz", + "integrity": "sha512-qc8h1KIQbJpp+241id3GuAtkdyJ+IK+LIVtkiFTRKRrmddDzs3SI9CvP1QYmWBFvm1I/PWRwj//of8bgAc0ltA==", + "engines": { + "node": ">=4" + } + }, + "node_modules/git-up": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/git-up/-/git-up-4.0.5.tgz", + "integrity": "sha512-YUvVDg/vX3d0syBsk/CKUTib0srcQME0JyHkL5BaYdwLsiCslPWmDSi8PUMo9pXYjrryMcmsCoCgsTpSCJEQaA==", + "dependencies": { + "is-ssh": "^1.3.0", + "parse-url": "^6.0.0" + } + }, + "node_modules/git-url-parse": { + "version": "11.6.0", + "resolved": "https://registry.npmjs.org/git-url-parse/-/git-url-parse-11.6.0.tgz", + "integrity": "sha512-WWUxvJs5HsyHL6L08wOusa/IXYtMuCAhrMmnTjQPpBU0TTHyDhnOATNH3xNQz7YOQUsqIIPTGr4xiVti1Hsk5g==", + "dependencies": { + "git-up": "^4.0.0" + } + }, + "node_modules/glob": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "engines": { + "node": ">=4" + } + }, + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" + }, + "node_modules/gzip-size": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-6.0.0.tgz", + "integrity": "sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q==", + "dependencies": { + "duplexer": "^0.1.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/hable": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hable/-/hable-3.0.0.tgz", + "integrity": "sha512-7+G0/2/COR8pwteYFqHIVYfQpuEiO2HXwJrhCBJVgrNrl9O5eaUoJVDGXUJX+0RpGncNVTuestexjk1afj01wQ==" + }, + "node_modules/hard-source-webpack-plugin": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/hard-source-webpack-plugin/-/hard-source-webpack-plugin-0.13.1.tgz", + "integrity": "sha512-r9zf5Wq7IqJHdVAQsZ4OP+dcUSvoHqDMxJlIzaE2J0TZWn3UjMMrHqwDHR8Jr/pzPfG7XxSe36E7Y8QGNdtuAw==", + "dependencies": { + "chalk": "^2.4.1", + "find-cache-dir": "^2.0.0", + "graceful-fs": "^4.1.11", + "lodash": "^4.15.0", + "mkdirp": "^0.5.1", + "node-object-hash": "^1.2.0", + "parse-json": "^4.0.0", + "pkg-dir": "^3.0.0", + "rimraf": "^2.6.2", + "semver": "^5.6.0", + "tapable": "^1.0.0-beta.5", + "webpack-sources": "^1.0.1", + "write-json-file": "^2.3.0" + }, + "engines": { + "node": ">=8.0.0" + }, + "peerDependencies": { + "webpack": "*" + } + }, + "node_modules/hard-source-webpack-plugin/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/hard-source-webpack-plugin/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/hard-source-webpack-plugin/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/hard-source-webpack-plugin/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" + }, + "node_modules/hard-source-webpack-plugin/node_modules/find-cache-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", + "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", + "dependencies": { + "commondir": "^1.0.1", + "make-dir": "^2.0.0", + "pkg-dir": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/hard-source-webpack-plugin/node_modules/find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dependencies": { + "locate-path": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/hard-source-webpack-plugin/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "engines": { + "node": ">=4" + } + }, + "node_modules/hard-source-webpack-plugin/node_modules/locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dependencies": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/hard-source-webpack-plugin/node_modules/make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "dependencies": { + "pify": "^4.0.1", + "semver": "^5.6.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/hard-source-webpack-plugin/node_modules/p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dependencies": { + "p-limit": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/hard-source-webpack-plugin/node_modules/path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "engines": { + "node": ">=4" + } + }, + "node_modules/hard-source-webpack-plugin/node_modules/pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "engines": { + "node": ">=6" + } + }, + "node_modules/hard-source-webpack-plugin/node_modules/pkg-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "dependencies": { + "find-up": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/hard-source-webpack-plugin/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/hard-source-webpack-plugin/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dependencies": { + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/has-ansi/node_modules/ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/has-bigints": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", + "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", + "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", + "dependencies": { + "get-intrinsic": "^1.1.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", + "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", + "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", + "dependencies": { + "get-value": "^2.0.6", + "has-values": "^1.0.0", + "isobject": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/has-values": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", + "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", + "dependencies": { + "is-number": "^3.0.0", + "kind-of": "^4.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/has-values/node_modules/is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/has-values/node_modules/is-number/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/has-values/node_modules/kind-of": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/hash-base": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", + "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==", + "dependencies": { + "inherits": "^2.0.4", + "readable-stream": "^3.6.0", + "safe-buffer": "^5.2.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/hash-base/node_modules/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==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/hash-base/node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/hash-sum": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/hash-sum/-/hash-sum-2.0.0.tgz", + "integrity": "sha512-WdZTbAByD+pHfl/g9QSsBIIwy8IT+EsPiKDs0KNX+zSHhdDLFKdZu0BQHljvO+0QI/BasbMSUa8wYNCZTvhslg==" + }, + "node_modules/hash.js": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", + "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", + "dependencies": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.1" + } + }, + "node_modules/hasha": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/hasha/-/hasha-5.2.2.tgz", + "integrity": "sha512-Hrp5vIK/xr5SkeN2onO32H0MgNZ0f17HRNH39WfL0SYUNOTZ5Lz1TJ8Pajo/87dYGEFlLMm7mIc/k/s6Bvz9HQ==", + "dev": true, + "dependencies": { + "is-stream": "^2.0.0", + "type-fest": "^0.8.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "bin": { + "he": "bin/he" + } + }, + "node_modules/hex-color-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/hex-color-regex/-/hex-color-regex-1.1.0.tgz", + "integrity": "sha512-l9sfDFsuqtOqKDsQdqrMRk0U85RZc0RtOR9yPI7mRVOa4FsR/BVnZ0shmQRM96Ji99kYZP/7hn1cedc1+ApsTQ==" + }, + "node_modules/hls.js": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/hls.js/-/hls.js-1.1.5.tgz", + "integrity": "sha512-mQX5TSNtJEzGo5HPpvcQgCu+BWoKDQM6YYtg/KbgWkmVAcqOCvSTi0SuqG2ZJLXxIzdnFcKU2z7Mrw/YQWhPOA==" + }, + "node_modules/hmac-drbg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", + "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", + "dependencies": { + "hash.js": "^1.0.3", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "node_modules/hsl-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/hsl-regex/-/hsl-regex-1.0.0.tgz", + "integrity": "sha1-1JMwx4ntgZ4nakwNJy3/owsY/m4=" + }, + "node_modules/hsla-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/hsla-regex/-/hsla-regex-1.0.0.tgz", + "integrity": "sha1-wc56MWjIxmFAM6S194d/OyJfnDg=" + }, + "node_modules/html-entities": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.3.3.tgz", + "integrity": "sha512-DV5Ln36z34NNTDgnz0EWGBLZENelNAtkiFA4kyNOG2tDI6Mz1uSWiq1wAKdyjnJwyDiDO7Fa2SO1CTxPXL8VxA==" + }, + "node_modules/html-minifier": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/html-minifier/-/html-minifier-4.0.0.tgz", + "integrity": "sha512-aoGxanpFPLg7MkIl/DDFYtb0iWz7jMFGqFhvEDZga6/4QTjneiD8I/NXL1x5aaoCp7FSIT6h/OhykDdPsbtMig==", + "dependencies": { + "camel-case": "^3.0.0", + "clean-css": "^4.2.1", + "commander": "^2.19.0", + "he": "^1.2.0", + "param-case": "^2.1.1", + "relateurl": "^0.2.7", + "uglify-js": "^3.5.1" + }, + "bin": { + "html-minifier": "cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/html-minifier-terser": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-5.1.1.tgz", + "integrity": "sha512-ZPr5MNObqnV/T9akshPKbVgyOqLmy+Bxo7juKCfTfnjNniTAMdy4hz21YQqoofMBJD2kdREaqPPdThoR78Tgxg==", + "dependencies": { + "camel-case": "^4.1.1", + "clean-css": "^4.2.3", + "commander": "^4.1.1", + "he": "^1.2.0", + "param-case": "^3.0.3", + "relateurl": "^0.2.7", + "terser": "^4.6.3" + }, + "bin": { + "html-minifier-terser": "cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/html-minifier-terser/node_modules/camel-case": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz", + "integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==", + "dependencies": { + "pascal-case": "^3.1.2", + "tslib": "^2.0.3" + } + }, + "node_modules/html-minifier-terser/node_modules/commander": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", + "engines": { + "node": ">= 6" + } + }, + "node_modules/html-minifier-terser/node_modules/param-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz", + "integrity": "sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==", + "dependencies": { + "dot-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/html-minifier-terser/node_modules/tslib": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" + }, + "node_modules/html-tags": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-2.0.0.tgz", + "integrity": "sha1-ELMKOGCF9Dzt41PMj6fLDe7qZos=", + "engines": { + "node": ">=4" + } + }, + "node_modules/html-webpack-plugin": { + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-4.5.2.tgz", + "integrity": "sha512-q5oYdzjKUIPQVjOosjgvCHQOv9Ett9CYYHlgvJeXG0qQvdSojnBq4vAdQBwn1+yGveAwHCoe/rMR86ozX3+c2A==", + "dependencies": { + "@types/html-minifier-terser": "^5.0.0", + "@types/tapable": "^1.0.5", + "@types/webpack": "^4.41.8", + "html-minifier-terser": "^5.0.1", + "loader-utils": "^1.2.3", + "lodash": "^4.17.20", + "pretty-error": "^2.1.1", + "tapable": "^1.1.3", + "util.promisify": "1.0.0" + }, + "engines": { + "node": ">=6.9" + }, + "peerDependencies": { + "webpack": "^4.0.0 || ^5.0.0" + } + }, + "node_modules/html-webpack-plugin/node_modules/json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" + } + }, + "node_modules/html-webpack-plugin/node_modules/loader-utils": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", + "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", + "dependencies": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^1.0.1" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/htmlparser2": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz", + "integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==", + "funding": [ + "https://github.com/fb55/htmlparser2?sponsor=1", + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "dependencies": { + "domelementtype": "^2.0.1", + "domhandler": "^4.0.0", + "domutils": "^2.5.2", + "entities": "^2.0.0" + } + }, + "node_modules/http-assert": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/http-assert/-/http-assert-1.5.0.tgz", + "integrity": "sha512-uPpH7OKX4H25hBmU6G1jWNaqJGpTXxey+YOUizJUAgu0AjLUeC8D73hTrhvDS5D+GJN1DN1+hhc/eF/wpxtp0w==", + "dev": true, + "dependencies": { + "deep-equal": "~1.0.1", + "http-errors": "~1.8.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/http-assert/node_modules/depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/http-assert/node_modules/http-errors": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz", + "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==", + "dev": true, + "dependencies": { + "depd": "~1.1.2", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/http-errors/node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/http-proxy": { + "version": "1.18.1", + "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", + "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", + "dependencies": { + "eventemitter3": "^4.0.0", + "follow-redirects": "^1.0.0", + "requires-port": "^1.0.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/http-proxy-middleware": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-1.3.1.tgz", + "integrity": "sha512-13eVVDYS4z79w7f1+NPllJtOQFx/FdUW4btIvVRMaRlUY9VGstAbo5MOhLEuUgZFRHn3x50ufn25zkj/boZnEg==", + "dependencies": { + "@types/http-proxy": "^1.17.5", + "http-proxy": "^1.18.1", + "is-glob": "^4.0.1", + "is-plain-obj": "^3.0.0", + "micromatch": "^4.0.2" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/https-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", + "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=" + }, + "node_modules/human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "engines": { + "node": ">=10.17.0" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/icss-utils": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", + "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/iferr": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/iferr/-/iferr-0.1.5.tgz", + "integrity": "sha1-xg7taebY/bazEEofy8ocGS3FtQE=" + }, + "node_modules/ignore": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", + "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", + "engines": { + "node": ">= 4" + } + }, + "node_modules/immediate": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", + "integrity": "sha1-nbHb0Pr43m++D13V5Wu2BigN5ps=" + }, + "node_modules/import-cwd": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/import-cwd/-/import-cwd-2.1.0.tgz", + "integrity": "sha1-qmzzbnInYShcs3HsZRn1PiQ1sKk=", + "dependencies": { + "import-from": "^2.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/import-fresh": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-2.0.0.tgz", + "integrity": "sha1-2BNVwVYS04bGH53dOSLUMEgipUY=", + "dependencies": { + "caller-path": "^2.0.0", + "resolve-from": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/import-fresh/node_modules/resolve-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", + "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=", + "engines": { + "node": ">=4" + } + }, + "node_modules/import-from": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/import-from/-/import-from-2.1.0.tgz", + "integrity": "sha1-M1238qev/VOqpHHUuAId7ja387E=", + "dependencies": { + "resolve-from": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/import-from/node_modules/resolve-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", + "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=", + "engines": { + "node": ">=4" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "engines": { + "node": ">=8" + } + }, + "node_modules/indexes-of": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/indexes-of/-/indexes-of-1.0.1.tgz", + "integrity": "sha1-8w9xbI4r00bHtn0985FVZqfAVgc=" + }, + "node_modules/infer-owner": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", + "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==" + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" + }, + "node_modules/inquirer": { + "version": "7.3.3", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-7.3.3.tgz", + "integrity": "sha512-JG3eIAj5V9CwcGvuOmoo6LB9kbAYT8HXffUl6memuszlwDC/qvFAJw49XJ5NROSFNPxp3iQg1GqkFhaY/CR0IA==", + "dependencies": { + "ansi-escapes": "^4.2.1", + "chalk": "^4.1.0", + "cli-cursor": "^3.1.0", + "cli-width": "^3.0.0", + "external-editor": "^3.0.3", + "figures": "^3.0.0", + "lodash": "^4.17.19", + "mute-stream": "0.0.8", + "run-async": "^2.4.0", + "rxjs": "^6.6.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0", + "through": "^2.3.6" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/internal-slot": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz", + "integrity": "sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==", + "dependencies": { + "get-intrinsic": "^1.1.0", + "has": "^1.0.3", + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/ip": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.8.tgz", + "integrity": "sha512-PuExPYUiu6qMBQb4l06ecm6T6ujzhmh+MeJcW9wa89PoAz5pvd4zPgN5WJV104mb6S2T1AwNIAaB70JNrLQWhg==" + }, + "node_modules/is-absolute-url": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-absolute-url/-/is-absolute-url-2.1.0.tgz", + "integrity": "sha1-UFMN+4T8yap9vnhS6Do3uTufKqY=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-accessor-descriptor/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=" + }, + "node_modules/is-bigint": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", + "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "dependencies": { + "has-bigints": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-boolean-object": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", + "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" + }, + "node_modules/is-callable": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz", + "integrity": "sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-color-stop": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-color-stop/-/is-color-stop-1.1.0.tgz", + "integrity": "sha1-z/9HGu5N1cnhWFmPvhKWe1za00U=", + "dependencies": { + "css-color-names": "^0.0.4", + "hex-color-regex": "^1.1.0", + "hsl-regex": "^1.0.0", + "hsla-regex": "^1.0.0", + "rgb-regex": "^1.0.1", + "rgba-regex": "^1.0.0" + } + }, + "node_modules/is-core-module": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.9.0.tgz", + "integrity": "sha512-+5FPy5PnwmO3lvfMb0AsoPaBG+5KHUI0wYFXOtYPnVVVspTFUuMZNfNaNVRt3FZadstu2c8x23vykRW/NBoU6A==", + "dependencies": { + "has": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-data-descriptor/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-date-object": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", + "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dependencies": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-descriptor/node_modules/kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-directory": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/is-directory/-/is-directory-0.3.1.tgz", + "integrity": "sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-docker": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-generator-function": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", + "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-negative-zero": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", + "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-number-object": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", + "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-obj": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", + "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-plain-obj": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-3.0.0.tgz", + "integrity": "sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-regex": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-resolvable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.1.0.tgz", + "integrity": "sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg==" + }, + "node_modules/is-retry-allowed": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-2.2.0.tgz", + "integrity": "sha512-XVm7LOeLpTW4jV19QSH38vkswxoLud8sQ57YwJVTPWdiaI9I8keEhGFpBlslyVsgdQy4Opg8QOLb8YRgsyZiQg==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-shared-array-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", + "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-ssh": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/is-ssh/-/is-ssh-1.3.3.tgz", + "integrity": "sha512-NKzJmQzJfEEma3w5cJNcUMxoXfDjz0Zj0eyCalHn2E6VOwlzjZo0yuO2fcBSf8zhFuVCL/82/r5gRcoi6aEPVQ==", + "dependencies": { + "protocols": "^1.1.0" + } + }, + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-string": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", + "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-symbol": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", + "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-url-superb": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-url-superb/-/is-url-superb-4.0.0.tgz", + "integrity": "sha512-GI+WjezhPPcbM+tqE9LnmsY5qqjwHzTvjJ36wxYX5ujNXefSUJ/T17r5bqDV8yLhcgB59KTPNOc9O9cmHTPWsA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-weakref": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", + "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-windows": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "dev": true, + "dependencies": { + "is-docker": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" + }, + "node_modules/isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/jest-worker": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-26.6.2.tgz", + "integrity": "sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ==", + "dependencies": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^7.0.0" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/jimp-compact": { + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/jimp-compact/-/jimp-compact-0.16.1.tgz", + "integrity": "sha512-dZ6Ra7u1G8c4Letq/B5EzAxj4tLFHL+cGtdpR+PVm4yzPDj+lCk+AbivWt1eOM+ikzkowtyV7qSqX6qr3t71Ww==", + "dev": true + }, + "node_modules/jiti": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.13.0.tgz", + "integrity": "sha512-/n9mNxZj/HDSrincJ6RP+L+yXbpnB8FybySBa+IjIaoH9FIxBbrbRT5XUbe8R7zuVM2AQqNMNDDqz0bzx3znOQ==", + "bin": { + "jiti": "bin/jiti.js" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + }, + "node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/json-parse-better-errors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==" + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true + }, + "node_modules/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==" + }, + "node_modules/json5": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz", + "integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/jszip": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.9.1.tgz", + "integrity": "sha512-H9A60xPqJ1CuC4Ka6qxzXZeU8aNmgOeP5IFqwJbQQwtu2EUYxota3LdsiZWplF7Wgd9tkAd0mdu36nceSaPuYw==", + "dependencies": { + "lie": "~3.3.0", + "pako": "~1.0.2", + "readable-stream": "~2.3.6", + "set-immediate-shim": "~1.0.1" + } + }, + "node_modules/keygrip": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/keygrip/-/keygrip-1.1.0.tgz", + "integrity": "sha512-iYSchDJ+liQ8iwbSI2QqsQOvqv58eJCEanyJPJi+Khyu8smkcKSFUCbPwzFcL7YVtZ6eONjqRX/38caJ7QjRAQ==", + "dev": true, + "dependencies": { + "tsscmp": "1.0.6" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/klona": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/klona/-/klona-2.0.5.tgz", + "integrity": "sha512-pJiBpiXMbt7dkzXe8Ghj/u4FfXOOa98fPW+bihOJ4SjnoijweJrNThJfd3ifXpXhREjpoF2mZVH1GfS9LV3kHQ==", + "engines": { + "node": ">= 8" + } + }, + "node_modules/koa": { + "version": "2.13.4", + "resolved": "https://registry.npmjs.org/koa/-/koa-2.13.4.tgz", + "integrity": "sha512-43zkIKubNbnrULWlHdN5h1g3SEKXOEzoAlRsHOTFpnlDu8JlAOZSMJBLULusuXRequboiwJcj5vtYXKB3k7+2g==", + "dev": true, + "dependencies": { + "accepts": "^1.3.5", + "cache-content-type": "^1.0.0", + "content-disposition": "~0.5.2", + "content-type": "^1.0.4", + "cookies": "~0.8.0", + "debug": "^4.3.2", + "delegates": "^1.0.0", + "depd": "^2.0.0", + "destroy": "^1.0.4", + "encodeurl": "^1.0.2", + "escape-html": "^1.0.3", + "fresh": "~0.5.2", + "http-assert": "^1.3.0", + "http-errors": "^1.6.3", + "is-generator-function": "^1.0.7", + "koa-compose": "^4.1.0", + "koa-convert": "^2.0.0", + "on-finished": "^2.3.0", + "only": "~0.0.2", + "parseurl": "^1.3.2", + "statuses": "^1.5.0", + "type-is": "^1.6.16", + "vary": "^1.1.2" + }, + "engines": { + "node": "^4.8.4 || ^6.10.1 || ^7.10.1 || >= 8.1.4" + } + }, + "node_modules/koa-compose": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/koa-compose/-/koa-compose-4.1.0.tgz", + "integrity": "sha512-8ODW8TrDuMYvXRwra/Kh7/rJo9BtOfPc6qO8eAfC80CnCvSjSl0bkRM24X6/XBBEyj0v1nRUQ1LyOy3dbqOWXw==", + "dev": true + }, + "node_modules/koa-convert": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/koa-convert/-/koa-convert-2.0.0.tgz", + "integrity": "sha512-asOvN6bFlSnxewce2e/DK3p4tltyfC4VM7ZwuTuepI7dEQVcvpyFuBcEARu1+Hxg8DIwytce2n7jrZtRlPrARA==", + "dev": true, + "dependencies": { + "co": "^4.6.0", + "koa-compose": "^4.1.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/koa-send": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/koa-send/-/koa-send-5.0.1.tgz", + "integrity": "sha512-tmcyQ/wXXuxpDxyNXv5yNNkdAMdFRqwtegBXUaowiQzUKqJehttS0x2j0eOZDQAyloAth5w6wwBImnFzkUz3pQ==", + "dev": true, + "dependencies": { + "debug": "^4.1.1", + "http-errors": "^1.7.3", + "resolve-path": "^1.4.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/koa-send/node_modules/depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/koa-send/node_modules/http-errors": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz", + "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==", + "dev": true, + "dependencies": { + "depd": "~1.1.2", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/koa-static": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/koa-static/-/koa-static-5.0.0.tgz", + "integrity": "sha512-UqyYyH5YEXaJrf9S8E23GoJFQZXkBVJ9zYYMPGz919MSX1KuvAcycIuS0ci150HCoPf4XQVhQ84Qf8xRPWxFaQ==", + "dev": true, + "dependencies": { + "debug": "^3.1.0", + "koa-send": "^5.0.0" + }, + "engines": { + "node": ">= 7.6.0" + } + }, + "node_modules/koa-static/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/koa/node_modules/http-errors": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz", + "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==", + "dev": true, + "dependencies": { + "depd": "~1.1.2", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/koa/node_modules/http-errors/node_modules/depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/last-call-webpack-plugin": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/last-call-webpack-plugin/-/last-call-webpack-plugin-3.0.0.tgz", + "integrity": "sha512-7KI2l2GIZa9p2spzPIVZBYyNKkN+e/SQPpnjlTiPhdbDW3F86tdKKELxKpzJ5sgU19wQWsACULZmpTPYHeWO5w==", + "dependencies": { + "lodash": "^4.17.5", + "webpack-sources": "^1.1.0" + } + }, + "node_modules/launch-editor": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.3.0.tgz", + "integrity": "sha512-3QrsCXejlWYHjBPFXTyGNhPj4rrQdB+5+r5r3wArpLH201aR+nWUgw/zKKkTmilCfY/sv6u8qo98pNvtg8LUTA==", + "dependencies": { + "picocolors": "^1.0.0", + "shell-quote": "^1.6.1" + } + }, + "node_modules/launch-editor-middleware": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/launch-editor-middleware/-/launch-editor-middleware-2.3.0.tgz", + "integrity": "sha512-GJR64trLdFFwCoL9DMn/d1SZX0OzTDPixu4mcfWTShQ4tIqCHCGvlg9fOEYQXyBlrSMQwylsJfUWncheShfV2w==", + "dependencies": { + "launch-editor": "^2.3.0" + } + }, + "node_modules/libarchive.js": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/libarchive.js/-/libarchive.js-1.3.0.tgz", + "integrity": "sha512-EkQfRXt9DhWwj6BnEA2TNpOf4jTnzSTUPGgE+iFxcdNqjktY8GitbDeHnx8qZA0/IukNyyBUR3oQKRdYkO+HFg==" + }, + "node_modules/lie": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz", + "integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==", + "dependencies": { + "immediate": "~3.0.5" + } + }, + "node_modules/lilconfig": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.0.5.tgz", + "integrity": "sha512-xaYmXZtTHPAw5m+xLN8ab9C+3a8YmV3asNSPOATITbtwrfbwaLJj8h66H1WMIpALCkqsIzK3h7oQ+PdX+LQ9Eg==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true + }, + "node_modules/loader-runner": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", + "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", + "engines": { + "node": ">=6.11.5" + } + }, + "node_modules/loader-utils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.2.tgz", + "integrity": "sha512-TM57VeHptv569d/GKh6TAYdzKblwDNiumOdkFnejjD0XwTH87K90w3O7AiJRqdQoXygvi1VQTJTLGhJl7WqA7A==", + "dependencies": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + }, + "engines": { + "node": ">=8.9.0" + } + }, + "node_modules/localforage": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/localforage/-/localforage-1.10.0.tgz", + "integrity": "sha512-14/H1aX7hzBBmmh7sGPd+AOMkkIrHM3Z1PAyGgZigA1H1p5O5ANnMyWzvpAETtG68/dC4pC0ncy3+PPGzXZHPg==", + "dependencies": { + "lie": "3.1.1" + } + }, + "node_modules/localforage/node_modules/lie": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/lie/-/lie-3.1.1.tgz", + "integrity": "sha1-mkNrLMd0bKWd56QfpGmz77dr2H4=", + "dependencies": { + "immediate": "~3.0.5" + } + }, + "node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "node_modules/lodash._reinterpolate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", + "integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=" + }, + "node_modules/lodash.debounce": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", + "integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168=" + }, + "node_modules/lodash.kebabcase": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.kebabcase/-/lodash.kebabcase-4.1.1.tgz", + "integrity": "sha1-hImxyw0p/4gZXM7KRI/21swpXDY=" + }, + "node_modules/lodash.memoize": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", + "integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=" + }, + "node_modules/lodash.sortby": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", + "integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=" + }, + "node_modules/lodash.template": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-4.5.0.tgz", + "integrity": "sha512-84vYFxIkmidUiFxidA/KjjH9pAycqW+h980j7Fuz5qxRtO9pgB7MDFTdys1N7A5mcucRiDyEq4fusljItR1T/A==", + "dependencies": { + "lodash._reinterpolate": "^3.0.0", + "lodash.templatesettings": "^4.0.0" + } + }, + "node_modules/lodash.templatesettings": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-4.2.0.tgz", + "integrity": "sha512-stgLz+i3Aa9mZgnjr/O+v9ruKZsPsndy7qPZOchbqk2cnTU1ZaldKK+v7m54WoKIyxiuMZTKT2H81F8BeAc3ZQ==", + "dependencies": { + "lodash._reinterpolate": "^3.0.0" + } + }, + "node_modules/lodash.topath": { + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/lodash.topath/-/lodash.topath-4.5.2.tgz", + "integrity": "sha512-1/W4dM+35DwvE/iEd1M9ekewOSTlpFekhw9mhAtrwjVqUr83/ilQiyAvmg4tVX7Unkcfl1KC+i9WdaT4B6aQcg==", + "dev": true + }, + "node_modules/lodash.uniq": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", + "integrity": "sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=" + }, + "node_modules/lower-case": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-1.1.4.tgz", + "integrity": "sha1-miyr0bno4K6ZOkv31YdcOcQujqw=" + }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dependencies": { + "semver": "^6.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/make-dir/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/map-age-cleaner": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz", + "integrity": "sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==", + "dependencies": { + "p-defer": "^1.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/map-cache": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", + "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/map-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", + "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", + "dependencies": { + "object-visit": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/marked": { + "version": "4.0.17", + "resolved": "https://registry.npmjs.org/marked/-/marked-4.0.17.tgz", + "integrity": "sha512-Wfk0ATOK5iPxM4ptrORkFemqroz0ZDxp5MWfYA7H/F+wO17NRWV5Ypxi6p3g2Xmw2bKeiYOl6oVnLHKxBA0VhA==", + "bin": { + "marked": "bin/marked.js" + }, + "engines": { + "node": ">= 12" + } + }, + "node_modules/marks-pane": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/marks-pane/-/marks-pane-1.0.9.tgz", + "integrity": "sha512-Ahs4oeG90tbdPWwAJkAAoHg2lRR8lAs9mZXETNPO9hYg3AkjUJBKi1NQ4aaIQZVGrig7c/3NUV1jANl8rFTeMg==" + }, + "node_modules/md5.js": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", + "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", + "dependencies": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "node_modules/mdn-data": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.4.tgz", + "integrity": "sha512-iV3XNKw06j5Q7mi6h+9vbx23Tv7JkjEVgKHW4pimwyDGWm0OIQntJJ+u1C6mg6mK1EaTv42XQ7w76yuzH7M2cA==" + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mem": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/mem/-/mem-8.1.1.tgz", + "integrity": "sha512-qFCFUDs7U3b8mBDPyz5EToEKoAkgCzqquIgi9nkkR9bixxOVOre+09lbuH7+9Kn2NFpm56M3GUWVbU2hQgdACA==", + "dependencies": { + "map-age-cleaner": "^0.1.3", + "mimic-fn": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/mem?sponsor=1" + } + }, + "node_modules/mem/node_modules/mimic-fn": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-3.1.0.tgz", + "integrity": "sha512-Ysbi9uYW9hFyfrThdDEQuykN4Ey6BuwPD2kpI5ES/nFTDn/98yxYNLZJcgUAKPT/mcrLLKaGzJR9YVxJrIdASQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/memfs": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.4.1.tgz", + "integrity": "sha512-1c9VPVvW5P7I85c35zAdEr1TD5+F11IToIHIlrVIcflfnzPkJa0ZoYEoEdYDP8KgPFoSZ/opDrUsAoZWym3mtw==", + "dependencies": { + "fs-monkey": "1.0.3" + }, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/memory-fs": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.5.0.tgz", + "integrity": "sha512-jA0rdU5KoQMC0e6ppoNRtpp6vjFq6+NY7r8hywnC7V+1Xj/MtHwGIbB1QaK/dunyjWteJzmkpd7ooeWg10T7GA==", + "dependencies": { + "errno": "^0.1.3", + "readable-stream": "^2.0.1" + }, + "engines": { + "node": ">=4.3.0 <5.0.0 || >=5.10" + } + }, + "node_modules/merge-source-map": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/merge-source-map/-/merge-source-map-1.1.0.tgz", + "integrity": "sha512-Qkcp7P2ygktpMPh2mCQZaf3jhN6D3Z/qVZHSdWvQ+2Ef5HgRAPBO57A77+ENm0CPx2+1Ce/MYKi3ymqdfuqibw==", + "dependencies": { + "source-map": "^0.6.1" + } + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==" + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "engines": { + "node": ">= 8" + } + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "dependencies": { + "braces": "^3.0.2", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/miller-rabin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", + "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", + "dependencies": { + "bn.js": "^4.0.0", + "brorand": "^1.0.1" + }, + "bin": { + "miller-rabin": "bin/miller-rabin" + } + }, + "node_modules/miller-rabin/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + }, + "node_modules/mime": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.5.2.tgz", + "integrity": "sha512-tqkh47FzKeCPD2PUiPB6pkbMzsCasjxAfC62/Wap5qrUWcb+sFasXUC5I3gYM5iBM8v/Qpn4UK0x+j0iHyFPDg==", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==" + }, + "node_modules/minimalistic-crypto-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", + "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=" + }, + "node_modules/minimatch": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.8.tgz", + "integrity": "sha512-6FsRAQsxQ61mw+qP1ZzbL9Bc78x2p5OqNgNpnoAFLTrX8n5Kxph0CsnhmKKNXTWjXqU5L0pGPR7hYk+XWZr60Q==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", + "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==" + }, + "node_modules/minipass": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.6.tgz", + "integrity": "sha512-rty5kpw9/z8SX9dmxblFA6edItUmwJgMeYDZRrwlIVN27i8gysGbznJwUggw2V/FVqFSDdWy040ZPS811DYAqQ==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-collect": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz", + "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minipass-flush": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", + "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minipass-pipeline": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", + "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "node_modules/minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "dependencies": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minizlib/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "node_modules/mississippi": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-3.0.0.tgz", + "integrity": "sha512-x471SsVjUtBRtcvd4BzKE9kFC+/2TeWgKCgw0bZcw1b9l2X3QX5vCWgF+KaZaYm87Ss//rHnWryupDrgLvmSkA==", + "dependencies": { + "concat-stream": "^1.5.0", + "duplexify": "^3.4.2", + "end-of-stream": "^1.1.0", + "flush-write-stream": "^1.0.0", + "from2": "^2.1.0", + "parallel-transform": "^1.1.0", + "pump": "^3.0.0", + "pumpify": "^1.3.3", + "stream-each": "^1.1.0", + "through2": "^2.0.0" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/mixin-deep": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", + "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", + "dependencies": { + "for-in": "^1.0.2", + "is-extendable": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/mixin-deep/node_modules/is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dependencies": { + "is-plain-object": "^2.0.4" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "dependencies": { + "minimist": "^1.2.6" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/modern-normalize": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/modern-normalize/-/modern-normalize-1.1.0.tgz", + "integrity": "sha512-2lMlY1Yc1+CUy0gw4H95uNN7vjbpoED7NNRSBHE25nWfLBdmMzFCsPshlzbxHz+gYMcBEUN8V4pU16prcdPSgA==", + "dev": true, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/move-concurrently": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz", + "integrity": "sha1-viwAX9oy4LKa8fBdfEszIUxwH5I=", + "dependencies": { + "aproba": "^1.1.1", + "copy-concurrently": "^1.0.0", + "fs-write-stream-atomic": "^1.0.8", + "mkdirp": "^0.5.1", + "rimraf": "^2.5.4", + "run-queue": "^1.0.3" + } + }, + "node_modules/mrmime": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-1.0.0.tgz", + "integrity": "sha512-a70zx7zFfVO7XpnQ2IX1Myh9yY4UYvfld/dikWRnsXxbyvMcfz+u6UfgNAtH+k2QqtJuzVpv6eLTx1G2+WKZbQ==", + "engines": { + "node": ">=10" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/mustache": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/mustache/-/mustache-2.3.2.tgz", + "integrity": "sha512-KpMNwdQsYz3O/SBS1qJ/o3sqUJ5wSb8gb0pul8CO0S56b9Y2ALm8zCfsjPXsqGFfoNBkDwZuZIAjhsZI03gYVQ==", + "bin": { + "mustache": "bin/mustache" + }, + "engines": { + "npm": ">=1.4.0" + } + }, + "node_modules/mute-stream": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", + "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==" + }, + "node_modules/nan": { + "version": "2.15.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.15.0.tgz", + "integrity": "sha512-8ZtvEnA2c5aYCZYd1cvgdnU6cqwixRoYg70xPLWUws5ORTa/lnw+u4amixRS/Ac5U5mQVgp9pnlSUnbNWFaWZQ==", + "optional": true + }, + "node_modules/nanoid": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz", + "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/nanomatch": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", + "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", + "dependencies": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "fragment-cache": "^0.2.1", + "is-windows": "^1.0.2", + "kind-of": "^6.0.2", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/nanomatch/node_modules/define-property": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", + "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", + "dependencies": { + "is-descriptor": "^1.0.2", + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/nanomatch/node_modules/extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dependencies": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/nanomatch/node_modules/is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dependencies": { + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/nanomatch/node_modules/is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dependencies": { + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/nanomatch/node_modules/is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dependencies": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/nanomatch/node_modules/is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dependencies": { + "is-plain-object": "^2.0.4" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==" + }, + "node_modules/next-tick": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz", + "integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==" + }, + "node_modules/no-case": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/no-case/-/no-case-2.3.2.tgz", + "integrity": "sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ==", + "dependencies": { + "lower-case": "^1.1.1" + } + }, + "node_modules/node-emoji": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-1.11.0.tgz", + "integrity": "sha512-wo2DpQkQp7Sjm2A0cq+sN7EHKO6Sl0ctXeBdFZrL9T9+UywORbufTcTZxom8YqpLQt/FqNMUkOpkZrJVYSKD3A==", + "dev": true, + "dependencies": { + "lodash": "^4.17.21" + } + }, + "node_modules/node-fetch": { + "version": "2.6.7", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", + "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/node-html-parser": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/node-html-parser/-/node-html-parser-3.3.6.tgz", + "integrity": "sha512-VkWDHvNgFGB3mbQGMyzqRE1i/BG7TKX9wRXC8e/v8kL0kZR/Oy6RjYxXH91K6/+m3g8iQ8dTqRy75lTYoA2Cjg==", + "dependencies": { + "css-select": "^4.1.3", + "he": "1.2.0" + } + }, + "node_modules/node-libs-browser": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.2.1.tgz", + "integrity": "sha512-h/zcD8H9kaDZ9ALUWwlBUDo6TKF8a7qBSCSEGfjTVIYeqsioSKaAX+BN7NgiMGp6iSIXZ3PxgCu8KS3b71YK5Q==", + "dependencies": { + "assert": "^1.1.1", + "browserify-zlib": "^0.2.0", + "buffer": "^4.3.0", + "console-browserify": "^1.1.0", + "constants-browserify": "^1.0.0", + "crypto-browserify": "^3.11.0", + "domain-browser": "^1.1.1", + "events": "^3.0.0", + "https-browserify": "^1.0.0", + "os-browserify": "^0.3.0", + "path-browserify": "0.0.1", + "process": "^0.11.10", + "punycode": "^1.2.4", + "querystring-es3": "^0.2.0", + "readable-stream": "^2.3.3", + "stream-browserify": "^2.0.1", + "stream-http": "^2.7.2", + "string_decoder": "^1.0.0", + "timers-browserify": "^2.0.4", + "tty-browserify": "0.0.0", + "url": "^0.11.0", + "util": "^0.11.0", + "vm-browserify": "^1.0.1" + } + }, + "node_modules/node-libs-browser/node_modules/buffer": { + "version": "4.9.2", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz", + "integrity": "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==", + "dependencies": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4", + "isarray": "^1.0.0" + } + }, + "node_modules/node-libs-browser/node_modules/punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" + }, + "node_modules/node-object-hash": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/node-object-hash/-/node-object-hash-1.4.2.tgz", + "integrity": "sha512-UdS4swXs85fCGWWf6t6DMGgpN/vnlKeSGEQ7hJcrs7PBFoxoKLmibc3QRb7fwiYsjdL7PX8iI/TMSlZ90dgHhQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/node-releases": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.4.tgz", + "integrity": "sha512-gbMzqQtTtDz/00jQzZ21PQzdI9PyLYqUSvD0p3naOhX4odFji0ZxYdnVwPTxmSwkmxhcFImpozceidSG+AgoPQ==" + }, + "node_modules/node-res": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/node-res/-/node-res-5.0.1.tgz", + "integrity": "sha512-YOleO9c7MAqoHC+Ccu2vzvV1fL6Ku49gShq3PIMKWHRgrMSih3XcwL05NbLBi6oU2J471gTBfdpVVxwT6Pfhxg==", + "dependencies": { + "destroy": "^1.0.4", + "etag": "^1.8.1", + "mime-types": "^2.1.19", + "on-finished": "^2.3.0", + "vary": "^1.1.2" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/normalize-range": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", + "integrity": "sha1-LRDAa9/TEuqXd2laTShDlFa3WUI=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/normalize-url": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-1.9.1.tgz", + "integrity": "sha1-LMDWazHqIwNkWENuNiDYWVTGbDw=", + "dependencies": { + "object-assign": "^4.0.1", + "prepend-http": "^1.0.0", + "query-string": "^4.1.0", + "sort-keys": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/nth-check": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.0.1.tgz", + "integrity": "sha512-it1vE95zF6dTT9lBsYbxvqh0Soy4SPowchj0UBGj/V6cTPnXXtQOPUbhZ6CmGzAD/rW22LQK6E96pcdJXk4A4w==", + "dependencies": { + "boolbase": "^1.0.0" + }, + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" + } + }, + "node_modules/num2fraction": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/num2fraction/-/num2fraction-1.2.2.tgz", + "integrity": "sha1-b2gragJ6Tp3fpFZM0lidHU5mnt4=" + }, + "node_modules/nuxt": { + "version": "2.15.8", + "resolved": "https://registry.npmjs.org/nuxt/-/nuxt-2.15.8.tgz", + "integrity": "sha512-ceK3qLg/Baj7J8mK9bIxqw9AavrF+LXqwYEreBdY/a4Sj8YV4mIvhqea/6E7VTCNNGvKT2sJ/TTJjtfQ597lTA==", + "hasInstallScript": true, + "dependencies": { + "@nuxt/babel-preset-app": "2.15.8", + "@nuxt/builder": "2.15.8", + "@nuxt/cli": "2.15.8", + "@nuxt/components": "^2.1.8", + "@nuxt/config": "2.15.8", + "@nuxt/core": "2.15.8", + "@nuxt/generator": "2.15.8", + "@nuxt/loading-screen": "^2.0.3", + "@nuxt/opencollective": "^0.3.2", + "@nuxt/server": "2.15.8", + "@nuxt/telemetry": "^1.3.3", + "@nuxt/utils": "2.15.8", + "@nuxt/vue-app": "2.15.8", + "@nuxt/vue-renderer": "2.15.8", + "@nuxt/webpack": "2.15.8" + }, + "bin": { + "nuxt": "bin/nuxt.js" + } + }, + "node_modules/nuxt-socket-io": { + "version": "1.1.24", + "resolved": "https://registry.npmjs.org/nuxt-socket-io/-/nuxt-socket-io-1.1.24.tgz", + "integrity": "sha512-ax9Q9ye0i+yrw/VBLGZVZA2WOj/qdRq7O9i8p6eMX7b+SCqa/7FSFdWTJsOoAIDZ9gPFyF+dK19h8pg/h/bCEg==", + "dependencies": { + "@nuxt/types": "^2.15.5", + "glob": "^7.1.7", + "socket.io": "^4.1.1", + "socket.io-client": "^4.1.1", + "tiny-emitter": "^2.1.0" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-copy": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", + "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", + "dependencies": { + "copy-descriptor": "^0.1.0", + "define-property": "^0.2.5", + "kind-of": "^3.0.3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-copy/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-hash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", + "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/object-inspect": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.0.tgz", + "integrity": "sha512-Ho2z80bVIvJloH+YzRmpZVQe87+qASmBUKZDWgx9cu+KDrX2ZDH/3tMy+gXbZETVGs2M8YdxObOh7XAtim9Y0g==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object-visit": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", + "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", + "dependencies": { + "isobject": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object.assign": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", + "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", + "dependencies": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3", + "has-symbols": "^1.0.1", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.getownpropertydescriptors": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.3.tgz", + "integrity": "sha512-VdDoCwvJI4QdC6ndjpqFmoL3/+HxffFBbcJzKi5hwLLqqx3mdbedRpfZDdK0SrOSauj8X4GzBvnDZl4vTN7dOw==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.1" + }, + "engines": { + "node": ">= 0.8" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.pick": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", + "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object.values": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.5.tgz", + "integrity": "sha512-QUZRW0ilQ3PnPpbNtgdNV1PDbEqLIiSFB3l+EnGtBQ/8SUTLj1PZwtQHABZtLgwpJZTSZhuGLOGk57Drx2IvYg==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/on-headers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", + "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/only": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/only/-/only-0.0.2.tgz", + "integrity": "sha512-Fvw+Jemq5fjjyWz6CpKx6w9s7xxqo3+JCyM0WXWeCSOboZ8ABkyvP8ID4CZuChA/wxSx+XSJmdOm8rGVyJ1hdQ==", + "dev": true + }, + "node_modules/open": { + "version": "7.4.2", + "resolved": "https://registry.npmjs.org/open/-/open-7.4.2.tgz", + "integrity": "sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q==", + "dev": true, + "dependencies": { + "is-docker": "^2.0.0", + "is-wsl": "^2.1.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/opener": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/opener/-/opener-1.5.2.tgz", + "integrity": "sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==", + "bin": { + "opener": "bin/opener-bin.js" + } + }, + "node_modules/optimize-css-assets-webpack-plugin": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/optimize-css-assets-webpack-plugin/-/optimize-css-assets-webpack-plugin-5.0.8.tgz", + "integrity": "sha512-mgFS1JdOtEGzD8l+EuISqL57cKO+We9GcoiQEmdCWRqqck+FGNmYJtx9qfAPzEz+lRrlThWMuGDaRkI/yWNx/Q==", + "dependencies": { + "cssnano": "^4.1.10", + "last-call-webpack-plugin": "^3.0.0" + }, + "peerDependencies": { + "webpack": "^4.0.0" + } + }, + "node_modules/os-browserify": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", + "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=" + }, + "node_modules/os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/p-defer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz", + "integrity": "sha1-n26xgvbJqozXQwBKfU+WsZaw+ww=", + "engines": { + "node": ">=4" + } + }, + "node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-map": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", + "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "dependencies": { + "aggregate-error": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "engines": { + "node": ">=6" + } + }, + "node_modules/pako": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==" + }, + "node_modules/parallel-transform": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/parallel-transform/-/parallel-transform-1.2.0.tgz", + "integrity": "sha512-P2vSmIu38uIlvdcU7fDkyrxj33gTUy/ABO5ZUbGowxNCopBq/OoD42bP4UmMrJoPyk4Uqf0mu3mtWBhHCZD8yg==", + "dependencies": { + "cyclist": "^1.0.1", + "inherits": "^2.0.3", + "readable-stream": "^2.1.5" + } + }, + "node_modules/param-case": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/param-case/-/param-case-2.1.1.tgz", + "integrity": "sha1-35T9jPZTHs915r75oIWPvHK+Ikc=", + "dependencies": { + "no-case": "^2.2.0" + } + }, + "node_modules/parent-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-2.0.0.tgz", + "integrity": "sha512-uo0Z9JJeWzv8BG+tRcapBKNJ0dro9cLyczGzulS6EfeyAdeC9sbojtW6XwvYxJkEne9En+J2XEl4zyglVeIwFg==", + "dev": true, + "dependencies": { + "callsites": "^3.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/parent-module/node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-asn1": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.6.tgz", + "integrity": "sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw==", + "dependencies": { + "asn1.js": "^5.2.0", + "browserify-aes": "^1.0.0", + "evp_bytestokey": "^1.0.0", + "pbkdf2": "^3.0.3", + "safe-buffer": "^5.1.1" + } + }, + "node_modules/parse-git-config": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/parse-git-config/-/parse-git-config-3.0.0.tgz", + "integrity": "sha512-wXoQGL1D+2COYWCD35/xbiKma1Z15xvZL8cI25wvxzled58V51SJM04Urt/uznS900iQor7QO04SgdfT/XlbuA==", + "dependencies": { + "git-config-path": "^2.0.0", + "ini": "^1.3.5" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "dependencies": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/parse-path": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/parse-path/-/parse-path-4.0.3.tgz", + "integrity": "sha512-9Cepbp2asKnWTJ9x2kpw6Fe8y9JDbqwahGCTvklzd/cEq5C5JC59x2Xb0Kx+x0QZ8bvNquGO8/BWP0cwBHzSAA==", + "dependencies": { + "is-ssh": "^1.3.0", + "protocols": "^1.4.0", + "qs": "^6.9.4", + "query-string": "^6.13.8" + } + }, + "node_modules/parse-path/node_modules/query-string": { + "version": "6.14.1", + "resolved": "https://registry.npmjs.org/query-string/-/query-string-6.14.1.tgz", + "integrity": "sha512-XDxAeVmpfu1/6IjyT/gXHOl+S0vQ9owggJ30hhWKdHAsNPOcasn5o9BW0eejZqL2e4vMjhAxoW3jVHcD6mbcYw==", + "dependencies": { + "decode-uri-component": "^0.2.0", + "filter-obj": "^1.1.0", + "split-on-first": "^1.0.0", + "strict-uri-encode": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parse-path/node_modules/strict-uri-encode": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz", + "integrity": "sha1-ucczDHBChi9rFC3CdLvMWGbONUY=", + "engines": { + "node": ">=4" + } + }, + "node_modules/parse-url": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/parse-url/-/parse-url-6.0.0.tgz", + "integrity": "sha512-cYyojeX7yIIwuJzledIHeLUBVJ6COVLeT4eF+2P6aKVzwvgKQPndCBv3+yQ7pcWjqToYwaligxzSYNNmGoMAvw==", + "dependencies": { + "is-ssh": "^1.3.0", + "normalize-url": "^6.1.0", + "parse-path": "^4.0.0", + "protocols": "^1.4.0" + } + }, + "node_modules/parse-url/node_modules/normalize-url": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", + "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/pascal-case": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz", + "integrity": "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==", + "dependencies": { + "no-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/pascal-case/node_modules/lower-case": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", + "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==", + "dependencies": { + "tslib": "^2.0.3" + } + }, + "node_modules/pascal-case/node_modules/no-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", + "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", + "dependencies": { + "lower-case": "^2.0.2", + "tslib": "^2.0.3" + } + }, + "node_modules/pascal-case/node_modules/tslib": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" + }, + "node_modules/pascalcase": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", + "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-browserify": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.1.tgz", + "integrity": "sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ==" + }, + "node_modules/path-dirname": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", + "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=", + "optional": true + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" + }, + "node_modules/path-to-regexp": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.2.1.tgz", + "integrity": "sha512-JLyh7xT1kizaEvcaXOQwOc2/Yhw6KZOvPf1S8401UyLk86CU79LN3vl7ztXGm/pZ+YjoyAJ4rxmHwbkBXJX+yw==", + "dev": true + }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-webpack": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/path-webpack/-/path-webpack-0.0.3.tgz", + "integrity": "sha1-/23sdJ7sWpRgXATV9j/FVgegOhY=" + }, + "node_modules/pbkdf2": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.2.tgz", + "integrity": "sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==", + "dependencies": { + "create-hash": "^1.1.2", + "create-hmac": "^1.1.4", + "ripemd160": "^2.0.1", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + }, + "engines": { + "node": ">=0.12" + } + }, + "node_modules/pdfjs-dist": { + "version": "2.6.347", + "resolved": "https://registry.npmjs.org/pdfjs-dist/-/pdfjs-dist-2.6.347.tgz", + "integrity": "sha512-QC+h7hG2su9v/nU1wEI3SnpPIrqJODL7GTDFvR74ANKGq1AFJW16PH8VWnhpiTi9YcLSFV9xLeWSgq+ckHLdVQ==" + }, + "node_modules/picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pify": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-5.0.0.tgz", + "integrity": "sha512-eW/gHNMlxdSP6dmG6uJip6FXN0EQBwm2clYYd8Wul42Cwu/DK8HEftzsapcNdYe2MfLiIwZqsDk2RDEsTE79hA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dependencies": { + "find-up": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pnp-webpack-plugin": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/pnp-webpack-plugin/-/pnp-webpack-plugin-1.7.0.tgz", + "integrity": "sha512-2Rb3vm+EXble/sMXNSu6eoBx8e79gKqhNq9F5ZWW6ERNCTE/Q0wQNne5541tE5vKjfM8hpNCYL+LGc1YTfI0dg==", + "dependencies": { + "ts-pnp": "^1.1.6" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/portfinder": { + "version": "1.0.28", + "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.28.tgz", + "integrity": "sha512-Se+2isanIcEqf2XMHjyUKskczxbPH7dQnlMjXX6+dybayyHvAf/TCgyMRlzf/B6QDhAEFOGes0pzRo3by4AbMA==", + "dev": true, + "dependencies": { + "async": "^2.6.2", + "debug": "^3.1.1", + "mkdirp": "^0.5.5" + }, + "engines": { + "node": ">= 0.12.0" + } + }, + "node_modules/portfinder/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/posix-character-classes": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", + "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postcss": { + "version": "8.4.14", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.14.tgz", + "integrity": "sha512-E398TUmfAYFPBSdzgeieK2Y1+1cpdxJx8yXbK/m57nRhKSmk1GB2tO4lbLBtlkfPQTDKfe4Xqv1ASWPpayPEig==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + } + ], + "dependencies": { + "nanoid": "^3.3.4", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-attribute-case-insensitive": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-attribute-case-insensitive/-/postcss-attribute-case-insensitive-4.0.2.tgz", + "integrity": "sha512-clkFxk/9pcdb4Vkn0hAHq3YnxBQ2p0CGD1dy24jN+reBck+EWxMbxSUqN4Yj7t0w8csl87K6p0gxBe1utkJsYA==", + "dependencies": { + "postcss": "^7.0.2", + "postcss-selector-parser": "^6.0.2" + } + }, + "node_modules/postcss-attribute-case-insensitive/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "node_modules/postcss-attribute-case-insensitive/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/postcss-calc": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-7.0.5.tgz", + "integrity": "sha512-1tKHutbGtLtEZF6PT4JSihCHfIVldU72mZ8SdZHIYriIZ9fh9k9aWSppaT8rHsyI3dX+KSR+W+Ix9BMY3AODrg==", + "dependencies": { + "postcss": "^7.0.27", + "postcss-selector-parser": "^6.0.2", + "postcss-value-parser": "^4.0.2" + } + }, + "node_modules/postcss-calc/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "node_modules/postcss-calc/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/postcss-color-functional-notation": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/postcss-color-functional-notation/-/postcss-color-functional-notation-2.0.1.tgz", + "integrity": "sha512-ZBARCypjEDofW4P6IdPVTLhDNXPRn8T2s1zHbZidW6rPaaZvcnCS2soYFIQJrMZSxiePJ2XIYTlcb2ztr/eT2g==", + "dependencies": { + "postcss": "^7.0.2", + "postcss-values-parser": "^2.0.0" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/postcss-color-functional-notation/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "node_modules/postcss-color-functional-notation/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/postcss-color-functional-notation/node_modules/postcss-values-parser": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/postcss-values-parser/-/postcss-values-parser-2.0.1.tgz", + "integrity": "sha512-2tLuBsA6P4rYTNKCXYG/71C7j1pU6pK503suYOmn4xYrQIzW+opD+7FAFNuGSdZC/3Qfy334QbeMu7MEb8gOxg==", + "dependencies": { + "flatten": "^1.0.2", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + }, + "engines": { + "node": ">=6.14.4" + } + }, + "node_modules/postcss-color-gray": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/postcss-color-gray/-/postcss-color-gray-5.0.0.tgz", + "integrity": "sha512-q6BuRnAGKM/ZRpfDascZlIZPjvwsRye7UDNalqVz3s7GDxMtqPY6+Q871liNxsonUw8oC61OG+PSaysYpl1bnw==", + "dependencies": { + "@csstools/convert-colors": "^1.4.0", + "postcss": "^7.0.5", + "postcss-values-parser": "^2.0.0" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/postcss-color-gray/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "node_modules/postcss-color-gray/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/postcss-color-gray/node_modules/postcss-values-parser": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/postcss-values-parser/-/postcss-values-parser-2.0.1.tgz", + "integrity": "sha512-2tLuBsA6P4rYTNKCXYG/71C7j1pU6pK503suYOmn4xYrQIzW+opD+7FAFNuGSdZC/3Qfy334QbeMu7MEb8gOxg==", + "dependencies": { + "flatten": "^1.0.2", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + }, + "engines": { + "node": ">=6.14.4" + } + }, + "node_modules/postcss-color-hex-alpha": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/postcss-color-hex-alpha/-/postcss-color-hex-alpha-5.0.3.tgz", + "integrity": "sha512-PF4GDel8q3kkreVXKLAGNpHKilXsZ6xuu+mOQMHWHLPNyjiUBOr75sp5ZKJfmv1MCus5/DWUGcK9hm6qHEnXYw==", + "dependencies": { + "postcss": "^7.0.14", + "postcss-values-parser": "^2.0.1" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/postcss-color-hex-alpha/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "node_modules/postcss-color-hex-alpha/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/postcss-color-hex-alpha/node_modules/postcss-values-parser": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/postcss-values-parser/-/postcss-values-parser-2.0.1.tgz", + "integrity": "sha512-2tLuBsA6P4rYTNKCXYG/71C7j1pU6pK503suYOmn4xYrQIzW+opD+7FAFNuGSdZC/3Qfy334QbeMu7MEb8gOxg==", + "dependencies": { + "flatten": "^1.0.2", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + }, + "engines": { + "node": ">=6.14.4" + } + }, + "node_modules/postcss-color-mod-function": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/postcss-color-mod-function/-/postcss-color-mod-function-3.0.3.tgz", + "integrity": "sha512-YP4VG+xufxaVtzV6ZmhEtc+/aTXH3d0JLpnYfxqTvwZPbJhWqp8bSY3nfNzNRFLgB4XSaBA82OE4VjOOKpCdVQ==", + "dependencies": { + "@csstools/convert-colors": "^1.4.0", + "postcss": "^7.0.2", + "postcss-values-parser": "^2.0.0" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/postcss-color-mod-function/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "node_modules/postcss-color-mod-function/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/postcss-color-mod-function/node_modules/postcss-values-parser": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/postcss-values-parser/-/postcss-values-parser-2.0.1.tgz", + "integrity": "sha512-2tLuBsA6P4rYTNKCXYG/71C7j1pU6pK503suYOmn4xYrQIzW+opD+7FAFNuGSdZC/3Qfy334QbeMu7MEb8gOxg==", + "dependencies": { + "flatten": "^1.0.2", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + }, + "engines": { + "node": ">=6.14.4" + } + }, + "node_modules/postcss-color-rebeccapurple": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-color-rebeccapurple/-/postcss-color-rebeccapurple-4.0.1.tgz", + "integrity": "sha512-aAe3OhkS6qJXBbqzvZth2Au4V3KieR5sRQ4ptb2b2O8wgvB3SJBsdG+jsn2BZbbwekDG8nTfcCNKcSfe/lEy8g==", + "dependencies": { + "postcss": "^7.0.2", + "postcss-values-parser": "^2.0.0" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/postcss-color-rebeccapurple/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "node_modules/postcss-color-rebeccapurple/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/postcss-color-rebeccapurple/node_modules/postcss-values-parser": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/postcss-values-parser/-/postcss-values-parser-2.0.1.tgz", + "integrity": "sha512-2tLuBsA6P4rYTNKCXYG/71C7j1pU6pK503suYOmn4xYrQIzW+opD+7FAFNuGSdZC/3Qfy334QbeMu7MEb8gOxg==", + "dependencies": { + "flatten": "^1.0.2", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + }, + "engines": { + "node": ">=6.14.4" + } + }, + "node_modules/postcss-colormin": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/postcss-colormin/-/postcss-colormin-4.0.3.tgz", + "integrity": "sha512-WyQFAdDZpExQh32j0U0feWisZ0dmOtPl44qYmJKkq9xFWY3p+4qnRzCHeNrkeRhwPHz9bQ3mo0/yVkaply0MNw==", + "dependencies": { + "browserslist": "^4.0.0", + "color": "^3.0.0", + "has": "^1.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/postcss-colormin/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "node_modules/postcss-colormin/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/postcss-colormin/node_modules/postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==" + }, + "node_modules/postcss-convert-values": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-convert-values/-/postcss-convert-values-4.0.1.tgz", + "integrity": "sha512-Kisdo1y77KUC0Jmn0OXU/COOJbzM8cImvw1ZFsBgBgMgb1iL23Zs/LXRe3r+EZqM3vGYKdQ2YJVQ5VkJI+zEJQ==", + "dependencies": { + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/postcss-convert-values/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "node_modules/postcss-convert-values/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/postcss-convert-values/node_modules/postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==" + }, + "node_modules/postcss-custom-media": { + "version": "7.0.8", + "resolved": "https://registry.npmjs.org/postcss-custom-media/-/postcss-custom-media-7.0.8.tgz", + "integrity": "sha512-c9s5iX0Ge15o00HKbuRuTqNndsJUbaXdiNsksnVH8H4gdc+zbLzr/UasOwNG6CTDpLFekVY4672eWdiiWu2GUg==", + "dependencies": { + "postcss": "^7.0.14" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/postcss-custom-media/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "node_modules/postcss-custom-media/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/postcss-custom-properties": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/postcss-custom-properties/-/postcss-custom-properties-11.0.0.tgz", + "integrity": "sha512-Fhnx/QLt+CTt23A/KKVx1anZD9nmVpOxKCKv5owWacMoOsBXFhMAD6SZYbmPMH4nHdIeMUnWOvLZnlY4niS0sA==", + "dev": true, + "dependencies": { + "postcss-values-parser": "^4.0.0" + }, + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-custom-selectors": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/postcss-custom-selectors/-/postcss-custom-selectors-5.1.2.tgz", + "integrity": "sha512-DSGDhqinCqXqlS4R7KGxL1OSycd1lydugJ1ky4iRXPHdBRiozyMHrdu0H3o7qNOCiZwySZTUI5MV0T8QhCLu+w==", + "dependencies": { + "postcss": "^7.0.2", + "postcss-selector-parser": "^5.0.0-rc.3" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/postcss-custom-selectors/node_modules/cssesc": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-2.0.0.tgz", + "integrity": "sha512-MsCAG1z9lPdoO/IUMLSBWBSVxVtJ1395VGIQ+Fc2gNdkQ1hNDnQdw3YhA71WJCBW1vdwA0cAnk/DnW6bqoEUYg==", + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-custom-selectors/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "node_modules/postcss-custom-selectors/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/postcss-custom-selectors/node_modules/postcss-selector-parser": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-5.0.0.tgz", + "integrity": "sha512-w+zLE5Jhg6Liz8+rQOWEAwtwkyqpfnmsinXjXg6cY7YIONZZtgvE0v2O0uhQBs0peNomOJwWRKt6JBfTdTd3OQ==", + "dependencies": { + "cssesc": "^2.0.0", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-dir-pseudo-class": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/postcss-dir-pseudo-class/-/postcss-dir-pseudo-class-5.0.0.tgz", + "integrity": "sha512-3pm4oq8HYWMZePJY+5ANriPs3P07q+LW6FAdTlkFH2XqDdP4HeeJYMOzn0HYLhRSjBO3fhiqSwwU9xEULSrPgw==", + "dependencies": { + "postcss": "^7.0.2", + "postcss-selector-parser": "^5.0.0-rc.3" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/postcss-dir-pseudo-class/node_modules/cssesc": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-2.0.0.tgz", + "integrity": "sha512-MsCAG1z9lPdoO/IUMLSBWBSVxVtJ1395VGIQ+Fc2gNdkQ1hNDnQdw3YhA71WJCBW1vdwA0cAnk/DnW6bqoEUYg==", + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-dir-pseudo-class/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "node_modules/postcss-dir-pseudo-class/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/postcss-dir-pseudo-class/node_modules/postcss-selector-parser": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-5.0.0.tgz", + "integrity": "sha512-w+zLE5Jhg6Liz8+rQOWEAwtwkyqpfnmsinXjXg6cY7YIONZZtgvE0v2O0uhQBs0peNomOJwWRKt6JBfTdTd3OQ==", + "dependencies": { + "cssesc": "^2.0.0", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-discard-comments": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-4.0.2.tgz", + "integrity": "sha512-RJutN259iuRf3IW7GZyLM5Sw4GLTOH8FmsXBnv8Ab/Tc2k4SR4qbV4DNbyyY4+Sjo362SyDmW2DQ7lBSChrpkg==", + "dependencies": { + "postcss": "^7.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/postcss-discard-comments/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "node_modules/postcss-discard-comments/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/postcss-discard-duplicates": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-4.0.2.tgz", + "integrity": "sha512-ZNQfR1gPNAiXZhgENFfEglF93pciw0WxMkJeVmw8eF+JZBbMD7jp6C67GqJAXVZP2BWbOztKfbsdmMp/k8c6oQ==", + "dependencies": { + "postcss": "^7.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/postcss-discard-duplicates/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "node_modules/postcss-discard-duplicates/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/postcss-discard-empty": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-4.0.1.tgz", + "integrity": "sha512-B9miTzbznhDjTfjvipfHoqbWKwd0Mj+/fL5s1QOz06wufguil+Xheo4XpOnc4NqKYBCNqqEzgPv2aPBIJLox0w==", + "dependencies": { + "postcss": "^7.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/postcss-discard-empty/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "node_modules/postcss-discard-empty/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/postcss-discard-overridden": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-4.0.1.tgz", + "integrity": "sha512-IYY2bEDD7g1XM1IDEsUT4//iEYCxAmP5oDSFMVU/JVvT7gh+l4fmjciLqGgwjdWpQIdb0Che2VX00QObS5+cTg==", + "dependencies": { + "postcss": "^7.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/postcss-discard-overridden/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "node_modules/postcss-discard-overridden/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/postcss-double-position-gradients": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/postcss-double-position-gradients/-/postcss-double-position-gradients-1.0.0.tgz", + "integrity": "sha512-G+nV8EnQq25fOI8CH/B6krEohGWnF5+3A6H/+JEpOncu5dCnkS1QQ6+ct3Jkaepw1NGVqqOZH6lqrm244mCftA==", + "dependencies": { + "postcss": "^7.0.5", + "postcss-values-parser": "^2.0.0" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/postcss-double-position-gradients/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "node_modules/postcss-double-position-gradients/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/postcss-double-position-gradients/node_modules/postcss-values-parser": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/postcss-values-parser/-/postcss-values-parser-2.0.1.tgz", + "integrity": "sha512-2tLuBsA6P4rYTNKCXYG/71C7j1pU6pK503suYOmn4xYrQIzW+opD+7FAFNuGSdZC/3Qfy334QbeMu7MEb8gOxg==", + "dependencies": { + "flatten": "^1.0.2", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + }, + "engines": { + "node": ">=6.14.4" + } + }, + "node_modules/postcss-env-function": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/postcss-env-function/-/postcss-env-function-2.0.2.tgz", + "integrity": "sha512-rwac4BuZlITeUbiBq60h/xbLzXY43qOsIErngWa4l7Mt+RaSkT7QBjXVGTcBHupykkblHMDrBFh30zchYPaOUw==", + "dependencies": { + "postcss": "^7.0.2", + "postcss-values-parser": "^2.0.0" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/postcss-env-function/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "node_modules/postcss-env-function/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/postcss-env-function/node_modules/postcss-values-parser": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/postcss-values-parser/-/postcss-values-parser-2.0.1.tgz", + "integrity": "sha512-2tLuBsA6P4rYTNKCXYG/71C7j1pU6pK503suYOmn4xYrQIzW+opD+7FAFNuGSdZC/3Qfy334QbeMu7MEb8gOxg==", + "dependencies": { + "flatten": "^1.0.2", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + }, + "engines": { + "node": ">=6.14.4" + } + }, + "node_modules/postcss-focus-visible": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-focus-visible/-/postcss-focus-visible-4.0.0.tgz", + "integrity": "sha512-Z5CkWBw0+idJHSV6+Bgf2peDOFf/x4o+vX/pwcNYrWpXFrSfTkQ3JQ1ojrq9yS+upnAlNRHeg8uEwFTgorjI8g==", + "dependencies": { + "postcss": "^7.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/postcss-focus-visible/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "node_modules/postcss-focus-visible/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/postcss-focus-within": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-focus-within/-/postcss-focus-within-3.0.0.tgz", + "integrity": "sha512-W0APui8jQeBKbCGZudW37EeMCjDeVxKgiYfIIEo8Bdh5SpB9sxds/Iq8SEuzS0Q4YFOlG7EPFulbbxujpkrV2w==", + "dependencies": { + "postcss": "^7.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/postcss-focus-within/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "node_modules/postcss-focus-within/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/postcss-font-variant": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-font-variant/-/postcss-font-variant-4.0.1.tgz", + "integrity": "sha512-I3ADQSTNtLTTd8uxZhtSOrTCQ9G4qUVKPjHiDk0bV75QSxXjVWiJVJ2VLdspGUi9fbW9BcjKJoRvxAH1pckqmA==", + "dependencies": { + "postcss": "^7.0.2" + } + }, + "node_modules/postcss-font-variant/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "node_modules/postcss-font-variant/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/postcss-gap-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postcss-gap-properties/-/postcss-gap-properties-2.0.0.tgz", + "integrity": "sha512-QZSqDaMgXCHuHTEzMsS2KfVDOq7ZFiknSpkrPJY6jmxbugUPTuSzs/vuE5I3zv0WAS+3vhrlqhijiprnuQfzmg==", + "dependencies": { + "postcss": "^7.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/postcss-gap-properties/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "node_modules/postcss-gap-properties/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/postcss-image-set-function": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/postcss-image-set-function/-/postcss-image-set-function-3.0.1.tgz", + "integrity": "sha512-oPTcFFip5LZy8Y/whto91L9xdRHCWEMs3e1MdJxhgt4jy2WYXfhkng59fH5qLXSCPN8k4n94p1Czrfe5IOkKUw==", + "dependencies": { + "postcss": "^7.0.2", + "postcss-values-parser": "^2.0.0" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/postcss-image-set-function/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "node_modules/postcss-image-set-function/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/postcss-image-set-function/node_modules/postcss-values-parser": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/postcss-values-parser/-/postcss-values-parser-2.0.1.tgz", + "integrity": "sha512-2tLuBsA6P4rYTNKCXYG/71C7j1pU6pK503suYOmn4xYrQIzW+opD+7FAFNuGSdZC/3Qfy334QbeMu7MEb8gOxg==", + "dependencies": { + "flatten": "^1.0.2", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + }, + "engines": { + "node": ">=6.14.4" + } + }, + "node_modules/postcss-import": { + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-13.0.0.tgz", + "integrity": "sha512-LPUbm3ytpYopwQQjqgUH4S3EM/Gb9QsaSPP/5vnoi+oKVy3/mIk2sc0Paqw7RL57GpScm9MdIMUypw2znWiBpg==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.0.0", + "read-cache": "^1.0.0", + "resolve": "^1.1.7" + }, + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "postcss": "^8.0.0" + } + }, + "node_modules/postcss-import-resolver": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postcss-import-resolver/-/postcss-import-resolver-2.0.0.tgz", + "integrity": "sha512-y001XYgGvVwgxyxw9J1a5kqM/vtmIQGzx34g0A0Oy44MFcy/ZboZw1hu/iN3VYFjSTRzbvd7zZJJz0Kh0AGkTw==", + "dependencies": { + "enhanced-resolve": "^4.1.1" + } + }, + "node_modules/postcss-initial": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/postcss-initial/-/postcss-initial-3.0.4.tgz", + "integrity": "sha512-3RLn6DIpMsK1l5UUy9jxQvoDeUN4gP939tDcKUHD/kM8SGSKbFAnvkpFpj3Bhtz3HGk1jWY5ZNWX6mPta5M9fg==", + "dependencies": { + "postcss": "^7.0.2" + } + }, + "node_modules/postcss-initial/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "node_modules/postcss-initial/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/postcss-js": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.0.tgz", + "integrity": "sha512-77QESFBwgX4irogGVPgQ5s07vLvFqWr228qZY+w6lW599cRlK/HmnlivnnVUxkjHnCu4J16PDMHcH+e+2HbvTQ==", + "dev": true, + "dependencies": { + "camelcase-css": "^2.0.1" + }, + "engines": { + "node": "^12 || ^14 || >= 16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + "peerDependencies": { + "postcss": "^8.3.3" + } + }, + "node_modules/postcss-lab-function": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/postcss-lab-function/-/postcss-lab-function-2.0.1.tgz", + "integrity": "sha512-whLy1IeZKY+3fYdqQFuDBf8Auw+qFuVnChWjmxm/UhHWqNHZx+B99EwxTvGYmUBqe3Fjxs4L1BoZTJmPu6usVg==", + "dependencies": { + "@csstools/convert-colors": "^1.4.0", + "postcss": "^7.0.2", + "postcss-values-parser": "^2.0.0" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/postcss-lab-function/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "node_modules/postcss-lab-function/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/postcss-lab-function/node_modules/postcss-values-parser": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/postcss-values-parser/-/postcss-values-parser-2.0.1.tgz", + "integrity": "sha512-2tLuBsA6P4rYTNKCXYG/71C7j1pU6pK503suYOmn4xYrQIzW+opD+7FAFNuGSdZC/3Qfy334QbeMu7MEb8gOxg==", + "dependencies": { + "flatten": "^1.0.2", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + }, + "engines": { + "node": ">=6.14.4" + } + }, + "node_modules/postcss-load-config": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-3.1.4.tgz", + "integrity": "sha512-6DiM4E7v4coTE4uzA8U//WhtPwyhiim3eyjEMFCnUpzbrkK9wJHgKDT2mR+HbtSrd/NubVaYTOpSpjUl8NQeRg==", + "dev": true, + "dependencies": { + "lilconfig": "^2.0.5", + "yaml": "^1.10.2" + }, + "engines": { + "node": ">= 10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + "peerDependencies": { + "postcss": ">=8.0.9", + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "postcss": { + "optional": true + }, + "ts-node": { + "optional": true + } + } + }, + "node_modules/postcss-loader": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-4.3.0.tgz", + "integrity": "sha512-M/dSoIiNDOo8Rk0mUqoj4kpGq91gcxCfb9PoyZVdZ76/AuhxylHDYZblNE8o+EQ9AMSASeMFEKxZf5aU6wlx1Q==", + "dev": true, + "dependencies": { + "cosmiconfig": "^7.0.0", + "klona": "^2.0.4", + "loader-utils": "^2.0.0", + "schema-utils": "^3.0.0", + "semver": "^7.3.4" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "postcss": "^7.0.0 || ^8.0.1", + "webpack": "^4.0.0 || ^5.0.0" + } + }, + "node_modules/postcss-loader/node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/postcss-loader/node_modules/cosmiconfig": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.0.1.tgz", + "integrity": "sha512-a1YWNUV2HwGimB7dU2s1wUMurNKjpx60HxBB6xUM8Re+2s1g1IIfJvFR0/iCF+XHdE0GMTKTuLR32UQff4TEyQ==", + "dev": true, + "dependencies": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.2.1", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.10.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/postcss-loader/node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/postcss-loader/node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/postcss-loader/node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/postcss-loader/node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-logical": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-logical/-/postcss-logical-3.0.0.tgz", + "integrity": "sha512-1SUKdJc2vuMOmeItqGuNaC+N8MzBWFWEkAnRnLpFYj1tGGa7NqyVBujfRtgNa2gXR+6RkGUiB2O5Vmh7E2RmiA==", + "dependencies": { + "postcss": "^7.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/postcss-logical/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "node_modules/postcss-logical/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/postcss-media-minmax": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-media-minmax/-/postcss-media-minmax-4.0.0.tgz", + "integrity": "sha512-fo9moya6qyxsjbFAYl97qKO9gyre3qvbMnkOZeZwlsW6XYFsvs2DMGDlchVLfAd8LHPZDxivu/+qW2SMQeTHBw==", + "dependencies": { + "postcss": "^7.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/postcss-media-minmax/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "node_modules/postcss-media-minmax/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/postcss-merge-longhand": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-4.0.11.tgz", + "integrity": "sha512-alx/zmoeXvJjp7L4mxEMjh8lxVlDFX1gqWHzaaQewwMZiVhLo42TEClKaeHbRf6J7j82ZOdTJ808RtN0ZOZwvw==", + "dependencies": { + "css-color-names": "0.0.4", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0", + "stylehacks": "^4.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/postcss-merge-longhand/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "node_modules/postcss-merge-longhand/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/postcss-merge-longhand/node_modules/postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==" + }, + "node_modules/postcss-merge-rules": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/postcss-merge-rules/-/postcss-merge-rules-4.0.3.tgz", + "integrity": "sha512-U7e3r1SbvYzO0Jr3UT/zKBVgYYyhAz0aitvGIYOYK5CPmkNih+WDSsS5tvPrJ8YMQYlEMvsZIiqmn7HdFUaeEQ==", + "dependencies": { + "browserslist": "^4.0.0", + "caniuse-api": "^3.0.0", + "cssnano-util-same-parent": "^4.0.0", + "postcss": "^7.0.0", + "postcss-selector-parser": "^3.0.0", + "vendors": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/postcss-merge-rules/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "node_modules/postcss-merge-rules/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/postcss-merge-rules/node_modules/postcss-selector-parser": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-3.1.2.tgz", + "integrity": "sha512-h7fJ/5uWuRVyOtkO45pnt1Ih40CEleeyCHzipqAZO2e5H20g25Y48uYnFUiShvY4rZWNJ/Bib/KVPmanaCtOhA==", + "dependencies": { + "dot-prop": "^5.2.0", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/postcss-minify-font-values": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-minify-font-values/-/postcss-minify-font-values-4.0.2.tgz", + "integrity": "sha512-j85oO6OnRU9zPf04+PZv1LYIYOprWm6IA6zkXkrJXyRveDEuQggG6tvoy8ir8ZwjLxLuGfNkCZEQG7zan+Hbtg==", + "dependencies": { + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/postcss-minify-font-values/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "node_modules/postcss-minify-font-values/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/postcss-minify-font-values/node_modules/postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==" + }, + "node_modules/postcss-minify-gradients": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-4.0.2.tgz", + "integrity": "sha512-qKPfwlONdcf/AndP1U8SJ/uzIJtowHlMaSioKzebAXSG4iJthlWC9iSWznQcX4f66gIWX44RSA841HTHj3wK+Q==", + "dependencies": { + "cssnano-util-get-arguments": "^4.0.0", + "is-color-stop": "^1.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/postcss-minify-gradients/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "node_modules/postcss-minify-gradients/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/postcss-minify-gradients/node_modules/postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==" + }, + "node_modules/postcss-minify-params": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-minify-params/-/postcss-minify-params-4.0.2.tgz", + "integrity": "sha512-G7eWyzEx0xL4/wiBBJxJOz48zAKV2WG3iZOqVhPet/9geefm/Px5uo1fzlHu+DOjT+m0Mmiz3jkQzVHe6wxAWg==", + "dependencies": { + "alphanum-sort": "^1.0.0", + "browserslist": "^4.0.0", + "cssnano-util-get-arguments": "^4.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0", + "uniqs": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/postcss-minify-params/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "node_modules/postcss-minify-params/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/postcss-minify-params/node_modules/postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==" + }, + "node_modules/postcss-minify-selectors": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-minify-selectors/-/postcss-minify-selectors-4.0.2.tgz", + "integrity": "sha512-D5S1iViljXBj9kflQo4YutWnJmwm8VvIsU1GeXJGiG9j8CIg9zs4voPMdQDUmIxetUOh60VilsNzCiAFTOqu3g==", + "dependencies": { + "alphanum-sort": "^1.0.0", + "has": "^1.0.0", + "postcss": "^7.0.0", + "postcss-selector-parser": "^3.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/postcss-minify-selectors/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "node_modules/postcss-minify-selectors/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/postcss-minify-selectors/node_modules/postcss-selector-parser": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-3.1.2.tgz", + "integrity": "sha512-h7fJ/5uWuRVyOtkO45pnt1Ih40CEleeyCHzipqAZO2e5H20g25Y48uYnFUiShvY4rZWNJ/Bib/KVPmanaCtOhA==", + "dependencies": { + "dot-prop": "^5.2.0", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/postcss-modules-extract-imports": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz", + "integrity": "sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==", + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-modules-local-by-default": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.0.tgz", + "integrity": "sha512-sT7ihtmGSF9yhm6ggikHdV0hlziDTX7oFoXtuVWeDd3hHObNkcHRo9V3yg7vCAY7cONyxJC/XXCmmiHHcvX7bQ==", + "dependencies": { + "icss-utils": "^5.0.0", + "postcss-selector-parser": "^6.0.2", + "postcss-value-parser": "^4.1.0" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-modules-scope": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.0.0.tgz", + "integrity": "sha512-hncihwFA2yPath8oZ15PZqvWGkWf+XUfQgUGamS4LqoP1anQLOsOJw0vr7J7IwLpoY9fatA2qiGUGmuZL0Iqlg==", + "dependencies": { + "postcss-selector-parser": "^6.0.4" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-modules-values": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz", + "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==", + "dependencies": { + "icss-utils": "^5.0.0" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-nested": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-5.0.6.tgz", + "integrity": "sha512-rKqm2Fk0KbA8Vt3AdGN0FB9OBOMDVajMG6ZCf/GoHgdxUJ4sBFp0A/uMIRm+MJUdo33YXEtjqIz8u7DAp8B7DA==", + "dev": true, + "dependencies": { + "postcss-selector-parser": "^6.0.6" + }, + "engines": { + "node": ">=12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + "peerDependencies": { + "postcss": "^8.2.14" + } + }, + "node_modules/postcss-nesting": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/postcss-nesting/-/postcss-nesting-8.0.1.tgz", + "integrity": "sha512-cHPNhW5VvRQjszFDxmy16mis9qFQqQLBNw6KVmueLqqE3M182ZAk9+QoxGqbGVryzLVhannw2B5Yhosqq522fA==", + "dev": true, + "engines": { + "node": "12 - 16" + }, + "peerDependencies": { + "postcss": "^8" + } + }, + "node_modules/postcss-normalize-charset": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-4.0.1.tgz", + "integrity": "sha512-gMXCrrlWh6G27U0hF3vNvR3w8I1s2wOBILvA87iNXaPvSNo5uZAMYsZG7XjCUf1eVxuPfyL4TJ7++SGZLc9A3g==", + "dependencies": { + "postcss": "^7.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/postcss-normalize-charset/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "node_modules/postcss-normalize-charset/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/postcss-normalize-display-values": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-display-values/-/postcss-normalize-display-values-4.0.2.tgz", + "integrity": "sha512-3F2jcsaMW7+VtRMAqf/3m4cPFhPD3EFRgNs18u+k3lTJJlVe7d0YPO+bnwqo2xg8YiRpDXJI2u8A0wqJxMsQuQ==", + "dependencies": { + "cssnano-util-get-match": "^4.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/postcss-normalize-display-values/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "node_modules/postcss-normalize-display-values/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/postcss-normalize-display-values/node_modules/postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==" + }, + "node_modules/postcss-normalize-positions": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-positions/-/postcss-normalize-positions-4.0.2.tgz", + "integrity": "sha512-Dlf3/9AxpxE+NF1fJxYDeggi5WwV35MXGFnnoccP/9qDtFrTArZ0D0R+iKcg5WsUd8nUYMIl8yXDCtcrT8JrdA==", + "dependencies": { + "cssnano-util-get-arguments": "^4.0.0", + "has": "^1.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/postcss-normalize-positions/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "node_modules/postcss-normalize-positions/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/postcss-normalize-positions/node_modules/postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==" + }, + "node_modules/postcss-normalize-repeat-style": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-4.0.2.tgz", + "integrity": "sha512-qvigdYYMpSuoFs3Is/f5nHdRLJN/ITA7huIoCyqqENJe9PvPmLhNLMu7QTjPdtnVf6OcYYO5SHonx4+fbJE1+Q==", + "dependencies": { + "cssnano-util-get-arguments": "^4.0.0", + "cssnano-util-get-match": "^4.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/postcss-normalize-repeat-style/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "node_modules/postcss-normalize-repeat-style/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/postcss-normalize-repeat-style/node_modules/postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==" + }, + "node_modules/postcss-normalize-string": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-string/-/postcss-normalize-string-4.0.2.tgz", + "integrity": "sha512-RrERod97Dnwqq49WNz8qo66ps0swYZDSb6rM57kN2J+aoyEAJfZ6bMx0sx/F9TIEX0xthPGCmeyiam/jXif0eA==", + "dependencies": { + "has": "^1.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/postcss-normalize-string/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "node_modules/postcss-normalize-string/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/postcss-normalize-string/node_modules/postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==" + }, + "node_modules/postcss-normalize-timing-functions": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-4.0.2.tgz", + "integrity": "sha512-acwJY95edP762e++00Ehq9L4sZCEcOPyaHwoaFOhIwWCDfik6YvqsYNxckee65JHLKzuNSSmAdxwD2Cud1Z54A==", + "dependencies": { + "cssnano-util-get-match": "^4.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/postcss-normalize-timing-functions/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "node_modules/postcss-normalize-timing-functions/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/postcss-normalize-timing-functions/node_modules/postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==" + }, + "node_modules/postcss-normalize-unicode": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-unicode/-/postcss-normalize-unicode-4.0.1.tgz", + "integrity": "sha512-od18Uq2wCYn+vZ/qCOeutvHjB5jm57ToxRaMeNuf0nWVHaP9Hua56QyMF6fs/4FSUnVIw0CBPsU0K4LnBPwYwg==", + "dependencies": { + "browserslist": "^4.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/postcss-normalize-unicode/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "node_modules/postcss-normalize-unicode/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/postcss-normalize-unicode/node_modules/postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==" + }, + "node_modules/postcss-normalize-url": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-url/-/postcss-normalize-url-4.0.1.tgz", + "integrity": "sha512-p5oVaF4+IHwu7VpMan/SSpmpYxcJMtkGppYf0VbdH5B6hN8YNmVyJLuY9FmLQTzY3fag5ESUUHDqM+heid0UVA==", + "dependencies": { + "is-absolute-url": "^2.0.0", + "normalize-url": "^3.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/postcss-normalize-url/node_modules/normalize-url": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-3.3.0.tgz", + "integrity": "sha512-U+JJi7duF1o+u2pynbp2zXDW2/PADgC30f0GsHZtRh+HOcXHnw137TrNlyxxRvWW5fjKd3bcLHPxofWuCjaeZg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/postcss-normalize-url/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "node_modules/postcss-normalize-url/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/postcss-normalize-url/node_modules/postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==" + }, + "node_modules/postcss-normalize-whitespace": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-whitespace/-/postcss-normalize-whitespace-4.0.2.tgz", + "integrity": "sha512-tO8QIgrsI3p95r8fyqKV+ufKlSHh9hMJqACqbv2XknufqEDhDvbguXGBBqxw9nsQoXWf0qOqppziKJKHMD4GtA==", + "dependencies": { + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/postcss-normalize-whitespace/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "node_modules/postcss-normalize-whitespace/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/postcss-normalize-whitespace/node_modules/postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==" + }, + "node_modules/postcss-ordered-values": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/postcss-ordered-values/-/postcss-ordered-values-4.1.2.tgz", + "integrity": "sha512-2fCObh5UanxvSxeXrtLtlwVThBvHn6MQcu4ksNT2tsaV2Fg76R2CV98W7wNSlX+5/pFwEyaDwKLLoEV7uRybAw==", + "dependencies": { + "cssnano-util-get-arguments": "^4.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/postcss-ordered-values/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "node_modules/postcss-ordered-values/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/postcss-ordered-values/node_modules/postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==" + }, + "node_modules/postcss-overflow-shorthand": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postcss-overflow-shorthand/-/postcss-overflow-shorthand-2.0.0.tgz", + "integrity": "sha512-aK0fHc9CBNx8jbzMYhshZcEv8LtYnBIRYQD5i7w/K/wS9c2+0NSR6B3OVMu5y0hBHYLcMGjfU+dmWYNKH0I85g==", + "dependencies": { + "postcss": "^7.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/postcss-overflow-shorthand/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "node_modules/postcss-overflow-shorthand/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/postcss-page-break": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postcss-page-break/-/postcss-page-break-2.0.0.tgz", + "integrity": "sha512-tkpTSrLpfLfD9HvgOlJuigLuk39wVTbbd8RKcy8/ugV2bNBUW3xU+AIqyxhDrQr1VUj1RmyJrBn1YWrqUm9zAQ==", + "dependencies": { + "postcss": "^7.0.2" + } + }, + "node_modules/postcss-page-break/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "node_modules/postcss-page-break/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/postcss-place": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-place/-/postcss-place-4.0.1.tgz", + "integrity": "sha512-Zb6byCSLkgRKLODj/5mQugyuj9bvAAw9LqJJjgwz5cYryGeXfFZfSXoP1UfveccFmeq0b/2xxwcTEVScnqGxBg==", + "dependencies": { + "postcss": "^7.0.2", + "postcss-values-parser": "^2.0.0" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/postcss-place/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "node_modules/postcss-place/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/postcss-place/node_modules/postcss-values-parser": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/postcss-values-parser/-/postcss-values-parser-2.0.1.tgz", + "integrity": "sha512-2tLuBsA6P4rYTNKCXYG/71C7j1pU6pK503suYOmn4xYrQIzW+opD+7FAFNuGSdZC/3Qfy334QbeMu7MEb8gOxg==", + "dependencies": { + "flatten": "^1.0.2", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + }, + "engines": { + "node": ">=6.14.4" + } + }, + "node_modules/postcss-preset-env": { + "version": "6.7.1", + "resolved": "https://registry.npmjs.org/postcss-preset-env/-/postcss-preset-env-6.7.1.tgz", + "integrity": "sha512-rlRkgX9t0v2On33n7TK8pnkcYOATGQSv48J2RS8GsXhqtg+xk6AummHP88Y5mJo0TLJelBjePvSjScTNkj3+qw==", + "dependencies": { + "autoprefixer": "^9.6.1", + "browserslist": "^4.6.4", + "caniuse-lite": "^1.0.30000981", + "css-blank-pseudo": "^0.1.4", + "css-has-pseudo": "^0.10.0", + "css-prefers-color-scheme": "^3.1.1", + "cssdb": "^4.4.0", + "postcss": "^7.0.17", + "postcss-attribute-case-insensitive": "^4.0.1", + "postcss-color-functional-notation": "^2.0.1", + "postcss-color-gray": "^5.0.0", + "postcss-color-hex-alpha": "^5.0.3", + "postcss-color-mod-function": "^3.0.3", + "postcss-color-rebeccapurple": "^4.0.1", + "postcss-custom-media": "^7.0.8", + "postcss-custom-properties": "^8.0.11", + "postcss-custom-selectors": "^5.1.2", + "postcss-dir-pseudo-class": "^5.0.0", + "postcss-double-position-gradients": "^1.0.0", + "postcss-env-function": "^2.0.2", + "postcss-focus-visible": "^4.0.0", + "postcss-focus-within": "^3.0.0", + "postcss-font-variant": "^4.0.0", + "postcss-gap-properties": "^2.0.0", + "postcss-image-set-function": "^3.0.1", + "postcss-initial": "^3.0.0", + "postcss-lab-function": "^2.0.1", + "postcss-logical": "^3.0.0", + "postcss-media-minmax": "^4.0.0", + "postcss-nesting": "^7.0.0", + "postcss-overflow-shorthand": "^2.0.0", + "postcss-page-break": "^2.0.0", + "postcss-place": "^4.0.1", + "postcss-pseudo-class-any-link": "^6.0.0", + "postcss-replace-overflow-wrap": "^3.0.0", + "postcss-selector-matches": "^4.0.0", + "postcss-selector-not": "^4.0.0" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/postcss-preset-env/node_modules/autoprefixer": { + "version": "9.8.8", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-9.8.8.tgz", + "integrity": "sha512-eM9d/swFopRt5gdJ7jrpCwgvEMIayITpojhkkSMRsFHYuH5bkSQ4p/9qTEHtmNudUZh22Tehu7I6CxAW0IXTKA==", + "dependencies": { + "browserslist": "^4.12.0", + "caniuse-lite": "^1.0.30001109", + "normalize-range": "^0.1.2", + "num2fraction": "^1.2.2", + "picocolors": "^0.2.1", + "postcss": "^7.0.32", + "postcss-value-parser": "^4.1.0" + }, + "bin": { + "autoprefixer": "bin/autoprefixer" + }, + "funding": { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/autoprefixer" + } + }, + "node_modules/postcss-preset-env/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "node_modules/postcss-preset-env/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/postcss-preset-env/node_modules/postcss-custom-properties": { + "version": "8.0.11", + "resolved": "https://registry.npmjs.org/postcss-custom-properties/-/postcss-custom-properties-8.0.11.tgz", + "integrity": "sha512-nm+o0eLdYqdnJ5abAJeXp4CEU1c1k+eB2yMCvhgzsds/e0umabFrN6HoTy/8Q4K5ilxERdl/JD1LO5ANoYBeMA==", + "dependencies": { + "postcss": "^7.0.17", + "postcss-values-parser": "^2.0.1" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/postcss-preset-env/node_modules/postcss-nesting": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/postcss-nesting/-/postcss-nesting-7.0.1.tgz", + "integrity": "sha512-FrorPb0H3nuVq0Sff7W2rnc3SmIcruVC6YwpcS+k687VxyxO33iE1amna7wHuRVzM8vfiYofXSBHNAZ3QhLvYg==", + "dependencies": { + "postcss": "^7.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/postcss-preset-env/node_modules/postcss-values-parser": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/postcss-values-parser/-/postcss-values-parser-2.0.1.tgz", + "integrity": "sha512-2tLuBsA6P4rYTNKCXYG/71C7j1pU6pK503suYOmn4xYrQIzW+opD+7FAFNuGSdZC/3Qfy334QbeMu7MEb8gOxg==", + "dependencies": { + "flatten": "^1.0.2", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + }, + "engines": { + "node": ">=6.14.4" + } + }, + "node_modules/postcss-pseudo-class-any-link": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/postcss-pseudo-class-any-link/-/postcss-pseudo-class-any-link-6.0.0.tgz", + "integrity": "sha512-lgXW9sYJdLqtmw23otOzrtbDXofUdfYzNm4PIpNE322/swES3VU9XlXHeJS46zT2onFO7V1QFdD4Q9LiZj8mew==", + "dependencies": { + "postcss": "^7.0.2", + "postcss-selector-parser": "^5.0.0-rc.3" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/postcss-pseudo-class-any-link/node_modules/cssesc": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-2.0.0.tgz", + "integrity": "sha512-MsCAG1z9lPdoO/IUMLSBWBSVxVtJ1395VGIQ+Fc2gNdkQ1hNDnQdw3YhA71WJCBW1vdwA0cAnk/DnW6bqoEUYg==", + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-pseudo-class-any-link/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "node_modules/postcss-pseudo-class-any-link/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/postcss-pseudo-class-any-link/node_modules/postcss-selector-parser": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-5.0.0.tgz", + "integrity": "sha512-w+zLE5Jhg6Liz8+rQOWEAwtwkyqpfnmsinXjXg6cY7YIONZZtgvE0v2O0uhQBs0peNomOJwWRKt6JBfTdTd3OQ==", + "dependencies": { + "cssesc": "^2.0.0", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-reduce-initial": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-4.0.3.tgz", + "integrity": "sha512-gKWmR5aUulSjbzOfD9AlJiHCGH6AEVLaM0AV+aSioxUDd16qXP1PCh8d1/BGVvpdWn8k/HiK7n6TjeoXN1F7DA==", + "dependencies": { + "browserslist": "^4.0.0", + "caniuse-api": "^3.0.0", + "has": "^1.0.0", + "postcss": "^7.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/postcss-reduce-initial/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "node_modules/postcss-reduce-initial/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/postcss-reduce-transforms": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-reduce-transforms/-/postcss-reduce-transforms-4.0.2.tgz", + "integrity": "sha512-EEVig1Q2QJ4ELpJXMZR8Vt5DQx8/mo+dGWSR7vWXqcob2gQLyQGsionYcGKATXvQzMPn6DSN1vTN7yFximdIAg==", + "dependencies": { + "cssnano-util-get-match": "^4.0.0", + "has": "^1.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/postcss-reduce-transforms/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "node_modules/postcss-reduce-transforms/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/postcss-reduce-transforms/node_modules/postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==" + }, + "node_modules/postcss-replace-overflow-wrap": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-replace-overflow-wrap/-/postcss-replace-overflow-wrap-3.0.0.tgz", + "integrity": "sha512-2T5hcEHArDT6X9+9dVSPQdo7QHzG4XKclFT8rU5TzJPDN7RIRTbO9c4drUISOVemLj03aezStHCR2AIcr8XLpw==", + "dependencies": { + "postcss": "^7.0.2" + } + }, + "node_modules/postcss-replace-overflow-wrap/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "node_modules/postcss-replace-overflow-wrap/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/postcss-selector-matches": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-selector-matches/-/postcss-selector-matches-4.0.0.tgz", + "integrity": "sha512-LgsHwQR/EsRYSqlwdGzeaPKVT0Ml7LAT6E75T8W8xLJY62CE4S/l03BWIt3jT8Taq22kXP08s2SfTSzaraoPww==", + "dependencies": { + "balanced-match": "^1.0.0", + "postcss": "^7.0.2" + } + }, + "node_modules/postcss-selector-matches/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "node_modules/postcss-selector-matches/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/postcss-selector-not": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-selector-not/-/postcss-selector-not-4.0.1.tgz", + "integrity": "sha512-YolvBgInEK5/79C+bdFMyzqTg6pkYqDbzZIST/PDMqa/o3qtXenD05apBG2jLgT0/BQ77d4U2UK12jWpilqMAQ==", + "dependencies": { + "balanced-match": "^1.0.0", + "postcss": "^7.0.2" + } + }, + "node_modules/postcss-selector-not/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "node_modules/postcss-selector-not/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/postcss-selector-parser": { + "version": "6.0.10", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.10.tgz", + "integrity": "sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-svgo": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-4.0.3.tgz", + "integrity": "sha512-NoRbrcMWTtUghzuKSoIm6XV+sJdvZ7GZSc3wdBN0W19FTtp2ko8NqLsgoh/m9CzNhU3KLPvQmjIwtaNFkaFTvw==", + "dependencies": { + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0", + "svgo": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/postcss-svgo/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "node_modules/postcss-svgo/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/postcss-svgo/node_modules/postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==" + }, + "node_modules/postcss-unique-selectors": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-4.0.1.tgz", + "integrity": "sha512-+JanVaryLo9QwZjKrmJgkI4Fn8SBgRO6WXQBJi7KiAVPlmxikB5Jzc4EvXMT2H0/m0RjrVVm9rGNhZddm/8Spg==", + "dependencies": { + "alphanum-sort": "^1.0.0", + "postcss": "^7.0.0", + "uniqs": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/postcss-unique-selectors/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "node_modules/postcss-unique-selectors/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/postcss-url": { + "version": "10.1.3", + "resolved": "https://registry.npmjs.org/postcss-url/-/postcss-url-10.1.3.tgz", + "integrity": "sha512-FUzyxfI5l2tKmXdYc6VTu3TWZsInayEKPbiyW+P6vmmIrrb4I6CGX0BFoewgYHLK+oIL5FECEK02REYRpBvUCw==", + "dev": true, + "dependencies": { + "make-dir": "~3.1.0", + "mime": "~2.5.2", + "minimatch": "~3.0.4", + "xxhashjs": "~0.2.2" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "postcss": "^8.0.0" + } + }, + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" + }, + "node_modules/postcss-values-parser": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-values-parser/-/postcss-values-parser-4.0.0.tgz", + "integrity": "sha512-R9x2D87FcbhwXUmoCXJR85M1BLII5suXRuXibGYyBJ7lVDEpRIdKZh4+8q5S+/+A4m0IoG1U5tFw39asyhX/Hw==", + "dev": true, + "dependencies": { + "color-name": "^1.1.4", + "is-url-superb": "^4.0.0", + "postcss": "^7.0.5" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/postcss-values-parser/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "node_modules/postcss-values-parser/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/prepend-http": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz", + "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/prettier": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.6.2.tgz", + "integrity": "sha512-PkUpF+qoXTqhOeWL9fu7As8LXsIUZ1WYaJiY/a7McAQzxjk82OF0tibkFXVCDImZtWxbvojFjerkiLb0/q8mew==", + "optional": true, + "bin": { + "prettier": "bin-prettier.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/pretty-bytes": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.6.0.tgz", + "integrity": "sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==", + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pretty-error": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-2.1.2.tgz", + "integrity": "sha512-EY5oDzmsX5wvuynAByrmY0P0hcp+QpnAKbJng2A2MPjVKXCxrDSUkzghVJ4ZGPIv+JC4gX8fPUWscC0RtjsWGw==", + "dependencies": { + "lodash": "^4.17.20", + "renderkid": "^2.0.4" + } + }, + "node_modules/pretty-hrtime": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", + "integrity": "sha512-66hKPCr+72mlfiSjlEB1+45IjXSqvVAIy6mocupoww4tBFE9R9IhwwUGoI4G++Tc9Aq+2rxOt0RFU6gPcrte0A==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/pretty-time": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/pretty-time/-/pretty-time-1.1.0.tgz", + "integrity": "sha512-28iF6xPQrP8Oa6uxE6a1biz+lWeTOAPKggvjB8HAs6nVMKZwf5bG++632Dx614hIWgUPkgivRfG+a8uAXGTIbA==", + "engines": { + "node": ">=4" + } + }, + "node_modules/process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=", + "engines": { + "node": ">= 0.6.0" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "node_modules/promise-inflight": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", + "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=" + }, + "node_modules/proper-lockfile": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/proper-lockfile/-/proper-lockfile-4.1.2.tgz", + "integrity": "sha512-TjNPblN4BwAWMXU8s9AEz4JmQxnD1NNL7bNOY/AKUzyamc379FWASUhc/K1pL2noVb+XmZKLL68cjzLsiOAMaA==", + "dependencies": { + "graceful-fs": "^4.2.4", + "retry": "^0.12.0", + "signal-exit": "^3.0.2" + } + }, + "node_modules/protocols": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/protocols/-/protocols-1.4.8.tgz", + "integrity": "sha512-IgjKyaUSjsROSO8/D49Ab7hP8mJgTYcqApOqdPhLoPxAplXmkp+zRvsrSQjFn5by0rhm4VH0GAUELIPpx7B1yg==" + }, + "node_modules/prr": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", + "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=" + }, + "node_modules/pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=" + }, + "node_modules/public-encrypt": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", + "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==", + "dependencies": { + "bn.js": "^4.1.0", + "browserify-rsa": "^4.0.0", + "create-hash": "^1.1.0", + "parse-asn1": "^5.0.0", + "randombytes": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "node_modules/public-encrypt/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + }, + "node_modules/pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/pumpify": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", + "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", + "dependencies": { + "duplexify": "^3.6.0", + "inherits": "^2.0.3", + "pump": "^2.0.0" + } + }, + "node_modules/pumpify/node_modules/pump": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", + "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "engines": { + "node": ">=6" + } + }, + "node_modules/purgecss": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/purgecss/-/purgecss-4.1.3.tgz", + "integrity": "sha512-99cKy4s+VZoXnPxaoM23e5ABcP851nC2y2GROkkjS8eJaJtlciGavd7iYAw2V84WeBqggZ12l8ef44G99HmTaw==", + "dev": true, + "dependencies": { + "commander": "^8.0.0", + "glob": "^7.1.7", + "postcss": "^8.3.5", + "postcss-selector-parser": "^6.0.6" + }, + "bin": { + "purgecss": "bin/purgecss.js" + } + }, + "node_modules/purgecss/node_modules/commander": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", + "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", + "dev": true, + "engines": { + "node": ">= 12" + } + }, + "node_modules/q": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", + "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=", + "engines": { + "node": ">=0.6.0", + "teleport": ">=0.2.0" + } + }, + "node_modules/qs": { + "version": "6.10.3", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.3.tgz", + "integrity": "sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ==", + "dependencies": { + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/query-string": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/query-string/-/query-string-4.3.4.tgz", + "integrity": "sha1-u7aTucqRXCMlFbIosaArYJBD2+s=", + "dependencies": { + "object-assign": "^4.1.0", + "strict-uri-encode": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/querystring": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", + "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=", + "deprecated": "The querystring API is considered Legacy. new code should use the URLSearchParams API instead.", + "engines": { + "node": ">=0.4.x" + } + }, + "node_modules/querystring-es3": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", + "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=", + "engines": { + "node": ">=0.4.x" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/quick-lru": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", + "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "node_modules/randomfill": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", + "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", + "dependencies": { + "randombytes": "^2.0.5", + "safe-buffer": "^5.1.0" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-loader": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/raw-loader/-/raw-loader-4.0.2.tgz", + "integrity": "sha512-ZnScIV3ag9A4wPX/ZayxL/jZH+euYb6FcUinPcgiQW0+UBtEv0O6Q3lGd3cqJ+GHH+rksEv3Pj99oxJ3u3VIKA==", + "dependencies": { + "loader-utils": "^2.0.0", + "schema-utils": "^3.0.0" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^4.0.0 || ^5.0.0" + } + }, + "node_modules/rc9": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/rc9/-/rc9-1.2.2.tgz", + "integrity": "sha512-zbe8+HR2X28eZepAwohuKkebbEsA67h0DO9I7g12QrHa2CQopR9gztOLPIPXXGTvcxeUjAN4wZ+b29t3m/u05g==", + "dependencies": { + "defu": "^6.0.0", + "destr": "^1.1.1", + "flat": "^5.0.0" + } + }, + "node_modules/rc9/node_modules/defu": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/defu/-/defu-6.0.0.tgz", + "integrity": "sha512-t2MZGLf1V2rV4VBZbWIaXKdX/mUcYW0n2znQZoADBkGGxYL8EWqCuCZBmJPJ/Yy9fofJkyuuSuo5GSwo0XdEgw==" + }, + "node_modules/read-cache": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", + "integrity": "sha1-5mTvMRYRZsl1HNvo28+GtftY93Q=", + "dependencies": { + "pify": "^2.3.0" + } + }, + "node_modules/read-cache/node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/reduce-css-calc": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/reduce-css-calc/-/reduce-css-calc-2.1.8.tgz", + "integrity": "sha512-8liAVezDmUcH+tdzoEGrhfbGcP7nOV4NkGE3a74+qqvE7nt9i4sKLGBuZNOnpI4WiGksiNPklZxva80061QiPg==", + "dev": true, + "dependencies": { + "css-unit-converter": "^1.1.1", + "postcss-value-parser": "^3.3.0" + } + }, + "node_modules/reduce-css-calc/node_modules/postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + }, + "node_modules/regenerate": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", + "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==" + }, + "node_modules/regenerate-unicode-properties": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.0.1.tgz", + "integrity": "sha512-vn5DU6yg6h8hP/2OkQo3K7uVILvY4iu0oI4t3HFa81UPkhGJwkRwM10JEc3upjdhHjs/k8GJY1sRBhk5sr69Bw==", + "dependencies": { + "regenerate": "^1.4.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/regenerator-runtime": { + "version": "0.13.9", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz", + "integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==" + }, + "node_modules/regenerator-transform": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.0.tgz", + "integrity": "sha512-LsrGtPmbYg19bcPHwdtmXwbW+TqNvtY4riE3P83foeHRroMbH6/2ddFBfab3t7kbzc7v7p4wbkIecHImqt0QNg==", + "dependencies": { + "@babel/runtime": "^7.8.4" + } + }, + "node_modules/regex-not": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", + "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", + "dependencies": { + "extend-shallow": "^3.0.2", + "safe-regex": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/regex-not/node_modules/extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dependencies": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/regex-not/node_modules/is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dependencies": { + "is-plain-object": "^2.0.4" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/regexp.prototype.flags": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz", + "integrity": "sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "functions-have-names": "^1.2.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/regexpu-core": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.0.1.tgz", + "integrity": "sha512-CriEZlrKK9VJw/xQGJpQM5rY88BtuL8DM+AEwvcThHilbxiTAy8vq4iJnd2tqq8wLmjbGZzP7ZcKFjbGkmEFrw==", + "dependencies": { + "regenerate": "^1.4.2", + "regenerate-unicode-properties": "^10.0.1", + "regjsgen": "^0.6.0", + "regjsparser": "^0.8.2", + "unicode-match-property-ecmascript": "^2.0.0", + "unicode-match-property-value-ecmascript": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/regjsgen": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.6.0.tgz", + "integrity": "sha512-ozE883Uigtqj3bx7OhL1KNbCzGyW2NQZPl6Hs09WTvCuZD5sTI4JY58bkbQWa/Y9hxIsvJ3M8Nbf7j54IqeZbA==" + }, + "node_modules/regjsparser": { + "version": "0.8.4", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.8.4.tgz", + "integrity": "sha512-J3LABycON/VNEu3abOviqGHuB/LOtOQj8SKmfP9anY5GfAVw/SPjwzSjxGjbZXIxbGfqTHtJw58C2Li/WkStmA==", + "dependencies": { + "jsesc": "~0.5.0" + }, + "bin": { + "regjsparser": "bin/parser" + } + }, + "node_modules/regjsparser/node_modules/jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", + "bin": { + "jsesc": "bin/jsesc" + } + }, + "node_modules/relateurl": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", + "integrity": "sha1-VNvzd+UUQKypCkzSdGANP/LYiKk=", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", + "optional": true + }, + "node_modules/renderkid": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/renderkid/-/renderkid-2.0.7.tgz", + "integrity": "sha512-oCcFyxaMrKsKcTY59qnCAtmDVSLfPbrv6A3tVbPdFMMrv5jaK10V6m40cKsoPNhAqN6rmHW9sswW4o3ruSrwUQ==", + "dependencies": { + "css-select": "^4.1.3", + "dom-converter": "^0.2.0", + "htmlparser2": "^6.1.0", + "lodash": "^4.17.21", + "strip-ansi": "^3.0.1" + } + }, + "node_modules/renderkid/node_modules/ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/renderkid/node_modules/strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/repeat-element": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.4.tgz", + "integrity": "sha512-LFiNfRcSu7KK3evMyYOuCzv3L10TW7yC1G2/+StMjK8Y6Vqd2MG7r/Qjw4ghtuCOjFvlnms/iMmLqpvW/ES/WQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", + "engines": { + "node": ">=0.10" + } + }, + "node_modules/replace-in-file": { + "version": "6.3.5", + "resolved": "https://registry.npmjs.org/replace-in-file/-/replace-in-file-6.3.5.tgz", + "integrity": "sha512-arB9d3ENdKva2fxRnSjwBEXfK1npgyci7ZZuwysgAp7ORjHSyxz6oqIjTEv8R0Ydl4Ll7uOAZXL4vbkhGIizCg==", + "dev": true, + "dependencies": { + "chalk": "^4.1.2", + "glob": "^7.2.0", + "yargs": "^17.2.1" + }, + "bin": { + "replace-in-file": "bin/cli.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=" + }, + "node_modules/resolve": { + "version": "1.22.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz", + "integrity": "sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw==", + "dependencies": { + "is-core-module": "^2.8.1", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve-path": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/resolve-path/-/resolve-path-1.4.0.tgz", + "integrity": "sha512-i1xevIst/Qa+nA9olDxLWnLk8YZbi8R/7JPbCMcgyWaFR6bKWaexgJgEB5oc2PKMjYdrHynyz0NY+if+H98t1w==", + "dev": true, + "dependencies": { + "http-errors": "~1.6.2", + "path-is-absolute": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/resolve-path/node_modules/depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/resolve-path/node_modules/http-errors": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "integrity": "sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A==", + "dev": true, + "dependencies": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.0", + "statuses": ">= 1.4.0 < 2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/resolve-path/node_modules/inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==", + "dev": true + }, + "node_modules/resolve-path/node_modules/setprototypeof": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", + "dev": true + }, + "node_modules/resolve-url": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", + "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", + "deprecated": "https://github.com/lydell/resolve-url#deprecated" + }, + "node_modules/restore-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "dependencies": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ret": { + "version": "0.1.15", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", + "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", + "engines": { + "node": ">=0.12" + } + }, + "node_modules/retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", + "integrity": "sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs=", + "engines": { + "node": ">= 4" + } + }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rgb-regex": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/rgb-regex/-/rgb-regex-1.0.1.tgz", + "integrity": "sha1-wODWiC3w4jviVKR16O3UGRX+rrE=" + }, + "node_modules/rgba-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/rgba-regex/-/rgba-regex-1.0.0.tgz", + "integrity": "sha1-QzdOLiyglosO8VI0YLfXMP8i7rM=" + }, + "node_modules/rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, + "node_modules/ripemd160": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", + "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", + "dependencies": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1" + } + }, + "node_modules/run-async": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", + "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/run-queue": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/run-queue/-/run-queue-1.0.3.tgz", + "integrity": "sha1-6Eg5bwV9Ij8kOGkkYY4laUFh7Ec=", + "dependencies": { + "aproba": "^1.1.1" + } + }, + "node_modules/rxjs": { + "version": "6.6.7", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", + "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", + "dependencies": { + "tslib": "^1.9.0" + }, + "engines": { + "npm": ">=2.0.0" + } + }, + "node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/safe-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", + "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", + "dependencies": { + "ret": "~0.1.10" + } + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "node_modules/sass-loader": { + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-10.1.1.tgz", + "integrity": "sha512-W6gVDXAd5hR/WHsPicvZdjAWHBcEJ44UahgxcIE196fW2ong0ZHMPO1kZuI5q0VlvMQZh32gpv69PLWQm70qrw==", + "dependencies": { + "klona": "^2.0.4", + "loader-utils": "^2.0.0", + "neo-async": "^2.6.2", + "schema-utils": "^3.0.0", + "semver": "^7.3.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "fibers": ">= 3.1.0", + "node-sass": "^4.0.0 || ^5.0.0", + "sass": "^1.3.0", + "webpack": "^4.36.0 || ^5.0.0" + }, + "peerDependenciesMeta": { + "fibers": { + "optional": true + }, + "node-sass": { + "optional": true + }, + "sass": { + "optional": true + } + } + }, + "node_modules/sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" + }, + "node_modules/schema-utils": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", + "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", + "dependencies": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/scule": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/scule/-/scule-0.2.1.tgz", + "integrity": "sha512-M9gnWtn3J0W+UhJOHmBxBTwv8mZCan5i1Himp60t6vvZcor0wr+IM0URKmIglsWJ7bRujNAVVN77fp+uZaWoKg==" + }, + "node_modules/semver": { + "version": "7.3.7", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", + "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/semver/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/semver/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "node_modules/send": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", + "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/send/node_modules/debug/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "node_modules/send/node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/send/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "node_modules/send/node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/send/node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/serialize-javascript": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-5.0.1.tgz", + "integrity": "sha512-SaaNal9imEO737H2c05Og0/8LUXG7EnsZyMa8MzkmuHoELfT6txuj0cMqRj6zfPKnmQ1yasR4PCJc8x+M4JSPA==", + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/serve-placeholder": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/serve-placeholder/-/serve-placeholder-1.2.4.tgz", + "integrity": "sha512-jWD9cZXLcr4vHTTL5KEPIUBUYyOWN/z6v/tn0l6XxFhi9iqV3Fc5Y1aFeduUyz+cx8sALzGCUczkPfeOlrq9jg==", + "dependencies": { + "defu": "^5.0.0" + } + }, + "node_modules/serve-static": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", + "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", + "dependencies": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.18.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/server-destroy": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/server-destroy/-/server-destroy-1.0.1.tgz", + "integrity": "sha1-8Tv5KOQrnD55OD5hzDmYtdFObN0=" + }, + "node_modules/set-immediate-shim": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz", + "integrity": "sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/set-value": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", + "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", + "dependencies": { + "extend-shallow": "^2.0.1", + "is-extendable": "^0.1.1", + "is-plain-object": "^2.0.3", + "split-string": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=" + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + }, + "node_modules/sha.js": { + "version": "2.4.11", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", + "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "dependencies": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + }, + "bin": { + "sha.js": "bin.js" + } + }, + "node_modules/shallow-clone": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", + "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", + "dev": true, + "dependencies": { + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "engines": { + "node": ">=8" + } + }, + "node_modules/shell-quote": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.7.3.tgz", + "integrity": "sha512-Vpfqwm4EnqGdlsBFNmHhxhElJYrdfcxPThu+ryKS5J8L/fhAwLazFZtq+S+TWZ9ANj2piSQLGj6NQg+lKPmxrw==" + }, + "node_modules/side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "dependencies": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, + "node_modules/simple-swizzle": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", + "integrity": "sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo=", + "dependencies": { + "is-arrayish": "^0.3.1" + } + }, + "node_modules/simple-swizzle/node_modules/is-arrayish": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", + "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==" + }, + "node_modules/sirv": { + "version": "1.0.19", + "resolved": "https://registry.npmjs.org/sirv/-/sirv-1.0.19.tgz", + "integrity": "sha512-JuLThK3TnZG1TAKDwNIqNq6QA2afLOCcm+iE8D1Kj3GA40pSPsxQjjJl0J8X3tsR7T+CP1GavpzLwYkgVLWrZQ==", + "dependencies": { + "@polka/url": "^1.0.0-next.20", + "mrmime": "^1.0.0", + "totalist": "^1.0.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "engines": { + "node": ">=8" + } + }, + "node_modules/snapdragon": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", + "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", + "dependencies": { + "base": "^0.11.1", + "debug": "^2.2.0", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "map-cache": "^0.2.2", + "source-map": "^0.5.6", + "source-map-resolve": "^0.5.0", + "use": "^3.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon-node": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", + "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", + "dependencies": { + "define-property": "^1.0.0", + "isobject": "^3.0.0", + "snapdragon-util": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon-node/node_modules/define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dependencies": { + "is-descriptor": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon-node/node_modules/is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dependencies": { + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon-node/node_modules/is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dependencies": { + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon-node/node_modules/is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dependencies": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon-util": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", + "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", + "dependencies": { + "kind-of": "^3.2.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon-util/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/snapdragon/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "node_modules/snapdragon/node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/socket.io": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.5.0.tgz", + "integrity": "sha512-slTYqU2jCgMjXwresG8grhUi/cC6GjzmcfqArzaH3BN/9I/42eZk9yamNvZJdBfTubkjEdKAKs12NEztId+bUA==", + "dependencies": { + "accepts": "~1.3.4", + "base64id": "~2.0.0", + "debug": "~4.3.2", + "engine.io": "~6.2.0", + "socket.io-adapter": "~2.4.0", + "socket.io-parser": "~4.0.4" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/socket.io-adapter": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.4.0.tgz", + "integrity": "sha512-W4N+o69rkMEGVuk2D/cvca3uYsvGlMwsySWV447y99gUPghxq42BxqLNMndb+a1mm/5/7NeXVQS7RLa2XyXvYg==" + }, + "node_modules/socket.io-client": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.5.0.tgz", + "integrity": "sha512-HW61c1G7OrYGxaI79WRn17+b03iBCdvhBj4iqyXHBoL5M8w2MSO/vChsjA93knG4GYEai1/vbXWJna9dzxXtSg==", + "dependencies": { + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.3.2", + "engine.io-client": "~6.2.1", + "socket.io-parser": "~4.2.0" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/socket.io-client/node_modules/socket.io-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.0.tgz", + "integrity": "sha512-tLfmEwcEwnlQTxFB7jibL/q2+q8dlVQzj4JdRLJ/W/G1+Fu9VSxCx1Lo+n1HvXxKnM//dUuD0xgiA7tQf57Vng==", + "dependencies": { + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.3.1" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/socket.io-parser": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.0.4.tgz", + "integrity": "sha512-t+b0SS+IxG7Rxzda2EVvyBZbvFPBCjJoyHuE0P//7OAsN23GItzDRdWa6ALxZI/8R5ygK7jAR6t028/z+7295g==", + "dependencies": { + "@types/component-emitter": "^1.2.10", + "component-emitter": "~1.3.0", + "debug": "~4.3.1" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/sort-keys": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-1.1.2.tgz", + "integrity": "sha1-RBttTTRnmPG05J6JIK37oOVD+a0=", + "dependencies": { + "is-plain-obj": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/sort-keys/node_modules/is-plain-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", + "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/sortablejs": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/sortablejs/-/sortablejs-1.10.2.tgz", + "integrity": "sha512-YkPGufevysvfwn5rfdlGyrGjt7/CRHwvRPogD/lC+TnvcN29jDpCifKP+rBqf+LRldfXSTh+0CGLcSg0VIxq3A==" + }, + "node_modules/source-list-map": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz", + "integrity": "sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==" + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-js": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", + "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-resolve": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", + "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==", + "deprecated": "See https://github.com/lydell/source-map-resolve#deprecated", + "dependencies": { + "atob": "^2.1.2", + "decode-uri-component": "^0.2.0", + "resolve-url": "^0.2.1", + "source-map-url": "^0.4.0", + "urix": "^0.1.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/source-map-url": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.1.tgz", + "integrity": "sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw==", + "deprecated": "See https://github.com/lydell/source-map-url#deprecated" + }, + "node_modules/split-on-first": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/split-on-first/-/split-on-first-1.1.0.tgz", + "integrity": "sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw==", + "engines": { + "node": ">=6" + } + }, + "node_modules/split-string": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", + "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", + "dependencies": { + "extend-shallow": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/split-string/node_modules/extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dependencies": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/split-string/node_modules/is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dependencies": { + "is-plain-object": "^2.0.4" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" + }, + "node_modules/ssri": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.1.tgz", + "integrity": "sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ==", + "dependencies": { + "minipass": "^3.1.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/stable": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz", + "integrity": "sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==", + "deprecated": "Modern JS already guarantees Array#sort() is a stable sort, so this library is deprecated. See the compatibility table on MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#browser_compatibility" + }, + "node_modules/stack-trace": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", + "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=", + "engines": { + "node": "*" + } + }, + "node_modules/stackframe": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/stackframe/-/stackframe-1.2.1.tgz", + "integrity": "sha512-h88QkzREN/hy8eRdyNhhsO7RSJ5oyTqxxmmn0dzBIMUclZsjpfmrsg81vp8mjjAs2vAZ72nyWxRUwSwmh0e4xg==" + }, + "node_modules/static-extend": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", + "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", + "dependencies": { + "define-property": "^0.2.5", + "object-copy": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/std-env": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-2.3.1.tgz", + "integrity": "sha512-eOsoKTWnr6C8aWrqJJ2KAReXoa7Vn5Ywyw6uCXgA/xDhxPoaIsBa5aNJmISY04dLwXPBnDHW4diGM7Sn5K4R/g==", + "dependencies": { + "ci-info": "^3.1.1" + } + }, + "node_modules/stream-browserify": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.2.tgz", + "integrity": "sha512-nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg==", + "dependencies": { + "inherits": "~2.0.1", + "readable-stream": "^2.0.2" + } + }, + "node_modules/stream-each": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/stream-each/-/stream-each-1.2.3.tgz", + "integrity": "sha512-vlMC2f8I2u/bZGqkdfLQW/13Zihpej/7PmSiMQsbYddxuTsJp8vRe2x2FvVExZg7FaOds43ROAuFJwPR4MTZLw==", + "dependencies": { + "end-of-stream": "^1.1.0", + "stream-shift": "^1.0.0" + } + }, + "node_modules/stream-http": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.3.tgz", + "integrity": "sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw==", + "dependencies": { + "builtin-status-codes": "^3.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.3.6", + "to-arraybuffer": "^1.0.0", + "xtend": "^4.0.0" + } + }, + "node_modules/stream-shift": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", + "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==" + }, + "node_modules/strict-uri-encode": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz", + "integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string.prototype.trimend": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.5.tgz", + "integrity": "sha512-I7RGvmjV4pJ7O3kdf+LXFpVfdNOxtCW/2C8f6jNiW4+PQchwxkCDzlk1/7p+Wl4bqFIZeF47qAHXLuHHWKAxog==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.19.5" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimstart": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.5.tgz", + "integrity": "sha512-THx16TJCGlsN0o6dl2o6ncWUsdgnLRSA23rRE5pyGBw/mLr3Ej/R2LaqCtgP8VNMGZsvMWnf9ooZPyY2bHvUFg==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.19.5" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/style-resources-loader": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/style-resources-loader/-/style-resources-loader-1.5.0.tgz", + "integrity": "sha512-fIfyvQ+uvXaCBGGAgfh+9v46ARQB1AWdaop2RpQw0PBVuROsTBqGvx8dj0kxwjGOAyq3vepe4AOK3M6+Q/q2jw==", + "dependencies": { + "glob": "^7.2.0", + "loader-utils": "^2.0.0", + "schema-utils": "^2.7.0", + "tslib": "^2.3.1" + }, + "engines": { + "node": ">=8.9" + }, + "peerDependencies": { + "webpack": "^3.0.0 || ^4.0.0 || ^5.0.0" + } + }, + "node_modules/style-resources-loader/node_modules/schema-utils": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz", + "integrity": "sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==", + "dependencies": { + "@types/json-schema": "^7.0.5", + "ajv": "^6.12.4", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 8.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/style-resources-loader/node_modules/tslib": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" + }, + "node_modules/stylehacks": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-4.0.3.tgz", + "integrity": "sha512-7GlLk9JwlElY4Y6a/rmbH2MhVlTyVmiJd1PfTCqFaIBEGMYNsrO/v3SeGTdhBThLg4Z+NbOk/qFMwCa+J+3p/g==", + "dependencies": { + "browserslist": "^4.0.0", + "postcss": "^7.0.0", + "postcss-selector-parser": "^3.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/stylehacks/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "node_modules/stylehacks/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/stylehacks/node_modules/postcss-selector-parser": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-3.1.2.tgz", + "integrity": "sha512-h7fJ/5uWuRVyOtkO45pnt1Ih40CEleeyCHzipqAZO2e5H20g25Y48uYnFUiShvY4rZWNJ/Bib/KVPmanaCtOhA==", + "dependencies": { + "dot-prop": "^5.2.0", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/svg-tags": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/svg-tags/-/svg-tags-1.0.0.tgz", + "integrity": "sha1-WPcc7jvVGbWdSyqEO2x95krAR2Q=" + }, + "node_modules/svgo": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/svgo/-/svgo-1.3.2.tgz", + "integrity": "sha512-yhy/sQYxR5BkC98CY7o31VGsg014AKLEPxdfhora76l36hD9Rdy5NZA/Ocn6yayNPgSamYdtX2rFJdcv07AYVw==", + "deprecated": "This SVGO version is no longer supported. Upgrade to v2.x.x.", + "dependencies": { + "chalk": "^2.4.1", + "coa": "^2.0.2", + "css-select": "^2.0.0", + "css-select-base-adapter": "^0.1.1", + "css-tree": "1.0.0-alpha.37", + "csso": "^4.0.2", + "js-yaml": "^3.13.1", + "mkdirp": "~0.5.1", + "object.values": "^1.1.0", + "sax": "~1.2.4", + "stable": "^0.1.8", + "unquote": "~1.1.1", + "util.promisify": "~1.0.0" + }, + "bin": { + "svgo": "bin/svgo" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/svgo/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/svgo/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/svgo/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/svgo/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" + }, + "node_modules/svgo/node_modules/css-select": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-2.1.0.tgz", + "integrity": "sha512-Dqk7LQKpwLoH3VovzZnkzegqNSuAziQyNZUcrdDM401iY+R5NkGBXGmtO05/yaXQziALuPogeG0b7UAgjnTJTQ==", + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^3.2.1", + "domutils": "^1.7.0", + "nth-check": "^1.0.2" + } + }, + "node_modules/svgo/node_modules/css-what": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-3.4.2.tgz", + "integrity": "sha512-ACUm3L0/jiZTqfzRM3Hi9Q8eZqd6IK37mMWPLz9PJxkLWllYeRf+EHUSHYEtFop2Eqytaq1FizFVh7XfBnXCDQ==", + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/svgo/node_modules/dom-serializer": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.2.tgz", + "integrity": "sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==", + "dependencies": { + "domelementtype": "^2.0.1", + "entities": "^2.0.0" + } + }, + "node_modules/svgo/node_modules/domutils": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.7.0.tgz", + "integrity": "sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==", + "dependencies": { + "dom-serializer": "0", + "domelementtype": "1" + } + }, + "node_modules/svgo/node_modules/domutils/node_modules/domelementtype": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", + "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==" + }, + "node_modules/svgo/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "engines": { + "node": ">=4" + } + }, + "node_modules/svgo/node_modules/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==", + "dependencies": { + "boolbase": "~1.0.0" + } + }, + "node_modules/svgo/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/tailwind-config-viewer": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/tailwind-config-viewer/-/tailwind-config-viewer-1.7.1.tgz", + "integrity": "sha512-EtDwFzgQEMJ6dFmp/6K+QJSP7NWANrGDsbwkn/BEq7MVJd/dEIZ5BBZTxo5jx+opa3HNJu/CHtWanKSCrgNwpA==", + "dev": true, + "dependencies": { + "@koa/router": "^9.0.1", + "commander": "^6.0.0", + "fs-extra": "^9.0.1", + "koa": "^2.12.0", + "koa-static": "^5.0.0", + "open": "^7.0.4", + "portfinder": "^1.0.26", + "replace-in-file": "^6.1.0" + }, + "bin": { + "tailwind-config-viewer": "cli/index.js", + "tailwindcss-config-viewer": "cli/index.js" + }, + "engines": { + "node": ">=8" + }, + "peerDependencies": { + "tailwindcss": "1 || 2 || 2.0.1-compat || 3" + } + }, + "node_modules/tailwind-config-viewer/node_modules/commander": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz", + "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/tailwindcss": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.1.4.tgz", + "integrity": "sha512-NrxbFV4tYsga/hpWbRyUfIaBrNMXDxx5BsHgBS4v5tlyjf+sDsgBg5m9OxjrXIqAS/uR9kicxLKP+bEHI7BSeQ==", + "dev": true, + "dependencies": { + "arg": "^5.0.2", + "chokidar": "^3.5.3", + "color-name": "^1.1.4", + "detective": "^5.2.1", + "didyoumean": "^1.2.2", + "dlv": "^1.1.3", + "fast-glob": "^3.2.11", + "glob-parent": "^6.0.2", + "is-glob": "^4.0.3", + "lilconfig": "^2.0.5", + "normalize-path": "^3.0.0", + "object-hash": "^3.0.0", + "picocolors": "^1.0.0", + "postcss": "^8.4.14", + "postcss-import": "^14.1.0", + "postcss-js": "^4.0.0", + "postcss-load-config": "^3.1.4", + "postcss-nested": "5.0.6", + "postcss-selector-parser": "^6.0.10", + "postcss-value-parser": "^4.2.0", + "quick-lru": "^5.1.1", + "resolve": "^1.22.0" + }, + "bin": { + "tailwind": "lib/cli.js", + "tailwindcss": "lib/cli.js" + }, + "engines": { + "node": ">=12.13.0" + }, + "peerDependencies": { + "postcss": "^8.0.9" + } + }, + "node_modules/tailwindcss/node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/tailwindcss/node_modules/postcss-import": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-14.1.0.tgz", + "integrity": "sha512-flwI+Vgm4SElObFVPpTIT7SU7R3qk2L7PyduMcokiaVKuWv9d/U+Gm/QAd8NDLuykTWTkcrjOeD2Pp1rMeBTGw==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.0.0", + "read-cache": "^1.0.0", + "resolve": "^1.1.7" + }, + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "postcss": "^8.0.0" + } + }, + "node_modules/tapable": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz", + "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/tar": { + "version": "6.1.11", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.11.tgz", + "integrity": "sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA==", + "dependencies": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^3.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/tar/node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/tar/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "node_modules/terser": { + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-4.8.0.tgz", + "integrity": "sha512-EAPipTNeWsb/3wLPeup1tVPaXfIaU68xMnVdPafIL1TV05OhASArYyIfFvnvJCNrR2NIOvDVNNTFRa+Re2MWyw==", + "dependencies": { + "commander": "^2.20.0", + "source-map": "~0.6.1", + "source-map-support": "~0.5.12" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/terser-webpack-plugin": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-4.2.3.tgz", + "integrity": "sha512-jTgXh40RnvOrLQNgIkwEKnQ8rmHjHK4u+6UBEi+W+FPmvb+uo+chJXntKe7/3lW5mNysgSWD60KyesnhW8D6MQ==", + "dependencies": { + "cacache": "^15.0.5", + "find-cache-dir": "^3.3.1", + "jest-worker": "^26.5.0", + "p-limit": "^3.0.2", + "schema-utils": "^3.0.0", + "serialize-javascript": "^5.0.1", + "source-map": "^0.6.1", + "terser": "^5.3.4", + "webpack-sources": "^1.4.3" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^4.0.0 || ^5.0.0" + } + }, + "node_modules/terser-webpack-plugin/node_modules/acorn": { + "version": "8.7.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.1.tgz", + "integrity": "sha512-Xx54uLJQZ19lKygFXOWsscKUbsBZW0CPykPhVQdhIeIwrbPmJzqeASDInc8nKBnp/JT6igTs82qPXz069H8I/A==", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/terser-webpack-plugin/node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/terser-webpack-plugin/node_modules/terser": { + "version": "5.13.1", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.13.1.tgz", + "integrity": "sha512-hn4WKOfwnwbYfe48NgrQjqNOH9jzLqRcIfbYytOXCOv46LBfWr9bDS17MQqOi+BWGD0sJK3Sj5NC/gJjiojaoA==", + "dependencies": { + "acorn": "^8.5.0", + "commander": "^2.20.0", + "source-map": "~0.8.0-beta.0", + "source-map-support": "~0.5.20" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/terser-webpack-plugin/node_modules/terser/node_modules/source-map": { + "version": "0.8.0-beta.0", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.8.0-beta.0.tgz", + "integrity": "sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA==", + "dependencies": { + "whatwg-url": "^7.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/terser-webpack-plugin/node_modules/tr46": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz", + "integrity": "sha1-qLE/1r/SSJUZZ0zN5VujaTtwbQk=", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/terser-webpack-plugin/node_modules/webidl-conversions": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz", + "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==" + }, + "node_modules/terser-webpack-plugin/node_modules/whatwg-url": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.1.0.tgz", + "integrity": "sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==", + "dependencies": { + "lodash.sortby": "^4.7.0", + "tr46": "^1.0.1", + "webidl-conversions": "^4.0.2" + } + }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=" + }, + "node_modules/thread-loader": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/thread-loader/-/thread-loader-3.0.4.tgz", + "integrity": "sha512-ByaL2TPb+m6yArpqQUZvP+5S1mZtXsEP7nWKKlAUTm7fCml8kB5s1uI3+eHRP2bk5mVYfRSBI7FFf+tWEyLZwA==", + "dependencies": { + "json-parse-better-errors": "^1.0.2", + "loader-runner": "^4.1.0", + "loader-utils": "^2.0.0", + "neo-async": "^2.6.2", + "schema-utils": "^3.0.0" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^4.27.0 || ^5.0.0" + } + }, + "node_modules/through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" + }, + "node_modules/through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dependencies": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "node_modules/time-fix-plugin": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/time-fix-plugin/-/time-fix-plugin-2.0.7.tgz", + "integrity": "sha512-uVFet1LQToeUX0rTcSiYVYVoGuBpc8gP/2jnlUzuHMHe+gux6XLsNzxLUweabMwiUj5ejhoIMsUI55nVSEa/Vw==", + "peerDependencies": { + "webpack": ">=4.0.0" + } + }, + "node_modules/timers-browserify": { + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.12.tgz", + "integrity": "sha512-9phl76Cqm6FhSX9Xe1ZUAMLtm1BLkKj2Qd5ApyWkXzsMRaA7dgr81kf4wJmQf/hAvg8EEyJxDo3du/0KlhPiKQ==", + "dependencies": { + "setimmediate": "^1.0.4" + }, + "engines": { + "node": ">=0.6.0" + } + }, + "node_modules/timsort": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/timsort/-/timsort-0.3.0.tgz", + "integrity": "sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q=" + }, + "node_modules/tiny-emitter": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-2.1.0.tgz", + "integrity": "sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==" + }, + "node_modules/tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "dependencies": { + "os-tmpdir": "~1.0.2" + }, + "engines": { + "node": ">=0.6.0" + } + }, + "node_modules/to-arraybuffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz", + "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=" + }, + "node_modules/to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", + "engines": { + "node": ">=4" + } + }, + "node_modules/to-object-path": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", + "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/to-object-path/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/to-regex": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", + "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", + "dependencies": { + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "regex-not": "^1.0.2", + "safe-regex": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/to-regex/node_modules/define-property": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", + "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", + "dependencies": { + "is-descriptor": "^1.0.2", + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/to-regex/node_modules/extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dependencies": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/to-regex/node_modules/is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dependencies": { + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/to-regex/node_modules/is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dependencies": { + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/to-regex/node_modules/is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dependencies": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/to-regex/node_modules/is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dependencies": { + "is-plain-object": "^2.0.4" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/totalist": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/totalist/-/totalist-1.1.0.tgz", + "integrity": "sha512-gduQwd1rOdDMGxFG1gEvhV88Oirdo2p+KjoYFU7k2g+i7n6AFFbDQ5kMPUsW0pNbfQsB/cwXvT1i4Bue0s9g5g==", + "engines": { + "node": ">=6" + } + }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=" + }, + "node_modules/trix": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/trix/-/trix-1.3.1.tgz", + "integrity": "sha512-BbH6mb6gk+AV4f2as38mP6Ucc1LE3OD6XxkZnAgPIduWXYtvg2mI3cZhIZSLqmMh9OITEpOBCCk88IVmyjU7bA==" + }, + "node_modules/ts-pnp": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/ts-pnp/-/ts-pnp-1.2.0.tgz", + "integrity": "sha512-csd+vJOb/gkzvcCHgTGSChYpy5f1/XKNsmvBGO4JXS+z1v2HobugDz4s1IeFXM3wZB44uczs+eazB5Q/ccdhQw==", + "engines": { + "node": ">=6" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + }, + "node_modules/tsscmp": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/tsscmp/-/tsscmp-1.0.6.tgz", + "integrity": "sha512-LxhtAkPDTkVCMQjt2h6eBVY28KCjikZqZfMcC15YBeNjkgUpdCfBu5HoiOTDu86v6smE8yOjyEktJ8hlbANHQA==", + "dev": true, + "engines": { + "node": ">=0.6.x" + } + }, + "node_modules/tty-browserify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", + "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=" + }, + "node_modules/type": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", + "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==" + }, + "node_modules/type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dev": true, + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" + }, + "node_modules/ua-parser-js": { + "version": "0.7.31", + "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.31.tgz", + "integrity": "sha512-qLK/Xe9E2uzmYI3qLeOmI0tEOt+TBBQyUIAh4aAgU05FVYzeZrKUdkAZfBNVGRaHVgV0TDkdEngJSw/SyQchkQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/ua-parser-js" + }, + { + "type": "paypal", + "url": "https://paypal.me/faisalman" + } + ], + "engines": { + "node": "*" + } + }, + "node_modules/ufo": { + "version": "0.7.11", + "resolved": "https://registry.npmjs.org/ufo/-/ufo-0.7.11.tgz", + "integrity": "sha512-IT3q0lPvtkqQ8toHQN/BkOi4VIqoqheqM1FnkNWT9y0G8B3xJhwnoKBu5OHx8zHDOvveQzfKuFowJ0VSARiIDg==" + }, + "node_modules/uglify-js": { + "version": "3.15.5", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.15.5.tgz", + "integrity": "sha512-hNM5q5GbBRB5xB+PMqVRcgYe4c8jbyZ1pzZhS6jbq54/4F2gFK869ZheiE5A8/t+W5jtTNpWef/5Q9zk639FNQ==", + "bin": { + "uglifyjs": "bin/uglifyjs" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/unbox-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", + "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", + "dependencies": { + "call-bind": "^1.0.2", + "has-bigints": "^1.0.2", + "has-symbols": "^1.0.3", + "which-boxed-primitive": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/unfetch": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/unfetch/-/unfetch-4.2.0.tgz", + "integrity": "sha512-F9p7yYCn6cIW9El1zi0HI6vqpeIvBsr3dSuRO6Xuppb1u5rXpCPmMvLSyECLhybr9isec8Ohl0hPekMVrEinDA==" + }, + "node_modules/unicode-canonical-property-names-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", + "integrity": "sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==", + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-match-property-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", + "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", + "dependencies": { + "unicode-canonical-property-names-ecmascript": "^2.0.0", + "unicode-property-aliases-ecmascript": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-match-property-value-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.0.0.tgz", + "integrity": "sha512-7Yhkc0Ye+t4PNYzOGKedDhXbYIBe1XEQYQxOPyhcXNMJ0WCABqqj6ckydd6pWRZTHV4GuCPKdBAUiMc60tsKVw==", + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-property-aliases-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.0.0.tgz", + "integrity": "sha512-5Zfuy9q/DFr4tfO7ZPeVXb1aPoeQSdeFMLpYuFebehDAhbuevLs5yxSZmIFN1tP5F9Wl4IpJrYojg85/zgyZHQ==", + "engines": { + "node": ">=4" + } + }, + "node_modules/union-value": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", + "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", + "dependencies": { + "arr-union": "^3.1.0", + "get-value": "^2.0.6", + "is-extendable": "^0.1.1", + "set-value": "^2.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/uniq": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/uniq/-/uniq-1.0.1.tgz", + "integrity": "sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8=" + }, + "node_modules/uniqs": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/uniqs/-/uniqs-2.0.0.tgz", + "integrity": "sha1-/+3ks2slKQaW5uFl1KWe25mOawI=" + }, + "node_modules/unique-filename": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", + "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", + "dependencies": { + "unique-slug": "^2.0.0" + } + }, + "node_modules/unique-slug": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz", + "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==", + "dependencies": { + "imurmurhash": "^0.1.4" + } + }, + "node_modules/universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/unquote": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/unquote/-/unquote-1.1.1.tgz", + "integrity": "sha1-j97XMk7G6IoP+LkF58CYzcCG1UQ=" + }, + "node_modules/unset-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", + "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", + "dependencies": { + "has-value": "^0.3.1", + "isobject": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/unset-value/node_modules/has-value": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", + "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", + "dependencies": { + "get-value": "^2.0.3", + "has-values": "^0.1.4", + "isobject": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/unset-value/node_modules/has-value/node_modules/isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dependencies": { + "isarray": "1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/unset-value/node_modules/has-values": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", + "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/upath": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/upath/-/upath-2.0.1.tgz", + "integrity": "sha512-1uEe95xksV1O0CYKXo8vQvN1JEbtJp7lb7C5U9HMsIp6IVwntkH/oNUzyVNQSd4S1sYk2FpSSW44FqMc8qee5w==", + "engines": { + "node": ">=4", + "yarn": "*" + } + }, + "node_modules/upper-case": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/upper-case/-/upper-case-1.1.3.tgz", + "integrity": "sha1-9rRQHC7EzdJrp4vnIilh3ndiFZg=" + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/urix": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", + "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", + "deprecated": "Please see https://github.com/lydell/urix#deprecated" + }, + "node_modules/url": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", + "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", + "dependencies": { + "punycode": "1.3.2", + "querystring": "0.2.0" + } + }, + "node_modules/url-loader": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/url-loader/-/url-loader-4.1.1.tgz", + "integrity": "sha512-3BTV812+AVHHOJQO8O5MkWgZ5aosP7GnROJwvzLS9hWDj00lZ6Z0wNak423Lp9PBZN05N+Jk/N5Si8jRAlGyWA==", + "dependencies": { + "loader-utils": "^2.0.0", + "mime-types": "^2.1.27", + "schema-utils": "^3.0.0" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "file-loader": "*", + "webpack": "^4.0.0 || ^5.0.0" + }, + "peerDependenciesMeta": { + "file-loader": { + "optional": true + } + } + }, + "node_modules/url/node_modules/punycode": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=" + }, + "node_modules/use": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", + "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/util": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/util/-/util-0.11.1.tgz", + "integrity": "sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ==", + "dependencies": { + "inherits": "2.0.3" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "node_modules/util.promisify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.0.0.tgz", + "integrity": "sha512-i+6qA2MPhvoKLuxnJNpXAGhg7HphQOSUq2LKMZD0m15EiskXUkMvKdF4Uui0WYeCUGea+o2cw/ZuwehtfsrNkA==", + "dependencies": { + "define-properties": "^1.1.2", + "object.getownpropertydescriptors": "^2.0.3" + } + }, + "node_modules/util/node_modules/inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + }, + "node_modules/utila": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/utila/-/utila-0.4.0.tgz", + "integrity": "sha1-ihagXURWV6Oupe7MWxKk+lN5dyw=" + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/v-click-outside": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/v-click-outside/-/v-click-outside-3.1.2.tgz", + "integrity": "sha512-gMdRqfRE6m6XU6SiFi3dyBlFB2MWogiXpof8Aa3LQysrl9pzTndqp/iEaAphLoadaQUFnQ0ec6fLLaxr7LiY6A==", + "engines": { + "node": ">=6" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/vendors": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/vendors/-/vendors-1.0.4.tgz", + "integrity": "sha512-/juG65kTL4Cy2su4P8HjtkTxk6VmJDiOPBufWniqQ6wknac6jNiXS9vU+hO3wgusiyqWlzTbVHi0dyJqRONg3w==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/vm-browserify": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz", + "integrity": "sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==" + }, + "node_modules/vue": { + "version": "2.6.14", + "resolved": "https://registry.npmjs.org/vue/-/vue-2.6.14.tgz", + "integrity": "sha512-x2284lgYvjOMj3Za7kqzRcUSxBboHqtgRE2zlos1qWaOye5yUmHn42LB1250NJBLRwEcdrB0JRwyPTEPhfQjiQ==" + }, + "node_modules/vue-client-only": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/vue-client-only/-/vue-client-only-2.1.0.tgz", + "integrity": "sha512-vKl1skEKn8EK9f8P2ZzhRnuaRHLHrlt1sbRmazlvsx6EiC3A8oWF8YCBrMJzoN+W3OnElwIGbVjsx6/xelY1AA==" + }, + "node_modules/vue-hot-reload-api": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/vue-hot-reload-api/-/vue-hot-reload-api-2.3.4.tgz", + "integrity": "sha512-BXq3jwIagosjgNVae6tkHzzIk6a8MHFtzAdwhnV5VlvPTFxDCvIttgSiHWjdGoTJvXtmRu5HacExfdarRcFhog==" + }, + "node_modules/vue-loader": { + "version": "15.9.8", + "resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-15.9.8.tgz", + "integrity": "sha512-GwSkxPrihfLR69/dSV3+5CdMQ0D+jXg8Ma1S4nQXKJAznYFX14vHdc/NetQc34Dw+rBbIJyP7JOuVb9Fhprvog==", + "dependencies": { + "@vue/component-compiler-utils": "^3.1.0", + "hash-sum": "^1.0.2", + "loader-utils": "^1.1.0", + "vue-hot-reload-api": "^2.3.0", + "vue-style-loader": "^4.1.0" + }, + "peerDependencies": { + "css-loader": "*", + "webpack": "^3.0.0 || ^4.1.0 || ^5.0.0-0" + }, + "peerDependenciesMeta": { + "cache-loader": { + "optional": true + }, + "vue-template-compiler": { + "optional": true + } + } + }, + "node_modules/vue-loader/node_modules/hash-sum": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/hash-sum/-/hash-sum-1.0.2.tgz", + "integrity": "sha1-M7QHd3VMZDJXPBIMw4CLvRDUfwQ=" + }, + "node_modules/vue-loader/node_modules/json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" + } + }, + "node_modules/vue-loader/node_modules/loader-utils": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", + "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", + "dependencies": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^1.0.1" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/vue-meta": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/vue-meta/-/vue-meta-2.4.0.tgz", + "integrity": "sha512-XEeZUmlVeODclAjCNpWDnjgw+t3WA6gdzs6ENoIAgwO1J1d5p1tezDhtteLUFwcaQaTtayRrsx7GL6oXp/m2Jw==", + "dependencies": { + "deepmerge": "^4.2.2" + } + }, + "node_modules/vue-no-ssr": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/vue-no-ssr/-/vue-no-ssr-1.1.1.tgz", + "integrity": "sha512-ZMjqRpWabMPqPc7gIrG0Nw6vRf1+itwf0Itft7LbMXs2g3Zs/NFmevjZGN1x7K3Q95GmIjWbQZTVerxiBxI+0g==" + }, + "node_modules/vue-pdf": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/vue-pdf/-/vue-pdf-4.3.0.tgz", + "integrity": "sha512-zd3lJj6CbtrawgaaDDciTDjkJMUKiLWtbEmBg5CvFn9Noe9oAO/GNy/fc5c59qGuFCJ14ibIV1baw4S07e5bSQ==", + "dependencies": { + "babel-plugin-syntax-dynamic-import": "^6.18.0", + "loader-utils": "^1.4.0", + "pdfjs-dist": "2.6.347", + "raw-loader": "^4.0.2", + "vue-resize-sensor": "^2.0.0", + "worker-loader": "^2.0.0" + } + }, + "node_modules/vue-pdf/node_modules/json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" + } + }, + "node_modules/vue-pdf/node_modules/loader-utils": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", + "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", + "dependencies": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^1.0.1" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/vue-resize-sensor": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/vue-resize-sensor/-/vue-resize-sensor-2.0.0.tgz", + "integrity": "sha512-W+y2EAI/BxS4Vlcca9scQv8ifeBFck56DRtSwWJ2H4Cw1GLNUYxiZxUHHkuzuI5JPW/cYtL1bPO5xPyEXx4LmQ==" + }, + "node_modules/vue-router": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-3.5.3.tgz", + "integrity": "sha512-FUlILrW3DGitS2h+Xaw8aRNvGTwtuaxrRkNSHWTizOfLUie7wuYwezeZ50iflRn8YPV5kxmU2LQuu3nM/b3Zsg==" + }, + "node_modules/vue-server-renderer": { + "version": "2.6.14", + "resolved": "https://registry.npmjs.org/vue-server-renderer/-/vue-server-renderer-2.6.14.tgz", + "integrity": "sha512-HifYRa/LW7cKywg9gd4ZtvtRuBlstQBao5ZCWlg40fyB4OPoGfEXAzxb0emSLv4pBDOHYx0UjpqvxpiQFEuoLA==", + "dependencies": { + "chalk": "^1.1.3", + "hash-sum": "^1.0.2", + "he": "^1.1.0", + "lodash.template": "^4.5.0", + "lodash.uniq": "^4.5.0", + "resolve": "^1.2.0", + "serialize-javascript": "^3.1.0", + "source-map": "0.5.6" + } + }, + "node_modules/vue-server-renderer/node_modules/ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/vue-server-renderer/node_modules/ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/vue-server-renderer/node_modules/chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dependencies": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/vue-server-renderer/node_modules/hash-sum": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/hash-sum/-/hash-sum-1.0.2.tgz", + "integrity": "sha1-M7QHd3VMZDJXPBIMw4CLvRDUfwQ=" + }, + "node_modules/vue-server-renderer/node_modules/serialize-javascript": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-3.1.0.tgz", + "integrity": "sha512-JIJT1DGiWmIKhzRsG91aS6Ze4sFUrYbltlkg2onR5OrnNM02Kl/hnY/T4FN2omvyeBbQmMJv+K4cPOpGzOTFBg==", + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/vue-server-renderer/node_modules/source-map": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz", + "integrity": "sha1-dc449SvwczxafwwRjYEzSiu19BI=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/vue-server-renderer/node_modules/strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/vue-server-renderer/node_modules/supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/vue-style-loader": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/vue-style-loader/-/vue-style-loader-4.1.3.tgz", + "integrity": "sha512-sFuh0xfbtpRlKfm39ss/ikqs9AbKCoXZBpHeVZ8Tx650o0k0q/YCM7FRvigtxpACezfq6af+a7JeqVTWvncqDg==", + "dependencies": { + "hash-sum": "^1.0.2", + "loader-utils": "^1.0.2" + } + }, + "node_modules/vue-style-loader/node_modules/hash-sum": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/hash-sum/-/hash-sum-1.0.2.tgz", + "integrity": "sha1-M7QHd3VMZDJXPBIMw4CLvRDUfwQ=" + }, + "node_modules/vue-style-loader/node_modules/json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" + } + }, + "node_modules/vue-style-loader/node_modules/loader-utils": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", + "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", + "dependencies": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^1.0.1" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/vue-template-compiler": { + "version": "2.6.14", + "resolved": "https://registry.npmjs.org/vue-template-compiler/-/vue-template-compiler-2.6.14.tgz", + "integrity": "sha512-ODQS1SyMbjKoO1JBJZojSw6FE4qnh9rIpUZn2EUT86FKizx9uH5z6uXiIrm4/Nb/gwxTi/o17ZDEGWAXHvtC7g==", + "dependencies": { + "de-indent": "^1.0.2", + "he": "^1.1.0" + } + }, + "node_modules/vue-template-es2015-compiler": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/vue-template-es2015-compiler/-/vue-template-es2015-compiler-1.9.1.tgz", + "integrity": "sha512-4gDntzrifFnCEvyoO8PqyJDmguXgVPxKiIxrBKjIowvL9l+N66196+72XVYR8BBf1Uv1Fgt3bGevJ+sEmxfZzw==" + }, + "node_modules/vue-toastification": { + "version": "1.7.14", + "resolved": "https://registry.npmjs.org/vue-toastification/-/vue-toastification-1.7.14.tgz", + "integrity": "sha512-khZR8t3NWZ/JJ2MZxXLbesHrRJ8AKa75PY5Zq8yMifF9x8lHq8ljYkC0d2PD9yahooygQB5tcFyRDkbbIPx8hw==", + "peerDependencies": { + "vue": "^2.0.0" + } + }, + "node_modules/vuedraggable": { + "version": "2.24.3", + "resolved": "https://registry.npmjs.org/vuedraggable/-/vuedraggable-2.24.3.tgz", + "integrity": "sha512-6/HDXi92GzB+Hcs9fC6PAAozK1RLt1ewPTLjK0anTYguXLAeySDmcnqE8IC0xa7shvSzRjQXq3/+dsZ7ETGF3g==", + "dependencies": { + "sortablejs": "1.10.2" + } + }, + "node_modules/vuex": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/vuex/-/vuex-3.6.2.tgz", + "integrity": "sha512-ETW44IqCgBpVomy520DT5jf8n0zoCac+sxWnn+hMe/CzaSejb/eVw2YToiXYX+Ex/AuHHia28vWTq4goAexFbw==", + "peerDependencies": { + "vue": "^2.0.0" + } + }, + "node_modules/watchpack": { + "version": "1.7.5", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.7.5.tgz", + "integrity": "sha512-9P3MWk6SrKjHsGkLT2KHXdQ/9SNkyoJbabxnKOoJepsvJjJG8uYTR3yTPxPQvNDI3w4Nz1xnE0TLHK4RIVe/MQ==", + "dependencies": { + "graceful-fs": "^4.1.2", + "neo-async": "^2.5.0" + }, + "optionalDependencies": { + "chokidar": "^3.4.1", + "watchpack-chokidar2": "^2.0.1" + } + }, + "node_modules/watchpack-chokidar2": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/watchpack-chokidar2/-/watchpack-chokidar2-2.0.1.tgz", + "integrity": "sha512-nCFfBIPKr5Sh61s4LPpy1Wtfi0HE8isJ3d2Yb5/Ppw2P2B/3eVSEBjKfN0fmHJSK14+31KwMKmcrzs2GM4P0Ww==", + "optional": true, + "dependencies": { + "chokidar": "^2.1.8" + } + }, + "node_modules/watchpack-chokidar2/node_modules/anymatch": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "optional": true, + "dependencies": { + "micromatch": "^3.1.4", + "normalize-path": "^2.1.1" + } + }, + "node_modules/watchpack-chokidar2/node_modules/anymatch/node_modules/normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "optional": true, + "dependencies": { + "remove-trailing-separator": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/watchpack-chokidar2/node_modules/binary-extensions": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", + "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/watchpack-chokidar2/node_modules/braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "optional": true, + "dependencies": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/watchpack-chokidar2/node_modules/chokidar": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", + "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", + "deprecated": "Chokidar 2 does not receive security updates since 2019. Upgrade to chokidar 3 with 15x fewer dependencies", + "optional": true, + "dependencies": { + "anymatch": "^2.0.0", + "async-each": "^1.0.1", + "braces": "^2.3.2", + "glob-parent": "^3.1.0", + "inherits": "^2.0.3", + "is-binary-path": "^1.0.0", + "is-glob": "^4.0.0", + "normalize-path": "^3.0.0", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.2.1", + "upath": "^1.1.1" + }, + "optionalDependencies": { + "fsevents": "^1.2.7" + } + }, + "node_modules/watchpack-chokidar2/node_modules/define-property": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", + "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", + "optional": true, + "dependencies": { + "is-descriptor": "^1.0.2", + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/watchpack-chokidar2/node_modules/fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "optional": true, + "dependencies": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/watchpack-chokidar2/node_modules/fsevents": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", + "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", + "deprecated": "fsevents 1 will break on node v14+ and could be using insecure binaries. Upgrade to fsevents 2.", + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "dependencies": { + "bindings": "^1.5.0", + "nan": "^2.12.1" + }, + "engines": { + "node": ">= 4.0" + } + }, + "node_modules/watchpack-chokidar2/node_modules/glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "optional": true, + "dependencies": { + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + } + }, + "node_modules/watchpack-chokidar2/node_modules/glob-parent/node_modules/is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "optional": true, + "dependencies": { + "is-extglob": "^2.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/watchpack-chokidar2/node_modules/is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "optional": true, + "dependencies": { + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/watchpack-chokidar2/node_modules/is-binary-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", + "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", + "optional": true, + "dependencies": { + "binary-extensions": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/watchpack-chokidar2/node_modules/is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "optional": true, + "dependencies": { + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/watchpack-chokidar2/node_modules/is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "optional": true, + "dependencies": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/watchpack-chokidar2/node_modules/is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "optional": true, + "dependencies": { + "is-plain-object": "^2.0.4" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/watchpack-chokidar2/node_modules/is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "optional": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/watchpack-chokidar2/node_modules/is-number/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "optional": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/watchpack-chokidar2/node_modules/micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "optional": true, + "dependencies": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/watchpack-chokidar2/node_modules/micromatch/node_modules/extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "optional": true, + "dependencies": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/watchpack-chokidar2/node_modules/readdirp": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", + "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", + "optional": true, + "dependencies": { + "graceful-fs": "^4.1.11", + "micromatch": "^3.1.10", + "readable-stream": "^2.0.2" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/watchpack-chokidar2/node_modules/to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "optional": true, + "dependencies": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/watchpack-chokidar2/node_modules/upath": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", + "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==", + "optional": true, + "engines": { + "node": ">=4", + "yarn": "*" + } + }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=" + }, + "node_modules/webpack": { + "version": "4.46.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.46.0.tgz", + "integrity": "sha512-6jJuJjg8znb/xRItk7bkT0+Q7AHCYjjFnvKIWQPkNIOyRqoCGvkOs0ipeQzrqz4l5FtN5ZI/ukEHroeX/o1/5Q==", + "dependencies": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-module-context": "1.9.0", + "@webassemblyjs/wasm-edit": "1.9.0", + "@webassemblyjs/wasm-parser": "1.9.0", + "acorn": "^6.4.1", + "ajv": "^6.10.2", + "ajv-keywords": "^3.4.1", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^4.5.0", + "eslint-scope": "^4.0.3", + "json-parse-better-errors": "^1.0.2", + "loader-runner": "^2.4.0", + "loader-utils": "^1.2.3", + "memory-fs": "^0.4.1", + "micromatch": "^3.1.10", + "mkdirp": "^0.5.3", + "neo-async": "^2.6.1", + "node-libs-browser": "^2.2.1", + "schema-utils": "^1.0.0", + "tapable": "^1.1.3", + "terser-webpack-plugin": "^1.4.3", + "watchpack": "^1.7.4", + "webpack-sources": "^1.4.1" + }, + "bin": { + "webpack": "bin/webpack.js" + }, + "engines": { + "node": ">=6.11.5" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependenciesMeta": { + "webpack-cli": { + "optional": true + }, + "webpack-command": { + "optional": true + } + } + }, + "node_modules/webpack-bundle-analyzer": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/webpack-bundle-analyzer/-/webpack-bundle-analyzer-4.5.0.tgz", + "integrity": "sha512-GUMZlM3SKwS8Z+CKeIFx7CVoHn3dXFcUAjT/dcZQQmfSZGvitPfMob2ipjai7ovFFqPvTqkEZ/leL4O0YOdAYQ==", + "dependencies": { + "acorn": "^8.0.4", + "acorn-walk": "^8.0.0", + "chalk": "^4.1.0", + "commander": "^7.2.0", + "gzip-size": "^6.0.0", + "lodash": "^4.17.20", + "opener": "^1.5.2", + "sirv": "^1.0.7", + "ws": "^7.3.1" + }, + "bin": { + "webpack-bundle-analyzer": "lib/bin/analyzer.js" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/webpack-bundle-analyzer/node_modules/acorn": { + "version": "8.7.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.1.tgz", + "integrity": "sha512-Xx54uLJQZ19lKygFXOWsscKUbsBZW0CPykPhVQdhIeIwrbPmJzqeASDInc8nKBnp/JT6igTs82qPXz069H8I/A==", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/webpack-bundle-analyzer/node_modules/acorn-walk": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", + "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/webpack-bundle-analyzer/node_modules/commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "engines": { + "node": ">= 10" + } + }, + "node_modules/webpack-bundle-analyzer/node_modules/ws": { + "version": "7.5.7", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.7.tgz", + "integrity": "sha512-KMvVuFzpKBuiIXW3E4u3mySRO2/mCHSyZDJQM5NQ9Q9KHWHWh0NHgfbRMLLrceUK5qAL4ytALJbpRMjixFZh8A==", + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/webpack-dev-middleware": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-4.3.0.tgz", + "integrity": "sha512-PjwyVY95/bhBh6VUqt6z4THplYcsvQ8YNNBTBM873xLVmw8FLeALn0qurHbs9EmcfhzQis/eoqypSnZeuUz26w==", + "dependencies": { + "colorette": "^1.2.2", + "mem": "^8.1.1", + "memfs": "^3.2.2", + "mime-types": "^2.1.30", + "range-parser": "^1.2.1", + "schema-utils": "^3.0.0" + }, + "engines": { + "node": ">= v10.23.3" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^4.0.0 || ^5.0.0" + } + }, + "node_modules/webpack-hot-middleware": { + "version": "2.25.1", + "resolved": "https://registry.npmjs.org/webpack-hot-middleware/-/webpack-hot-middleware-2.25.1.tgz", + "integrity": "sha512-Koh0KyU/RPYwel/khxbsDz9ibDivmUbrRuKSSQvW42KSDdO4w23WI3SkHpSUKHE76LrFnnM/L7JCrpBwu8AXYw==", + "dependencies": { + "ansi-html-community": "0.0.8", + "html-entities": "^2.1.0", + "querystring": "^0.2.0", + "strip-ansi": "^6.0.0" + } + }, + "node_modules/webpack-node-externals": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/webpack-node-externals/-/webpack-node-externals-3.0.0.tgz", + "integrity": "sha512-LnL6Z3GGDPht/AigwRh2dvL9PQPFQ8skEpVrWZXLWBYmqcaojHNN0onvHzie6rq7EWKrrBfPYqNEzTJgiwEQDQ==", + "engines": { + "node": ">=6" + } + }, + "node_modules/webpack-sources": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz", + "integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==", + "dependencies": { + "source-list-map": "^2.0.0", + "source-map": "~0.6.1" + } + }, + "node_modules/webpack/node_modules/acorn": { + "version": "6.4.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.2.tgz", + "integrity": "sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/webpack/node_modules/braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dependencies": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/webpack/node_modules/cacache": { + "version": "12.0.4", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-12.0.4.tgz", + "integrity": "sha512-a0tMB40oefvuInr4Cwb3GerbL9xTj1D5yg0T5xrjGCGyfvbxseIXX7BAO/u/hIXdafzOI5JC3wDwHyf24buOAQ==", + "dependencies": { + "bluebird": "^3.5.5", + "chownr": "^1.1.1", + "figgy-pudding": "^3.5.1", + "glob": "^7.1.4", + "graceful-fs": "^4.1.15", + "infer-owner": "^1.0.3", + "lru-cache": "^5.1.1", + "mississippi": "^3.0.0", + "mkdirp": "^0.5.1", + "move-concurrently": "^1.0.1", + "promise-inflight": "^1.0.1", + "rimraf": "^2.6.3", + "ssri": "^6.0.1", + "unique-filename": "^1.1.1", + "y18n": "^4.0.0" + } + }, + "node_modules/webpack/node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + }, + "node_modules/webpack/node_modules/define-property": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", + "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", + "dependencies": { + "is-descriptor": "^1.0.2", + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/webpack/node_modules/fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dependencies": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/webpack/node_modules/find-cache-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", + "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", + "dependencies": { + "commondir": "^1.0.1", + "make-dir": "^2.0.0", + "pkg-dir": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/webpack/node_modules/find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dependencies": { + "locate-path": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/webpack/node_modules/is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dependencies": { + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/webpack/node_modules/is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dependencies": { + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/webpack/node_modules/is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dependencies": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/webpack/node_modules/is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dependencies": { + "is-plain-object": "^2.0.4" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/webpack/node_modules/is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/webpack/node_modules/is-number/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/webpack/node_modules/is-wsl": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", + "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=", + "engines": { + "node": ">=4" + } + }, + "node_modules/webpack/node_modules/json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" + } + }, + "node_modules/webpack/node_modules/loader-runner": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.4.0.tgz", + "integrity": "sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw==", + "engines": { + "node": ">=4.3.0 <5.0.0 || >=5.10" + } + }, + "node_modules/webpack/node_modules/loader-utils": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", + "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", + "dependencies": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^1.0.1" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/webpack/node_modules/locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dependencies": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/webpack/node_modules/make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "dependencies": { + "pify": "^4.0.1", + "semver": "^5.6.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/webpack/node_modules/memory-fs": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz", + "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=", + "dependencies": { + "errno": "^0.1.3", + "readable-stream": "^2.0.1" + } + }, + "node_modules/webpack/node_modules/micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dependencies": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/webpack/node_modules/micromatch/node_modules/extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dependencies": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/webpack/node_modules/p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dependencies": { + "p-limit": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/webpack/node_modules/path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "engines": { + "node": ">=4" + } + }, + "node_modules/webpack/node_modules/pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "engines": { + "node": ">=6" + } + }, + "node_modules/webpack/node_modules/pkg-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "dependencies": { + "find-up": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/webpack/node_modules/schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "dependencies": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + }, + "engines": { + "node": ">= 4" + } + }, + "node_modules/webpack/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/webpack/node_modules/serialize-javascript": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz", + "integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==", + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/webpack/node_modules/ssri": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.2.tgz", + "integrity": "sha512-cepbSq/neFK7xB6A50KHN0xHDotYzq58wWCa5LeWqnPrHG8GzfEjO/4O8kpmcGW+oaxkvhEJCWgbgNk4/ZV93Q==", + "dependencies": { + "figgy-pudding": "^3.5.1" + } + }, + "node_modules/webpack/node_modules/terser-webpack-plugin": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.4.5.tgz", + "integrity": "sha512-04Rfe496lN8EYruwi6oPQkG0vo8C+HT49X687FZnpPF0qMAIHONI6HEXYPKDOE8e5HjXTyKfqRd/agHtH0kOtw==", + "dependencies": { + "cacache": "^12.0.2", + "find-cache-dir": "^2.1.0", + "is-wsl": "^1.1.0", + "schema-utils": "^1.0.0", + "serialize-javascript": "^4.0.0", + "source-map": "^0.6.1", + "terser": "^4.1.2", + "webpack-sources": "^1.4.0", + "worker-farm": "^1.7.0" + }, + "engines": { + "node": ">= 6.9.0" + }, + "peerDependencies": { + "webpack": "^4.0.0" + } + }, + "node_modules/webpack/node_modules/to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "dependencies": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/webpack/node_modules/y18n": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==" + }, + "node_modules/webpackbar": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/webpackbar/-/webpackbar-4.0.0.tgz", + "integrity": "sha512-k1qRoSL/3BVuINzngj09nIwreD8wxV4grcuhHTD8VJgUbGcy8lQSPqv+bM00B7F+PffwIsQ8ISd4mIwRbr23eQ==", + "dependencies": { + "ansi-escapes": "^4.2.1", + "chalk": "^2.4.2", + "consola": "^2.10.0", + "figures": "^3.0.0", + "pretty-time": "^1.1.0", + "std-env": "^2.2.1", + "text-table": "^0.2.0", + "wrap-ansi": "^6.0.0" + }, + "engines": { + "node": ">= 8.0.0" + }, + "peerDependencies": { + "webpack": "^3.0.0 || ^4.0.0" + } + }, + "node_modules/webpackbar/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/webpackbar/node_modules/chalk/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/webpackbar/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/webpackbar/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" + }, + "node_modules/webpackbar/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "engines": { + "node": ">=4" + } + }, + "node_modules/webpackbar/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/webpackbar/node_modules/wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "dependencies": { + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/widest-line": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", + "integrity": "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==", + "dependencies": { + "string-width": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/workbox-cdn": { + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/workbox-cdn/-/workbox-cdn-5.1.4.tgz", + "integrity": "sha512-04gM3mi8QGutokkSaA9xunVfjURnLbo9TTWyi8+pSDCEW5cD8u5GbJiliLK1vB9CShk/9OY1UDfW+XcmD+d6KQ==", + "dev": true + }, + "node_modules/worker-farm": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/worker-farm/-/worker-farm-1.7.0.tgz", + "integrity": "sha512-rvw3QTZc8lAxyVrqcSGVm5yP/IJ2UcB3U0graE3LCFoZ0Yn2x4EoVSqJKdB/T5M+FLcRPjz4TDacRf3OCfNUzw==", + "dependencies": { + "errno": "~0.1.7" + } + }, + "node_modules/worker-loader": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/worker-loader/-/worker-loader-2.0.0.tgz", + "integrity": "sha512-tnvNp4K3KQOpfRnD20m8xltE3eWh89Ye+5oj7wXEEHKac1P4oZ6p9oTj8/8ExqoSBnk9nu5Pr4nKfQ1hn2APJw==", + "dependencies": { + "loader-utils": "^1.0.0", + "schema-utils": "^0.4.0" + }, + "engines": { + "node": ">= 6.9.0 || >= 8.9.0" + }, + "peerDependencies": { + "webpack": "^3.0.0 || ^4.0.0-alpha.0 || ^4.0.0" + } + }, + "node_modules/worker-loader/node_modules/json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" + } + }, + "node_modules/worker-loader/node_modules/loader-utils": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", + "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", + "dependencies": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^1.0.1" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/worker-loader/node_modules/schema-utils": { + "version": "0.4.7", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.4.7.tgz", + "integrity": "sha512-v/iwU6wvwGK8HbU9yi3/nhGzP0yGSuhQMzL6ySiec1FSrZZDkhm4noOSWzrNFo/jEc+SJY6jRTwuwbSXJPDUnQ==", + "dependencies": { + "ajv": "^6.1.0", + "ajv-keywords": "^3.1.0" + }, + "engines": { + "node": ">= 4" + } + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "node_modules/write-file-atomic": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.3.tgz", + "integrity": "sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==", + "dependencies": { + "graceful-fs": "^4.1.11", + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.2" + } + }, + "node_modules/write-json-file": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/write-json-file/-/write-json-file-2.3.0.tgz", + "integrity": "sha1-K2TIozAE1UuGmMdtWFp3zrYdoy8=", + "dependencies": { + "detect-indent": "^5.0.0", + "graceful-fs": "^4.1.2", + "make-dir": "^1.0.0", + "pify": "^3.0.0", + "sort-keys": "^2.0.0", + "write-file-atomic": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/write-json-file/node_modules/is-plain-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", + "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/write-json-file/node_modules/make-dir": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz", + "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==", + "dependencies": { + "pify": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/write-json-file/node_modules/pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "engines": { + "node": ">=4" + } + }, + "node_modules/write-json-file/node_modules/sort-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-2.0.0.tgz", + "integrity": "sha1-ZYU1WEhh7JfXMNbPQYIuH1ZoQSg=", + "dependencies": { + "is-plain-obj": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/ws": { + "version": "8.2.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.2.3.tgz", + "integrity": "sha512-wBuoj1BDpC6ZQ1B7DWQBYVLphPWkm8i9Y0/3YdHjHKHiohOJ1ws+3OccDWtH+PoC9DZD5WOTrJvNbWvjS6JWaA==", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xmlhttprequest-ssl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.0.0.tgz", + "integrity": "sha512-QKxVRxiRACQcVuQEYFsI1hhkrMlrXHPegbbd1yn9UHOmRxY+si12nQYzri3vbzt8VdTTRviqcKxcyllFas5z2A==", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "engines": { + "node": ">=0.4" + } + }, + "node_modules/xxhashjs": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/xxhashjs/-/xxhashjs-0.2.2.tgz", + "integrity": "sha512-AkTuIuVTET12tpsVIQo+ZU6f/qDmKuRUcjaqR+OIvm+aCBsZ95i7UVY5WJ9TMsSaZ0DA2WxoZ4acu0sPH+OKAw==", + "dependencies": { + "cuint": "^0.2.2" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" + }, + "node_modules/yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/yargs": { + "version": "17.5.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.5.1.tgz", + "integrity": "sha512-t6YAJcxDkNX7NFYiVtKvWUz8l+PaKTLiL63mJYWR2GnHq2gjEWISzsLp9wg3aY36dY1j+gfIEL3pIF+XlJJfbA==", + "dev": true, + "dependencies": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.0.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.0.1.tgz", + "integrity": "sha512-9BK1jFpLzJROCI5TzwZL/TU4gqjK5xiHV/RfWLOahrjAko/e4DJkRDZQXfvqAsiZzzYhgAzbgz6lg48jcm4GLg==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/ylru": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/ylru/-/ylru-1.3.2.tgz", + "integrity": "sha512-RXRJzMiK6U2ye0BlGGZnmpwJDPgakn6aNQ0A7gHRbD4I0uvK4TW6UqkK1V0pp9jskjJBAXd3dRrbzWkqJ+6cxA==", + "dev": true, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + } + }, "dependencies": { "@ampproject/remapping": { "version": "2.2.0", @@ -2897,12 +20293,14 @@ "ajv-errors": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/ajv-errors/-/ajv-errors-1.0.1.tgz", - "integrity": "sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ==" + "integrity": "sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ==", + "requires": {} }, "ajv-keywords": { "version": "3.5.2", "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==" + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "requires": {} }, "alphanum-sort": { "version": "1.0.2", @@ -4302,7 +21700,6 @@ "version": "5.2.7", "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-5.2.7.tgz", "integrity": "sha512-Q7mOvpBNBG7YrVGMxRxcBJZFL75o+cH2abNASdibkj/fffYD8qWbInZrD0S9ccI6vZclF3DsHE7njGlLtaHbhg==", - "dev": true, "requires": { "icss-utils": "^5.1.0", "loader-utils": "^2.0.0", @@ -6179,7 +23576,7 @@ "version": "5.1.0", "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", - "dev": true + "requires": {} }, "ieee754": { "version": "1.2.1", @@ -7040,6 +24437,11 @@ "object-visit": "^1.0.0" } }, + "marked": { + "version": "4.0.17", + "resolved": "https://registry.npmjs.org/marked/-/marked-4.0.17.tgz", + "integrity": "sha512-Wfk0ATOK5iPxM4ptrORkFemqroz0ZDxp5MWfYA7H/F+wO17NRWV5Ypxi6p3g2Xmw2bKeiYOl6oVnLHKxBA0VhA==" + }, "marks-pane": { "version": "1.0.9", "resolved": "https://registry.npmjs.org/marks-pane/-/marks-pane-1.0.9.tgz", @@ -8086,7 +25488,6 @@ "version": "8.4.14", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.14.tgz", "integrity": "sha512-E398TUmfAYFPBSdzgeieK2Y1+1cpdxJx8yXbK/m57nRhKSmk1GB2tO4lbLBtlkfPQTDKfe4Xqv1ASWPpayPEig==", - "dev": true, "requires": { "nanoid": "^3.3.4", "picocolors": "^1.0.0", @@ -9219,13 +26620,12 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz", "integrity": "sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==", - "dev": true + "requires": {} }, "postcss-modules-local-by-default": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.0.tgz", "integrity": "sha512-sT7ihtmGSF9yhm6ggikHdV0hlziDTX7oFoXtuVWeDd3hHObNkcHRo9V3yg7vCAY7cONyxJC/XXCmmiHHcvX7bQ==", - "dev": true, "requires": { "icss-utils": "^5.0.0", "postcss-selector-parser": "^6.0.2", @@ -9236,7 +26636,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.0.0.tgz", "integrity": "sha512-hncihwFA2yPath8oZ15PZqvWGkWf+XUfQgUGamS4LqoP1anQLOsOJw0vr7J7IwLpoY9fatA2qiGUGmuZL0Iqlg==", - "dev": true, "requires": { "postcss-selector-parser": "^6.0.4" } @@ -9245,7 +26644,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz", "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==", - "dev": true, "requires": { "icss-utils": "^5.0.0" } @@ -9263,7 +26661,8 @@ "version": "8.0.1", "resolved": "https://registry.npmjs.org/postcss-nesting/-/postcss-nesting-8.0.1.tgz", "integrity": "sha512-cHPNhW5VvRQjszFDxmy16mis9qFQqQLBNw6KVmueLqqE3M182ZAk9+QoxGqbGVryzLVhannw2B5Yhosqq522fA==", - "dev": true + "dev": true, + "requires": {} }, "postcss-normalize-charset": { "version": "4.0.1", @@ -11105,8 +28504,7 @@ "source-map-js": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", - "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", - "dev": true + "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==" }, "source-map-resolve": { "version": "0.5.3", @@ -11256,6 +28654,14 @@ "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz", "integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=" }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + }, "string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", @@ -11286,14 +28692,6 @@ "es-abstract": "^1.19.5" } }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - } - }, "strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", @@ -11729,7 +29127,8 @@ "time-fix-plugin": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/time-fix-plugin/-/time-fix-plugin-2.0.7.tgz", - "integrity": "sha512-uVFet1LQToeUX0rTcSiYVYVoGuBpc8gP/2jnlUzuHMHe+gux6XLsNzxLUweabMwiUj5ejhoIMsUI55nVSEa/Vw==" + "integrity": "sha512-uVFet1LQToeUX0rTcSiYVYVoGuBpc8gP/2jnlUzuHMHe+gux6XLsNzxLUweabMwiUj5ejhoIMsUI55nVSEa/Vw==", + "requires": {} }, "timers-browserify": { "version": "2.0.12", @@ -12410,7 +29809,8 @@ "vue-toastification": { "version": "1.7.14", "resolved": "https://registry.npmjs.org/vue-toastification/-/vue-toastification-1.7.14.tgz", - "integrity": "sha512-khZR8t3NWZ/JJ2MZxXLbesHrRJ8AKa75PY5Zq8yMifF9x8lHq8ljYkC0d2PD9yahooygQB5tcFyRDkbbIPx8hw==" + "integrity": "sha512-khZR8t3NWZ/JJ2MZxXLbesHrRJ8AKa75PY5Zq8yMifF9x8lHq8ljYkC0d2PD9yahooygQB5tcFyRDkbbIPx8hw==", + "requires": {} }, "vuedraggable": { "version": "2.24.3", @@ -12423,7 +29823,8 @@ "vuex": { "version": "3.6.2", "resolved": "https://registry.npmjs.org/vuex/-/vuex-3.6.2.tgz", - "integrity": "sha512-ETW44IqCgBpVomy520DT5jf8n0zoCac+sxWnn+hMe/CzaSejb/eVw2YToiXYX+Ex/AuHHia28vWTq4goAexFbw==" + "integrity": "sha512-ETW44IqCgBpVomy520DT5jf8n0zoCac+sxWnn+hMe/CzaSejb/eVw2YToiXYX+Ex/AuHHia28vWTq4goAexFbw==", + "requires": {} }, "watchpack": { "version": "1.7.5", @@ -13075,7 +30476,8 @@ "ws": { "version": "7.5.7", "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.7.tgz", - "integrity": "sha512-KMvVuFzpKBuiIXW3E4u3mySRO2/mCHSyZDJQM5NQ9Q9KHWHWh0NHgfbRMLLrceUK5qAL4ytALJbpRMjixFZh8A==" + "integrity": "sha512-KMvVuFzpKBuiIXW3E4u3mySRO2/mCHSyZDJQM5NQ9Q9KHWHWh0NHgfbRMLLrceUK5qAL4ytALJbpRMjixFZh8A==", + "requires": {} } } }, @@ -13348,7 +30750,8 @@ "ws": { "version": "8.2.3", "resolved": "https://registry.npmjs.org/ws/-/ws-8.2.3.tgz", - "integrity": "sha512-wBuoj1BDpC6ZQ1B7DWQBYVLphPWkm8i9Y0/3YdHjHKHiohOJ1ws+3OccDWtH+PoC9DZD5WOTrJvNbWvjS6JWaA==" + "integrity": "sha512-wBuoj1BDpC6ZQ1B7DWQBYVLphPWkm8i9Y0/3YdHjHKHiohOJ1ws+3OccDWtH+PoC9DZD5WOTrJvNbWvjS6JWaA==", + "requires": {} }, "xmlhttprequest-ssl": { "version": "2.0.0", diff --git a/client/package.json b/client/package.json index 21179693a..7f0e5dd28 100644 --- a/client/package.json +++ b/client/package.json @@ -20,6 +20,7 @@ "epubjs": "^0.3.88", "hls.js": "^1.0.7", "libarchive.js": "^1.3.0", + "marked": "^4.0.17", "nuxt": "^2.15.8", "nuxt-socket-io": "^1.1.18", "trix": "^1.3.1", diff --git a/client/static/libs/marked/LICENSE b/client/static/libs/marked/LICENSE new file mode 100644 index 000000000..17c0feb87 --- /dev/null +++ b/client/static/libs/marked/LICENSE @@ -0,0 +1,44 @@ +# License information + +## Contribution License Agreement + +If you contribute code to this project, you are implicitly allowing your code +to be distributed under the MIT license. You are also implicitly verifying that +all code is your original work. `` + +## Marked + +Copyright (c) 2018+, MarkedJS (https://github.com/markedjs/) +Copyright (c) 2011-2018, Christopher Jeffrey (https://github.com/chjj/) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +## Markdown + +Copyright © 2004, John Gruber +http://daringfireball.net/ +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. +* Neither the name “Markdown” nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + +This software is provided by the copyright holders and contributors “as is” and any express or implied warranties, including, but not limited to, the implied warranties of merchantability and fitness for a particular purpose are disclaimed. In no event shall the copyright owner or contributors be liable for any direct, indirect, incidental, special, exemplary, or consequential damages (including, but not limited to, procurement of substitute goods or services; loss of use, data, or profits; or business interruption) however caused and on any theory of liability, whether in contract, strict liability, or tort (including negligence or otherwise) arising in any way out of the use of this software, even if advised of the possibility of such damage. \ No newline at end of file diff --git a/client/static/libs/marked/index.js b/client/static/libs/marked/index.js new file mode 100644 index 000000000..ce0e6525a --- /dev/null +++ b/client/static/libs/marked/index.js @@ -0,0 +1,6 @@ +/** + * marked - a markdown parser + * Copyright (c) 2011-2022, Christopher Jeffrey. (MIT Licensed) + * https://github.com/markedjs/marked + */ + !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).marked={})}(this,function(r){"use strict";function i(e,t){for(var u=0;ue.length)&&(t=e.length);for(var u=0,n=new Array(t);u=e.length?{done:!0}:{done:!1,value:e[u++]}};throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}function e(){return{baseUrl:null,breaks:!1,extensions:null,gfm:!0,headerIds:!0,headerPrefix:"",highlight:null,langPrefix:"language-",mangle:!0,pedantic:!1,renderer:null,sanitize:!1,sanitizer:null,silent:!1,smartLists:!1,smartypants:!1,tokenizer:null,walkTokens:null,xhtml:!1}}r.defaults=e();function u(e){return t[e]}var n=/[&<>"']/,l=/[&<>"']/g,a=/[<>"']|&(?!#?\w+;)/,o=/[<>"']|&(?!#?\w+;)/g,t={"&":"&","<":"<",">":">",'"':""","'":"'"};function D(e,t){if(t){if(n.test(e))return e.replace(l,u)}else if(a.test(e))return e.replace(o,u);return e}var c=/&(#(?:\d+)|(?:#x[0-9A-Fa-f]+)|(?:\w+));?/gi;function x(e){return e.replace(c,function(e,t){return"colon"===(t=t.toLowerCase())?":":"#"===t.charAt(0)?"x"===t.charAt(1)?String.fromCharCode(parseInt(t.substring(2),16)):String.fromCharCode(+t.substring(1)):""})}var h=/(^|[^\[])\^/g;function p(u,e){u="string"==typeof u?u:u.source,e=e||"";var n={replace:function(e,t){return t=(t=t.source||t).replace(h,"$1"),u=u.replace(e,t),n},getRegex:function(){return new RegExp(u,e)}};return n}var f=/[^\w:]/g,Z=/^$|^[a-z][a-z0-9+.-]*:|^[?#]/i;function g(e,t,u){if(e){try{n=decodeURIComponent(x(u)).replace(f,"").toLowerCase()}catch(e){return null}if(0===n.indexOf("javascript:")||0===n.indexOf("vbscript:")||0===n.indexOf("data:"))return null}var n;t&&!Z.test(u)&&(e=u,F[" "+(n=t)]||(O.test(n)?F[" "+n]=n+"/":F[" "+n]=k(n,"/",!0)),t=-1===(n=F[" "+n]).indexOf(":"),u="//"===e.substring(0,2)?t?e:n.replace(q,"$1")+e:"/"===e.charAt(0)?t?e:n.replace(L,"$1")+e:n+e);try{u=encodeURI(u).replace(/%25/g,"%")}catch(e){return null}return u}var F={},O=/^[^:]+:\/*[^/]*$/,q=/^([^:]+:)[\s\S]*$/,L=/^([^:]+:\/*[^/]*)[\s\S]*$/;var A={exec:function(){}};function d(e){for(var t,u,n=1;nt)u.splice(t);else for(;u.length>=1,e+=e;return u+e}function B(e,t,u,n){var r=t.href,t=t.title?D(t.title):null,i=e[1].replace(/\\([\[\]])/g,"$1");return"!"!==e[0].charAt(0)?(n.state.inLink=!0,e={type:"link",raw:u,href:r,title:t,text:i,tokens:n.inlineTokens(i,[])},n.state.inLink=!1,e):{type:"image",raw:u,href:r,title:t,text:D(i)}}var w=function(){function e(e){this.options=e||r.defaults}var t=e.prototype;return t.space=function(e){e=this.rules.block.newline.exec(e);if(e&&0=u.length?e.slice(u.length):e}).join("\n")}(t=e[0],e[3]||""),{type:"code",raw:t,lang:e[2]&&e[2].trim(),text:u}},t.heading=function(e){var t,u,e=this.rules.block.heading.exec(e);if(e)return t=e[2].trim(),/#$/.test(t)&&(u=k(t,"#"),!this.options.pedantic&&u&&!/ $/.test(u)||(t=u.trim())),u={type:"heading",raw:e[0],depth:e[1].length,text:t,tokens:[]},this.lexer.inline(u.text,u.tokens),u},t.hr=function(e){e=this.rules.block.hr.exec(e);if(e)return{type:"hr",raw:e[0]}},t.blockquote=function(e){var t,e=this.rules.block.blockquote.exec(e);if(e)return t=e[0].replace(/^ *>[ \t]?/gm,""),{type:"blockquote",raw:e[0],tokens:this.lexer.blockTokens(t,[]),text:t}},t.list=function(e){var t=this.rules.block.list.exec(e);if(t){var u,n,r,i,s,l,a,o,D,c,h,p=1<(g=t[1].trim()).length,f={type:"list",raw:"",ordered:p,start:p?+g.slice(0,-1):"",loose:!1,items:[]},g=p?"\\d{1,9}\\"+g.slice(-1):"\\"+g;this.options.pedantic&&(g=p?g:"[*+-]");for(var F=new RegExp("^( {0,3}"+g+")((?:[\t ][^\\n]*)?(?:\\n|$))");e&&(h=!1,t=F.exec(e))&&!this.rules.block.hr.test(e);){if(u=t[0],e=e.substring(u.length),a=t[2].split("\n",1)[0],o=e.split("\n",1)[0],this.options.pedantic?(i=2,c=a.trimLeft()):(i=t[2].search(/[^ ]/),c=a.slice(i=4=i||!a.trim())c+="\n"+a.slice(i);else{if(s)break;c+="\n"+a}s||a.trim()||(s=!0),u+=D+"\n",e=e.substring(D.length+1)}f.loose||(l?f.loose=!0:/\n *\n *$/.test(u)&&(l=!0)),this.options.gfm&&(n=/^\[[ xX]\] /.exec(c))&&(r="[ ] "!==n[0],c=c.replace(/^\[[ xX]\] +/,"")),f.items.push({type:"list_item",raw:u,task:!!n,checked:r,loose:!1,text:c}),f.raw+=u}f.items[f.items.length-1].raw=u.trimRight(),f.items[f.items.length-1].text=c.trimRight(),f.raw=f.raw.trimRight();for(var k=f.items.length,E=0;E/i.test(e[0])&&(this.lexer.state.inLink=!1),!this.lexer.state.inRawBlock&&/^<(pre|code|kbd|script)(\s|>)/i.test(e[0])?this.lexer.state.inRawBlock=!0:this.lexer.state.inRawBlock&&/^<\/(pre|code|kbd|script)(\s|>)/i.test(e[0])&&(this.lexer.state.inRawBlock=!1),{type:this.options.sanitize?"text":"html",raw:e[0],inLink:this.lexer.state.inLink,inRawBlock:this.lexer.state.inRawBlock,text:this.options.sanitize?this.options.sanitizer?this.options.sanitizer(e[0]):D(e[0]):e[0]}},t.link=function(e){e=this.rules.inline.link.exec(e);if(e){var t=e[2].trim();if(!this.options.pedantic&&/^$/.test(t))return;var u=k(t.slice(0,-1),"\\");if((t.length-u.length)%2==0)return}else{u=function(e,t){if(-1===e.indexOf(t[1]))return-1;for(var u=e.length,n=0,r=0;r$/.test(t)?u.slice(1):u.slice(1,-1):u)&&u.replace(this.rules.inline._escapes,"$1"),title:r&&r.replace(this.rules.inline._escapes,"$1")},e[0],this.lexer)}},t.reflink=function(e,t){var u;if((u=this.rules.inline.reflink.exec(e))||(u=this.rules.inline.nolink.exec(e)))return(e=t[(e=(u[2]||u[1]).replace(/\s+/g," ")).toLowerCase()])&&e.href?B(u,e,u[0],this.lexer):{type:"text",raw:t=u[0].charAt(0),text:t}},t.emStrong=function(e,t,u){void 0===u&&(u="");var n=this.rules.inline.emStrong.lDelim.exec(e);if(n&&(!n[3]||!u.match(/(?:[0-9A-Za-z\xAA\xB2\xB3\xB5\xB9\xBA\xBC-\xBE\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u048A-\u052F\u0531-\u0556\u0559\u0560-\u0588\u05D0-\u05EA\u05EF-\u05F2\u0620-\u064A\u0660-\u0669\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07C0-\u07EA\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u0858\u0860-\u086A\u0870-\u0887\u0889-\u088E\u08A0-\u08C9\u0904-\u0939\u093D\u0950\u0958-\u0961\u0966-\u096F\u0971-\u0980\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09E6-\u09F1\u09F4-\u09F9\u09FC\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A59-\u0A5C\u0A5E\u0A66-\u0A6F\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0AE6-\u0AEF\u0AF9\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C\u0B5D\u0B5F-\u0B61\u0B66-\u0B6F\u0B71-\u0B77\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0\u0BE6-\u0BF2\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D\u0C58-\u0C5A\u0C5D\u0C60\u0C61\u0C66-\u0C6F\u0C78-\u0C7E\u0C80\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDD\u0CDE\u0CE0\u0CE1\u0CE6-\u0CEF\u0CF1\u0CF2\u0D04-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D\u0D4E\u0D54-\u0D56\u0D58-\u0D61\u0D66-\u0D78\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0DE6-\u0DEF\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E46\u0E50-\u0E59\u0E81\u0E82\u0E84\u0E86-\u0E8A\u0E8C-\u0EA3\u0EA5\u0EA7-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6\u0ED0-\u0ED9\u0EDC-\u0EDF\u0F00\u0F20-\u0F33\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A\u103F-\u1049\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081\u108E\u1090-\u1099\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u1369-\u137C\u1380-\u138F\u13A0-\u13F5\u13F8-\u13FD\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F8\u1700-\u1711\u171F-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7\u17DC\u17E0-\u17E9\u17F0-\u17F9\u1810-\u1819\u1820-\u1878\u1880-\u1884\u1887-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191E\u1946-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u19D0-\u19DA\u1A00-\u1A16\u1A20-\u1A54\u1A80-\u1A89\u1A90-\u1A99\u1AA7\u1B05-\u1B33\u1B45-\u1B4C\u1B50-\u1B59\u1B83-\u1BA0\u1BAE-\u1BE5\u1C00-\u1C23\u1C40-\u1C49\u1C4D-\u1C7D\u1C80-\u1C88\u1C90-\u1CBA\u1CBD-\u1CBF\u1CE9-\u1CEC\u1CEE-\u1CF3\u1CF5\u1CF6\u1CFA\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2070\u2071\u2074-\u2079\u207F-\u2089\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2150-\u2189\u2460-\u249B\u24EA-\u24FF\u2776-\u2793\u2C00-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3\u2CFD\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2E2F\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303C\u3041-\u3096\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312F\u3131-\u318E\u3192-\u3195\u31A0-\u31BF\u31F0-\u31FF\u3220-\u3229\u3248-\u324F\u3251-\u325F\u3280-\u3289\u32B1-\u32BF\u3400-\u4DBF\u4E00-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA62B\uA640-\uA66E\uA67F-\uA69D\uA6A0-\uA6EF\uA717-\uA71F\uA722-\uA788\uA78B-\uA7CA\uA7D0\uA7D1\uA7D3\uA7D5-\uA7D9\uA7F2-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA830-\uA835\uA840-\uA873\uA882-\uA8B3\uA8D0-\uA8D9\uA8F2-\uA8F7\uA8FB\uA8FD\uA8FE\uA900-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF-\uA9D9\uA9E0-\uA9E4\uA9E6-\uA9FE\uAA00-\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA50-\uAA59\uAA60-\uAA76\uAA7A\uAA7E-\uAAAF\uAAB1\uAAB5\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB69\uAB70-\uABE2\uABF0-\uABF9\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF10-\uFF19\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]|\uD800[\uDC00-\uDC0B\uDC0D-\uDC26\uDC28-\uDC3A\uDC3C\uDC3D\uDC3F-\uDC4D\uDC50-\uDC5D\uDC80-\uDCFA\uDD07-\uDD33\uDD40-\uDD78\uDD8A\uDD8B\uDE80-\uDE9C\uDEA0-\uDED0\uDEE1-\uDEFB\uDF00-\uDF23\uDF2D-\uDF4A\uDF50-\uDF75\uDF80-\uDF9D\uDFA0-\uDFC3\uDFC8-\uDFCF\uDFD1-\uDFD5]|\uD801[\uDC00-\uDC9D\uDCA0-\uDCA9\uDCB0-\uDCD3\uDCD8-\uDCFB\uDD00-\uDD27\uDD30-\uDD63\uDD70-\uDD7A\uDD7C-\uDD8A\uDD8C-\uDD92\uDD94\uDD95\uDD97-\uDDA1\uDDA3-\uDDB1\uDDB3-\uDDB9\uDDBB\uDDBC\uDE00-\uDF36\uDF40-\uDF55\uDF60-\uDF67\uDF80-\uDF85\uDF87-\uDFB0\uDFB2-\uDFBA]|\uD802[\uDC00-\uDC05\uDC08\uDC0A-\uDC35\uDC37\uDC38\uDC3C\uDC3F-\uDC55\uDC58-\uDC76\uDC79-\uDC9E\uDCA7-\uDCAF\uDCE0-\uDCF2\uDCF4\uDCF5\uDCFB-\uDD1B\uDD20-\uDD39\uDD80-\uDDB7\uDDBC-\uDDCF\uDDD2-\uDE00\uDE10-\uDE13\uDE15-\uDE17\uDE19-\uDE35\uDE40-\uDE48\uDE60-\uDE7E\uDE80-\uDE9F\uDEC0-\uDEC7\uDEC9-\uDEE4\uDEEB-\uDEEF\uDF00-\uDF35\uDF40-\uDF55\uDF58-\uDF72\uDF78-\uDF91\uDFA9-\uDFAF]|\uD803[\uDC00-\uDC48\uDC80-\uDCB2\uDCC0-\uDCF2\uDCFA-\uDD23\uDD30-\uDD39\uDE60-\uDE7E\uDE80-\uDEA9\uDEB0\uDEB1\uDF00-\uDF27\uDF30-\uDF45\uDF51-\uDF54\uDF70-\uDF81\uDFB0-\uDFCB\uDFE0-\uDFF6]|\uD804[\uDC03-\uDC37\uDC52-\uDC6F\uDC71\uDC72\uDC75\uDC83-\uDCAF\uDCD0-\uDCE8\uDCF0-\uDCF9\uDD03-\uDD26\uDD36-\uDD3F\uDD44\uDD47\uDD50-\uDD72\uDD76\uDD83-\uDDB2\uDDC1-\uDDC4\uDDD0-\uDDDA\uDDDC\uDDE1-\uDDF4\uDE00-\uDE11\uDE13-\uDE2B\uDE80-\uDE86\uDE88\uDE8A-\uDE8D\uDE8F-\uDE9D\uDE9F-\uDEA8\uDEB0-\uDEDE\uDEF0-\uDEF9\uDF05-\uDF0C\uDF0F\uDF10\uDF13-\uDF28\uDF2A-\uDF30\uDF32\uDF33\uDF35-\uDF39\uDF3D\uDF50\uDF5D-\uDF61]|\uD805[\uDC00-\uDC34\uDC47-\uDC4A\uDC50-\uDC59\uDC5F-\uDC61\uDC80-\uDCAF\uDCC4\uDCC5\uDCC7\uDCD0-\uDCD9\uDD80-\uDDAE\uDDD8-\uDDDB\uDE00-\uDE2F\uDE44\uDE50-\uDE59\uDE80-\uDEAA\uDEB8\uDEC0-\uDEC9\uDF00-\uDF1A\uDF30-\uDF3B\uDF40-\uDF46]|\uD806[\uDC00-\uDC2B\uDCA0-\uDCF2\uDCFF-\uDD06\uDD09\uDD0C-\uDD13\uDD15\uDD16\uDD18-\uDD2F\uDD3F\uDD41\uDD50-\uDD59\uDDA0-\uDDA7\uDDAA-\uDDD0\uDDE1\uDDE3\uDE00\uDE0B-\uDE32\uDE3A\uDE50\uDE5C-\uDE89\uDE9D\uDEB0-\uDEF8]|\uD807[\uDC00-\uDC08\uDC0A-\uDC2E\uDC40\uDC50-\uDC6C\uDC72-\uDC8F\uDD00-\uDD06\uDD08\uDD09\uDD0B-\uDD30\uDD46\uDD50-\uDD59\uDD60-\uDD65\uDD67\uDD68\uDD6A-\uDD89\uDD98\uDDA0-\uDDA9\uDEE0-\uDEF2\uDFB0\uDFC0-\uDFD4]|\uD808[\uDC00-\uDF99]|\uD809[\uDC00-\uDC6E\uDC80-\uDD43]|\uD80B[\uDF90-\uDFF0]|[\uD80C\uD81C-\uD820\uD822\uD840-\uD868\uD86A-\uD86C\uD86F-\uD872\uD874-\uD879\uD880-\uD883][\uDC00-\uDFFF]|\uD80D[\uDC00-\uDC2E]|\uD811[\uDC00-\uDE46]|\uD81A[\uDC00-\uDE38\uDE40-\uDE5E\uDE60-\uDE69\uDE70-\uDEBE\uDEC0-\uDEC9\uDED0-\uDEED\uDF00-\uDF2F\uDF40-\uDF43\uDF50-\uDF59\uDF5B-\uDF61\uDF63-\uDF77\uDF7D-\uDF8F]|\uD81B[\uDE40-\uDE96\uDF00-\uDF4A\uDF50\uDF93-\uDF9F\uDFE0\uDFE1\uDFE3]|\uD821[\uDC00-\uDFF7]|\uD823[\uDC00-\uDCD5\uDD00-\uDD08]|\uD82B[\uDFF0-\uDFF3\uDFF5-\uDFFB\uDFFD\uDFFE]|\uD82C[\uDC00-\uDD22\uDD50-\uDD52\uDD64-\uDD67\uDD70-\uDEFB]|\uD82F[\uDC00-\uDC6A\uDC70-\uDC7C\uDC80-\uDC88\uDC90-\uDC99]|\uD834[\uDEE0-\uDEF3\uDF60-\uDF78]|\uD835[\uDC00-\uDC54\uDC56-\uDC9C\uDC9E\uDC9F\uDCA2\uDCA5\uDCA6\uDCA9-\uDCAC\uDCAE-\uDCB9\uDCBB\uDCBD-\uDCC3\uDCC5-\uDD05\uDD07-\uDD0A\uDD0D-\uDD14\uDD16-\uDD1C\uDD1E-\uDD39\uDD3B-\uDD3E\uDD40-\uDD44\uDD46\uDD4A-\uDD50\uDD52-\uDEA5\uDEA8-\uDEC0\uDEC2-\uDEDA\uDEDC-\uDEFA\uDEFC-\uDF14\uDF16-\uDF34\uDF36-\uDF4E\uDF50-\uDF6E\uDF70-\uDF88\uDF8A-\uDFA8\uDFAA-\uDFC2\uDFC4-\uDFCB\uDFCE-\uDFFF]|\uD837[\uDF00-\uDF1E]|\uD838[\uDD00-\uDD2C\uDD37-\uDD3D\uDD40-\uDD49\uDD4E\uDE90-\uDEAD\uDEC0-\uDEEB\uDEF0-\uDEF9]|\uD839[\uDFE0-\uDFE6\uDFE8-\uDFEB\uDFED\uDFEE\uDFF0-\uDFFE]|\uD83A[\uDC00-\uDCC4\uDCC7-\uDCCF\uDD00-\uDD43\uDD4B\uDD50-\uDD59]|\uD83B[\uDC71-\uDCAB\uDCAD-\uDCAF\uDCB1-\uDCB4\uDD01-\uDD2D\uDD2F-\uDD3D\uDE00-\uDE03\uDE05-\uDE1F\uDE21\uDE22\uDE24\uDE27\uDE29-\uDE32\uDE34-\uDE37\uDE39\uDE3B\uDE42\uDE47\uDE49\uDE4B\uDE4D-\uDE4F\uDE51\uDE52\uDE54\uDE57\uDE59\uDE5B\uDE5D\uDE5F\uDE61\uDE62\uDE64\uDE67-\uDE6A\uDE6C-\uDE72\uDE74-\uDE77\uDE79-\uDE7C\uDE7E\uDE80-\uDE89\uDE8B-\uDE9B\uDEA1-\uDEA3\uDEA5-\uDEA9\uDEAB-\uDEBB]|\uD83C[\uDD00-\uDD0C]|\uD83E[\uDFF0-\uDFF9]|\uD869[\uDC00-\uDEDF\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF38\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D\uDC20-\uDFFF]|\uD873[\uDC00-\uDEA1\uDEB0-\uDFFF]|\uD87A[\uDC00-\uDFE0]|\uD87E[\uDC00-\uDE1D]|\uD884[\uDC00-\uDF4A])/))){var r=n[1]||n[2]||"";if(!r||""===u||this.rules.inline.punctuation.exec(u)){var i=n[0].length-1,s=i,l=0,a="*"===n[0][0]?this.rules.inline.emStrong.rDelimAst:this.rules.inline.emStrong.rDelimUnd;for(a.lastIndex=0,t=t.slice(-1*e.length+i);null!=(n=a.exec(t));)if(o=n[1]||n[2]||n[3]||n[4]||n[5]||n[6])if(o=o.length,n[3]||n[4])s+=o;else if((n[5]||n[6])&&i%3&&!((i+o)%3))l+=o;else if(!(0<(s-=o))){var o=Math.min(o,o+s+l);if(Math.min(i,o)%2)return D=e.slice(1,i+n.index+o),{type:"em",raw:e.slice(0,i+n.index+o+1),text:D,tokens:this.lexer.inlineTokens(D,[])};var D=e.slice(2,i+n.index+o-1);return{type:"strong",raw:e.slice(0,i+n.index+o+1),text:D,tokens:this.lexer.inlineTokens(D,[])}}}}},t.codespan=function(e){var t,u,n,e=this.rules.inline.code.exec(e);if(e)return n=e[2].replace(/\n/g," "),t=/[^ ]/.test(n),u=/^ /.test(n)&&/ $/.test(n),n=D(n=t&&u?n.substring(1,n.length-1):n,!0),{type:"codespan",raw:e[0],text:n}},t.br=function(e){e=this.rules.inline.br.exec(e);if(e)return{type:"br",raw:e[0]}},t.del=function(e){e=this.rules.inline.del.exec(e);if(e)return{type:"del",raw:e[0],text:e[2],tokens:this.lexer.inlineTokens(e[2],[])}},t.autolink=function(e,t){var u,e=this.rules.inline.autolink.exec(e);if(e)return t="@"===e[2]?"mailto:"+(u=D(this.options.mangle?t(e[1]):e[1])):u=D(e[1]),{type:"link",raw:e[0],text:u,href:t,tokens:[{type:"text",raw:u,text:u}]}},t.url=function(e,t){var u,n,r,i;if(u=this.rules.inline.url.exec(e)){if("@"===u[2])r="mailto:"+(n=D(this.options.mangle?t(u[0]):u[0]));else{for(;i=u[0],u[0]=this.rules.inline._backpedal.exec(u[0])[0],i!==u[0];);n=D(u[0]),r="www."===u[1]?"http://"+n:n}return{type:"link",raw:u[0],text:n,href:r,tokens:[{type:"text",raw:n,text:n}]}}},t.inlineText=function(e,t){e=this.rules.inline.text.exec(e);if(e)return t=this.lexer.state.inRawBlock?this.options.sanitize?this.options.sanitizer?this.options.sanitizer(e[0]):D(e[0]):e[0]:D(this.options.smartypants?t(e[0]):e[0]),{type:"text",raw:e[0],text:t}},e}(),y={newline:/^(?: *(?:\n|$))+/,code:/^( {4}[^\n]+(?:\n(?: *(?:\n|$))*)?)+/,fences:/^ {0,3}(`{3,}(?=[^`\n]*\n)|~{3,})([^\n]*)\n(?:|([\s\S]*?)\n)(?: {0,3}\1[~`]* *(?=\n|$)|$)/,hr:/^ {0,3}((?:-[\t ]*){3,}|(?:_[ \t]*){3,}|(?:\*[ \t]*){3,})(?:\n+|$)/,heading:/^ {0,3}(#{1,6})(?=\s|$)(.*)(?:\n+|$)/,blockquote:/^( {0,3}> ?(paragraph|[^\n]*)(?:\n|$))+/,list:/^( {0,3}bull)([ \t][^\n]+?)?(?:\n|$)/,html:"^ {0,3}(?:<(script|pre|style|textarea)[\\s>][\\s\\S]*?(?:[^\\n]*\\n+|$)|comment[^\\n]*(\\n+|$)|<\\?[\\s\\S]*?(?:\\?>\\n*|$)|\\n*|$)|\\n*|$)|)[\\s\\S]*?(?:(?:\\n *)+\\n|$)|<(?!script|pre|style|textarea)([a-z][\\w-]*)(?:attribute)*? */?>(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:(?:\\n *)+\\n|$)|(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:(?:\\n *)+\\n|$))",def:/^ {0,3}\[(label)\]: *(?:\n *)?]+)>?(?:(?: +(?:\n *)?| *\n *)(title))? *(?:\n+|$)/,table:A,lheading:/^([^\n]+)\n {0,3}(=+|-+) *(?:\n+|$)/,_paragraph:/^([^\n]+(?:\n(?!hr|heading|lheading|blockquote|fences|list|html|table| +\n)[^\n]+)*)/,text:/^[^\n]+/,_label:/(?!\s*\])(?:\\.|[^\[\]\\])+/,_title:/(?:"(?:\\"?|[^"\\])*"|'[^'\n]*(?:\n[^'\n]+)*\n?'|\([^()]*\))/},v=(y.def=p(y.def).replace("label",y._label).replace("title",y._title).getRegex(),y.bullet=/(?:[*+-]|\d{1,9}[.)])/,y.listItemStart=p(/^( *)(bull) */).replace("bull",y.bullet).getRegex(),y.list=p(y.list).replace(/bull/g,y.bullet).replace("hr","\\n+(?=\\1?(?:(?:- *){3,}|(?:_ *){3,}|(?:\\* *){3,})(?:\\n+|$))").replace("def","\\n+(?="+y.def.source+")").getRegex(),y._tag="address|article|aside|base|basefont|blockquote|body|caption|center|col|colgroup|dd|details|dialog|dir|div|dl|dt|fieldset|figcaption|figure|footer|form|frame|frameset|h[1-6]|head|header|hr|html|iframe|legend|li|link|main|menu|menuitem|meta|nav|noframes|ol|optgroup|option|p|param|section|source|summary|table|tbody|td|tfoot|th|thead|title|tr|track|ul",y._comment=/|$)/,y.html=p(y.html,"i").replace("comment",y._comment).replace("tag",y._tag).replace("attribute",/ +[a-zA-Z:_][\w.:-]*(?: *= *"[^"\n]*"| *= *'[^'\n]*'| *= *[^\s"'=<>`]+)?/).getRegex(),y.paragraph=p(y._paragraph).replace("hr",y.hr).replace("heading"," {0,3}#{1,6} ").replace("|lheading","").replace("|table","").replace("blockquote"," {0,3}>").replace("fences"," {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace("list"," {0,3}(?:[*+-]|1[.)]) ").replace("html",")|<(?:script|pre|style|textarea|!--)").replace("tag",y._tag).getRegex(),y.blockquote=p(y.blockquote).replace("paragraph",y.paragraph).getRegex(),y.normal=d({},y),y.gfm=d({},y.normal,{table:"^ *([^\\n ].*\\|.*)\\n {0,3}(?:\\| *)?(:?-+:? *(?:\\| *:?-+:? *)*)(?:\\| *)?(?:\\n((?:(?! *\\n|hr|heading|blockquote|code|fences|list|html).*(?:\\n|$))*)\\n*|$)"}),y.gfm.table=p(y.gfm.table).replace("hr",y.hr).replace("heading"," {0,3}#{1,6} ").replace("blockquote"," {0,3}>").replace("code"," {4}[^\\n]").replace("fences"," {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace("list"," {0,3}(?:[*+-]|1[.)]) ").replace("html",")|<(?:script|pre|style|textarea|!--)").replace("tag",y._tag).getRegex(),y.gfm.paragraph=p(y._paragraph).replace("hr",y.hr).replace("heading"," {0,3}#{1,6} ").replace("|lheading","").replace("table",y.gfm.table).replace("blockquote"," {0,3}>").replace("fences"," {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace("list"," {0,3}(?:[*+-]|1[.)]) ").replace("html",")|<(?:script|pre|style|textarea|!--)").replace("tag",y._tag).getRegex(),y.pedantic=d({},y.normal,{html:p("^ *(?:comment *(?:\\n|\\s*$)|<(tag)[\\s\\S]+? *(?:\\n{2,}|\\s*$)|\\s]*)*?/?> *(?:\\n{2,}|\\s*$))").replace("comment",y._comment).replace(/tag/g,"(?!(?:a|em|strong|small|s|cite|q|dfn|abbr|data|time|code|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo|span|br|wbr|ins|del|img)\\b)\\w+(?!:|[^\\w\\s@]*@)\\b").getRegex(),def:/^ *\[([^\]]+)\]: *]+)>?(?: +(["(][^\n]+[")]))? *(?:\n+|$)/,heading:/^(#{1,6})(.*)(?:\n+|$)/,fences:A,paragraph:p(y.normal._paragraph).replace("hr",y.hr).replace("heading"," *#{1,6} *[^\n]").replace("lheading",y.lheading).replace("blockquote"," {0,3}>").replace("|fences","").replace("|list","").replace("|html","").getRegex()}),{escape:/^\\([!"#$%&'()*+,\-./:;<=>?@\[\]\\^_`{|}~])/,autolink:/^<(scheme:[^\s\x00-\x1f<>]*|email)>/,url:A,tag:"^comment|^|^<[a-zA-Z][\\w-]*(?:attribute)*?\\s*/?>|^<\\?[\\s\\S]*?\\?>|^|^",link:/^!?\[(label)\]\(\s*(href)(?:\s+(title))?\s*\)/,reflink:/^!?\[(label)\]\[(ref)\]/,nolink:/^!?\[(ref)\](?:\[\])?/,reflinkSearch:"reflink|nolink(?!\\()",emStrong:{lDelim:/^(?:\*+(?:([punct_])|[^\s*]))|^_+(?:([punct*])|([^\s_]))/,rDelimAst:/^[^_*]*?\_\_[^_*]*?\*[^_*]*?(?=\_\_)|[^*]+(?=[^*])|[punct_](\*+)(?=[\s]|$)|[^punct*_\s](\*+)(?=[punct_\s]|$)|[punct_\s](\*+)(?=[^punct*_\s])|[\s](\*+)(?=[punct_])|[punct_](\*+)(?=[punct_])|[^punct*_\s](\*+)(?=[^punct*_\s])/,rDelimUnd:/^[^_*]*?\*\*[^_*]*?\_[^_*]*?(?=\*\*)|[^_]+(?=[^_])|[punct*](\_+)(?=[\s]|$)|[^punct*_\s](\_+)(?=[punct*\s]|$)|[punct*\s](\_+)(?=[^punct*_\s])|[\s](\_+)(?=[punct*])|[punct*](\_+)(?=[punct*])/},code:/^(`+)([^`]|[^`][\s\S]*?[^`])\1(?!`)/,br:/^( {2,}|\\)\n(?!\s*$)/,del:A,text:/^(`+|[^`])(?:(?= {2,}\n)|[\s\S]*?(?:(?=[\\?@\\[\\]`^{|}~",v.punctuation=p(v.punctuation).replace(/punctuation/g,v._punctuation).getRegex(),v.blockSkip=/\[[^\]]*?\]\([^\)]*?\)|`[^`]*?`|<[^>]*?>/g,v.escapedEmSt=/\\\*|\\_/g,v._comment=p(y._comment).replace("(?:--\x3e|$)","--\x3e").getRegex(),v.emStrong.lDelim=p(v.emStrong.lDelim).replace(/punct/g,v._punctuation).getRegex(),v.emStrong.rDelimAst=p(v.emStrong.rDelimAst,"g").replace(/punct/g,v._punctuation).getRegex(),v.emStrong.rDelimUnd=p(v.emStrong.rDelimUnd,"g").replace(/punct/g,v._punctuation).getRegex(),v._escapes=/\\([!"#$%&'()*+,\-./:;<=>?@\[\]\\^_`{|}~])/g,v._scheme=/[a-zA-Z][a-zA-Z0-9+.-]{1,31}/,v._email=/[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+(@)[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+(?![-_])/,v.autolink=p(v.autolink).replace("scheme",v._scheme).replace("email",v._email).getRegex(),v._attribute=/\s+[a-zA-Z:_][\w.:-]*(?:\s*=\s*"[^"]*"|\s*=\s*'[^']*'|\s*=\s*[^\s"'=<>`]+)?/,v.tag=p(v.tag).replace("comment",v._comment).replace("attribute",v._attribute).getRegex(),v._label=/(?:\[(?:\\.|[^\[\]\\])*\]|\\.|`[^`]*`|[^\[\]\\`])*?/,v._href=/<(?:\\.|[^\n<>\\])+>|[^\s\x00-\x1f]*/,v._title=/"(?:\\"?|[^"\\])*"|'(?:\\'?|[^'\\])*'|\((?:\\\)?|[^)\\])*\)/,v.link=p(v.link).replace("label",v._label).replace("href",v._href).replace("title",v._title).getRegex(),v.reflink=p(v.reflink).replace("label",v._label).replace("ref",y._label).getRegex(),v.nolink=p(v.nolink).replace("ref",y._label).getRegex(),v.reflinkSearch=p(v.reflinkSearch,"g").replace("reflink",v.reflink).replace("nolink",v.nolink).getRegex(),v.normal=d({},v),v.pedantic=d({},v.normal,{strong:{start:/^__|\*\*/,middle:/^__(?=\S)([\s\S]*?\S)__(?!_)|^\*\*(?=\S)([\s\S]*?\S)\*\*(?!\*)/,endAst:/\*\*(?!\*)/g,endUnd:/__(?!_)/g},em:{start:/^_|\*/,middle:/^()\*(?=\S)([\s\S]*?\S)\*(?!\*)|^_(?=\S)([\s\S]*?\S)_(?!_)/,endAst:/\*(?!\*)/g,endUnd:/_(?!_)/g},link:p(/^!?\[(label)\]\((.*?)\)/).replace("label",v._label).getRegex(),reflink:p(/^!?\[(label)\]\s*\[([^\]]*)\]/).replace("label",v._label).getRegex()}),v.gfm=d({},v.normal,{escape:p(v.escape).replace("])","~|])").getRegex(),_extended_email:/[A-Za-z0-9._+-]+(@)[a-zA-Z0-9-_]+(?:\.[a-zA-Z0-9-_]*[a-zA-Z0-9])+(?![-_])/,url:/^((?:ftp|https?):\/\/|www\.)(?:[a-zA-Z0-9\-]+\.?)+[^\s<]*|^email/,_backpedal:/(?:[^?!.,:;*_~()&]+|\([^)]*\)|&(?![a-zA-Z0-9]+;$)|[?!.,:;*_~)]+(?!$))+/,del:/^(~~?)(?=[^\s~])([\s\S]*?[^\s~])\1(?=[^~]|$)/,text:/^([`~]+|[^`~])(?:(?= {2,}\n)|(?=[a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-]+@)|[\s\S]*?(?:(?=[\\'+(u?e:D(e,!0))+"\n":"
"+(u?e:D(e,!0))+"
\n"},t.blockquote=function(e){return"
\n"+e+"
\n"},t.html=function(e){return e},t.heading=function(e,t,u,n){return this.options.headerIds?"'+e+"\n":""+e+"\n"},t.hr=function(){return this.options.xhtml?"
\n":"
\n"},t.list=function(e,t,u){var n=t?"ol":"ul";return"<"+n+(t&&1!==u?' start="'+u+'"':"")+">\n"+e+"\n"},t.listitem=function(e){return"
  • "+e+"
  • \n"},t.checkbox=function(e){return" "},t.paragraph=function(e){return"

    "+e+"

    \n"},t.table=function(e,t){return"\n\n"+e+"\n"+(t=t&&""+t+"")+"
    \n"},t.tablerow=function(e){return"\n"+e+"\n"},t.tablecell=function(e,t){var u=t.header?"th":"td";return(t.align?"<"+u+' align="'+t.align+'">':"<"+u+">")+e+"\n"},t.strong=function(e){return""+e+""},t.em=function(e){return""+e+""},t.codespan=function(e){return""+e+""},t.br=function(){return this.options.xhtml?"
    ":"
    "},t.del=function(e){return""+e+""},t.link=function(e,t,u){if(null===(e=g(this.options.sanitize,this.options.baseUrl,e)))return u;e='"},t.image=function(e,t,u){if(null===(e=g(this.options.sanitize,this.options.baseUrl,e)))return u;e=''+u+'":">"},t.text=function(e){return e},e}(),S=function(){function e(){}var t=e.prototype;return t.strong=function(e){return e},t.em=function(e){return e},t.codespan=function(e){return e},t.del=function(e){return e},t.html=function(e){return e},t.text=function(e){return e},t.link=function(e,t,u){return""+u},t.image=function(e,t,u){return""+u},t.br=function(){return""},e}(),T=function(){function e(){this.seen={}}var t=e.prototype;return t.serialize=function(e){return e.toLowerCase().trim().replace(/<[!\/a-z].*?>/gi,"").replace(/[\u2000-\u206F\u2E00-\u2E7F\\'!"#$%&()*+,./:;<=>?@[\]^`{|}~]/g,"").replace(/\s/g,"-")},t.getNextSafeSlug=function(e,t){var u=e,n=0;if(this.seen.hasOwnProperty(u))for(n=this.seen[e];u=e+"-"+ ++n,this.seen.hasOwnProperty(u););return t||(this.seen[e]=n,this.seen[u]=0),u},t.slug=function(e,t){void 0===t&&(t={});e=this.serialize(e);return this.getNextSafeSlug(e,t.dryrun)},e}(),R=function(){function u(e){this.options=e||r.defaults,this.options.renderer=this.options.renderer||new $,this.renderer=this.options.renderer,this.renderer.options=this.options,this.textRenderer=new S,this.slugger=new T}u.parse=function(e,t){return new u(t).parse(e)},u.parseInline=function(e,t){return new u(t).parseInline(e)};var e=u.prototype;return e.parse=function(e,t){void 0===t&&(t=!0);for(var u,n,r,i,s,l,a,o,D,c,h,p,f,g,F,A,d="",C=e.length,k=0;kAn error occurred:

    "+D(e.message+"",!0)+"
    ";throw e}}I.options=I.setOptions=function(e){return d(I.defaults,e),e=I.defaults,r.defaults=e,I},I.getDefaults=e,I.defaults=r.defaults,I.use=function(){for(var e=arguments.length,t=new Array(e),u=0;uAn error occurred:

    "+D(e.message+"",!0)+"
    ";throw e}},I.Parser=R,I.parser=R.parse,I.Renderer=$,I.TextRenderer=S,I.Lexer=z,I.lexer=z.lex,I.Tokenizer=w,I.Slugger=T;var A=(I.parse=I).options,P=I.setOptions,Q=I.use,U=I.walkTokens,M=I.parseInline,N=I,X=R.parse,G=z.lex;r.Lexer=z,r.Parser=R,r.Renderer=$,r.Slugger=T,r.TextRenderer=S,r.Tokenizer=w,r.getDefaults=e,r.lexer=G,r.marked=I,r.options=A,r.parse=N,r.parseInline=M,r.parser=X,r.setOptions=P,r.use=Q,r.walkTokens=U,Object.defineProperty(r,"__esModule",{value:!0})}); \ No newline at end of file From 5dfd5c4971b540353dfa216336447f2b2ab2a0b6 Mon Sep 17 00:00:00 2001 From: advplyr Date: Sat, 9 Jul 2022 17:29:30 -0500 Subject: [PATCH 018/100] Remove marked dependency --- package-lock.json | 17 ----------------- package.json | 1 - 2 files changed, 18 deletions(-) diff --git a/package-lock.json b/package-lock.json index 136595c5a..83f891ccb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,7 +13,6 @@ "express": "^4.17.1", "graceful-fs": "^4.2.10", "htmlparser2": "^8.0.1", - "marked": "^4.0.17", "socket.io": "^4.4.1", "xml2js": "^0.4.23" }, @@ -531,17 +530,6 @@ "node": ">= 0.10" } }, - "node_modules/marked": { - "version": "4.0.17", - "resolved": "https://registry.npmjs.org/marked/-/marked-4.0.17.tgz", - "integrity": "sha512-Wfk0ATOK5iPxM4ptrORkFemqroz0ZDxp5MWfYA7H/F+wO17NRWV5Ypxi6p3g2Xmw2bKeiYOl6oVnLHKxBA0VhA==", - "bin": { - "marked": "bin/marked.js" - }, - "engines": { - "node": ">= 12" - } - }, "node_modules/media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", @@ -1329,11 +1317,6 @@ "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==" }, - "marked": { - "version": "4.0.17", - "resolved": "https://registry.npmjs.org/marked/-/marked-4.0.17.tgz", - "integrity": "sha512-Wfk0ATOK5iPxM4ptrORkFemqroz0ZDxp5MWfYA7H/F+wO17NRWV5Ypxi6p3g2Xmw2bKeiYOl6oVnLHKxBA0VhA==" - }, "media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", diff --git a/package.json b/package.json index d567147ae..eaeb8cf20 100644 --- a/package.json +++ b/package.json @@ -34,7 +34,6 @@ "express": "^4.17.1", "graceful-fs": "^4.2.10", "htmlparser2": "^8.0.1", - "marked": "^4.0.17", "socket.io": "^4.4.1", "xml2js": "^0.4.23" } From d11f9608b46ba12bd28afb3b867d8a7f0e76aae5 Mon Sep 17 00:00:00 2001 From: advplyr Date: Tue, 12 Jul 2022 14:35:43 -0500 Subject: [PATCH 019/100] Remove old audio file scanner --- server/objects/files/AudioFile.js | 2 +- server/scanner/AudioFileScanner.js | 249 ----------------------------- server/scanner/MediaFileScanner.js | 4 +- 3 files changed, 3 insertions(+), 252 deletions(-) delete mode 100644 server/scanner/AudioFileScanner.js diff --git a/server/objects/files/AudioFile.js b/server/objects/files/AudioFile.js index d20dc367d..c2a15fb53 100644 --- a/server/objects/files/AudioFile.js +++ b/server/objects/files/AudioFile.js @@ -111,7 +111,7 @@ class AudioFile { } } - // New scanner creates AudioFile from AudioFileScanner + // New scanner creates AudioFile from MediaFileScanner setDataFromProbe(libraryFile, probeData) { this.ino = libraryFile.ino || null diff --git a/server/scanner/AudioFileScanner.js b/server/scanner/AudioFileScanner.js deleted file mode 100644 index f1735d4df..000000000 --- a/server/scanner/AudioFileScanner.js +++ /dev/null @@ -1,249 +0,0 @@ -const Path = require('path') - -const AudioFile = require('../objects/files/AudioFile') - -const prober = require('../utils/prober') -const Logger = require('../Logger') -const { LogLevel } = require('../utils/constants') - -class AudioFileScanner { - constructor() { } - - getTrackAndDiscNumberFromFilename(mediaMetadataFromScan, audioLibraryFile) { - const { title, author, series, publishedYear } = mediaMetadataFromScan - const { filename, path } = audioLibraryFile.metadata - var partbasename = Path.basename(filename, Path.extname(filename)) - - // Remove title, author, series, and publishedYear from filename if there - if (title) partbasename = partbasename.replace(title, '') - if (author) partbasename = partbasename.replace(author, '') - if (series) partbasename = partbasename.replace(series, '') - if (publishedYear) partbasename = partbasename.replace(publishedYear) - - // Look for disc number - var discNumber = null - var discMatch = partbasename.match(/\b(disc|cd) ?(\d\d?)\b/i) - if (discMatch && discMatch.length > 2 && discMatch[2]) { - if (!isNaN(discMatch[2])) { - discNumber = Number(discMatch[2]) - } - - // Remove disc number from filename - partbasename = partbasename.replace(/\b(disc|cd) ?(\d\d?)\b/i, '') - } - - // Look for disc number in folder path e.g. /Book Title/CD01/audiofile.mp3 - var pathdir = Path.dirname(path).split('/').pop() - if (pathdir && /^cd\d{1,3}$/i.test(pathdir)) { - var discFromFolder = Number(pathdir.replace(/cd/i, '')) - if (!isNaN(discFromFolder) && discFromFolder !== null) discNumber = discFromFolder - } - - var numbersinpath = partbasename.match(/\d{1,4}/g) - var trackNumber = numbersinpath && numbersinpath.length ? parseInt(numbersinpath[0]) : null - return { - trackNumber, - discNumber - } - } - - getAverageScanDurationMs(results) { - if (!results.length) return 0 - var total = 0 - for (let i = 0; i < results.length; i++) total += results[i].elapsed - return Math.floor(total / results.length) - } - - async scan(mediaType, audioLibraryFile, mediaMetadataFromScan, verbose = false) { - var probeStart = Date.now() - var probeData = await prober.probe(audioLibraryFile.metadata.path, verbose) - if (probeData.error) { - Logger.error(`[AudioFileScanner] ${probeData.error} : "${audioLibraryFile.metadata.path}"`) - return null - } - - var audioFile = new AudioFile() - audioFile.trackNumFromMeta = probeData.trackNumber - audioFile.discNumFromMeta = probeData.discNumber - if (mediaType === 'book') { - const { trackNumber, discNumber } = this.getTrackAndDiscNumberFromFilename(mediaMetadataFromScan, audioLibraryFile) - audioFile.trackNumFromFilename = trackNumber - audioFile.discNumFromFilename = discNumber - } - audioFile.setDataFromProbe(audioLibraryFile, probeData) - - return { - audioFile, - elapsed: Date.now() - probeStart - } - } - - // Returns array of { AudioFile, elapsed, averageScanDuration } from audio file scan objects - async executeAudioFileScans(mediaType, audioLibraryFiles, scanData) { - var mediaMetadataFromScan = scanData.media.metadata || null - var proms = [] - for (let i = 0; i < audioLibraryFiles.length; i++) { - proms.push(this.scan(mediaType, audioLibraryFiles[i], mediaMetadataFromScan)) - } - var scanStart = Date.now() - var results = await Promise.all(proms).then((scanResults) => scanResults.filter(sr => sr)) - return { - audioFiles: results.map(r => r.audioFile), - elapsed: Date.now() - scanStart, - averageScanDuration: this.getAverageScanDurationMs(results) - } - } - - isSequential(nums) { - if (!nums || !nums.length) return false - if (nums.length === 1) return true - var prev = nums[0] - for (let i = 1; i < nums.length; i++) { - if (nums[i] - prev > 1) return false - prev = nums[i] - } - return true - } - - removeDupes(nums) { - if (!nums || !nums.length) return [] - if (nums.length === 1) return nums - - var nodupes = [nums[0]] - nums.forEach((num) => { - if (num > nodupes[nodupes.length - 1]) nodupes.push(num) - }) - return nodupes - } - - runSmartTrackOrder(libraryItem, audioFiles) { - var discsFromFilename = [] - var tracksFromFilename = [] - var discsFromMeta = [] - var tracksFromMeta = [] - - audioFiles.forEach((af) => { - if (af.discNumFromFilename !== null) discsFromFilename.push(af.discNumFromFilename) - if (af.discNumFromMeta !== null) discsFromMeta.push(af.discNumFromMeta) - if (af.trackNumFromFilename !== null) tracksFromFilename.push(af.trackNumFromFilename) - if (af.trackNumFromMeta !== null) tracksFromMeta.push(af.trackNumFromMeta) - af.validateTrackIndex() // Sets error if no valid track number - }) - discsFromFilename.sort((a, b) => a - b) - discsFromMeta.sort((a, b) => a - b) - tracksFromFilename.sort((a, b) => a - b) - tracksFromMeta.sort((a, b) => a - b) - - var discKey = null - if (discsFromMeta.length === audioFiles.length && this.isSequential(discsFromMeta)) { - discKey = 'discNumFromMeta' - } else if (discsFromFilename.length === audioFiles.length && this.isSequential(discsFromFilename)) { - discKey = 'discNumFromFilename' - } - - var trackKey = null - tracksFromFilename = this.removeDupes(tracksFromFilename) - tracksFromMeta = this.removeDupes(tracksFromMeta) - if (tracksFromFilename.length > tracksFromMeta.length) { - trackKey = 'trackNumFromFilename' - } else { - trackKey = 'trackNumFromMeta' - } - - if (discKey !== null) { - Logger.debug(`[AudioFileScanner] Smart track order for "${libraryItem.media.metadata.title}" using disc key ${discKey} and track key ${trackKey}`) - audioFiles.sort((a, b) => { - let Dx = a[discKey] - b[discKey] - if (Dx === 0) Dx = a[trackKey] - b[trackKey] - return Dx - }) - } else { - Logger.debug(`[AudioFileScanner] Smart track order for "${libraryItem.media.metadata.title}" using track key ${trackKey}`) - audioFiles.sort((a, b) => a[trackKey] - b[trackKey]) - } - - for (let i = 0; i < audioFiles.length; i++) { - audioFiles[i].index = i + 1 - var existingAF = libraryItem.media.findFileWithInode(audioFiles[i].ino) - if (existingAF) { - if (existingAF.updateFromScan) existingAF.updateFromScan(audioFiles[i]) - } else { - libraryItem.media.addAudioFile(audioFiles[i]) - } - } - } - - async scanAudioFiles(audioLibraryFiles, scanData, libraryItem, preferAudioMetadata, libraryScan = null) { - var hasUpdated = false - - var audioScanResult = await this.executeAudioFileScans(libraryItem.mediaType, audioLibraryFiles, scanData) - if (audioScanResult.audioFiles.length) { - if (libraryScan) { - libraryScan.addLog(LogLevel.DEBUG, `Library Item "${scanData.path}" Audio file scan took ${audioScanResult.elapsed}ms for ${audioScanResult.audioFiles.length} with average time of ${audioScanResult.averageScanDuration}ms`) - } - - var totalAudioFilesToInclude = audioScanResult.audioFiles.length - var newAudioFiles = audioScanResult.audioFiles.filter(af => { - return !libraryItem.media.findFileWithInode(af.ino) - }) - - // Book: Adding audio files to book media - if (libraryItem.mediaType === 'book') { - if (newAudioFiles.length) { - // Single Track Audiobooks - if (totalAudioFilesToInclude === 1) { - var af = audioScanResult.audioFiles[0] - af.index = 1 - libraryItem.media.addAudioFile(af) - hasUpdated = true - } else { - this.runSmartTrackOrder(libraryItem, audioScanResult.audioFiles) - hasUpdated = true - } - } else { - // Only update metadata not index - audioScanResult.audioFiles.forEach((af) => { - var existingAF = libraryItem.media.findFileWithInode(af.ino) - if (existingAF) { - af.index = existingAF.index - if (existingAF.updateFromScan && existingAF.updateFromScan(af)) { - hasUpdated = true - } - } - }) - } - - // Set book details from audio file ID3 tags, optional prefer - if (libraryItem.media.setMetadataFromAudioFile(preferAudioMetadata)) { - hasUpdated = true - } - - if (hasUpdated) { - libraryItem.media.rebuildTracks() - } - } else { // Podcast Media Type - var existingAudioFiles = audioScanResult.audioFiles.filter(af => libraryItem.media.findFileWithInode(af.ino)) - - if (newAudioFiles.length) { - var newIndex = libraryItem.media.episodes.length + 1 - newAudioFiles.forEach((newAudioFile) => { - libraryItem.media.addNewEpisodeFromAudioFile(newAudioFile, newIndex++) - }) - libraryItem.media.reorderEpisodes() - hasUpdated = true - } - - // Update audio file metadata for audio files already there - existingAudioFiles.forEach((af) => { - var peAudioFile = libraryItem.media.findFileWithInode(af.ino) - if (peAudioFile.updateFromScan && peAudioFile.updateFromScan(af)) { - hasUpdated = true - } - }) - } - } - - return hasUpdated - } -} -module.exports = new AudioFileScanner() \ No newline at end of file diff --git a/server/scanner/MediaFileScanner.js b/server/scanner/MediaFileScanner.js index 3d43d85e2..3ed968956 100644 --- a/server/scanner/MediaFileScanner.js +++ b/server/scanner/MediaFileScanner.js @@ -173,14 +173,14 @@ class MediaFileScanner { } if (discKey !== null) { - Logger.debug(`[AudioFileScanner] Smart track order for "${libraryItem.media.metadata.title}" using disc key ${discKey} and track key ${trackKey}`) + Logger.debug(`[MediaFileScanner] Smart track order for "${libraryItem.media.metadata.title}" using disc key ${discKey} and track key ${trackKey}`) audioFiles.sort((a, b) => { let Dx = a[discKey] - b[discKey] if (Dx === 0) Dx = a[trackKey] - b[trackKey] return Dx }) } else { - Logger.debug(`[AudioFileScanner] Smart track order for "${libraryItem.media.metadata.title}" using track key ${trackKey}`) + Logger.debug(`[MediaFileScanner] Smart track order for "${libraryItem.media.metadata.title}" using track key ${trackKey}`) audioFiles.sort((a, b) => a[trackKey] - b[trackKey]) } From 2b91bff1afca58f1f37a0f33ce37d51b4b288a7d Mon Sep 17 00:00:00 2001 From: advplyr Date: Tue, 12 Jul 2022 15:02:08 -0500 Subject: [PATCH 020/100] Fix:Ordering newly scanned in audio tracks properly #823 --- server/objects/files/AudioFile.js | 4 ++++ server/scanner/MediaFileScanner.js | 10 +++++++--- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/server/objects/files/AudioFile.js b/server/objects/files/AudioFile.js index c2a15fb53..27c62e8e6 100644 --- a/server/objects/files/AudioFile.js +++ b/server/objects/files/AudioFile.js @@ -111,6 +111,10 @@ class AudioFile { } } + get isValidTrack() { + return !this.invalid && !this.exclude + } + // New scanner creates AudioFile from MediaFileScanner setDataFromProbe(libraryFile, probeData) { this.ino = libraryFile.ino || null diff --git a/server/scanner/MediaFileScanner.js b/server/scanner/MediaFileScanner.js index 3ed968956..e010d1b13 100644 --- a/server/scanner/MediaFileScanner.js +++ b/server/scanner/MediaFileScanner.js @@ -211,22 +211,26 @@ class MediaFileScanner { Logger.debug(`Library Item "${scanData.path}" Audio file scan took ${mediaScanResult.elapsed}ms for ${mediaScanResult.audioFiles.length} with average time of ${mediaScanResult.averageScanDuration}ms`) } - var totalAudioFilesToInclude = mediaScanResult.audioFiles.length var newAudioFiles = mediaScanResult.audioFiles.filter(af => { return !libraryItem.media.findFileWithInode(af.ino) }) // Book: Adding audio files to book media if (libraryItem.mediaType === 'book') { + var mediaScanFileInodes = mediaScanResult.audioFiles.map(af => af.ino) + // Filter for existing valid track audio files not included in the audio files scanned + var existingAudioFiles = libraryItem.media.audioFiles.filter(af => af.isValidTrack && !mediaScanFileInodes.includes(af.ino)) + if (newAudioFiles.length) { // Single Track Audiobooks - if (totalAudioFilesToInclude === 1) { + if (mediaScanFileInodes.length + existingAudioFiles.length === 1) { var af = mediaScanResult.audioFiles[0] af.index = 1 libraryItem.media.addAudioFile(af) hasUpdated = true } else { - this.runSmartTrackOrder(libraryItem, mediaScanResult.audioFiles) + var allAudioFiles = existingAudioFiles.concat(mediaScanResult.audioFiles) + this.runSmartTrackOrder(libraryItem, allAudioFiles) hasUpdated = true } } else { From 21e704e12c51f5421a1afacf3be787e736aabf17 Mon Sep 17 00:00:00 2001 From: advplyr Date: Tue, 12 Jul 2022 16:11:23 -0500 Subject: [PATCH 021/100] Fix:Show toasts below appbar & toolbar #819 --- client/assets/app.css | 14 ++++++++++++++ client/layouts/blank.vue | 7 ++++++- client/layouts/default.vue | 14 ++++++++++++++ 3 files changed, 34 insertions(+), 1 deletion(-) diff --git a/client/assets/app.css b/client/assets/app.css index 5d67df53c..f9999c7aa 100644 --- a/client/assets/app.css +++ b/client/assets/app.css @@ -225,4 +225,18 @@ Bookshelf Label -webkit-line-clamp: 2; /* number of lines to show */ -webkit-box-orient: vertical; +} + + +/* Padding for toastification toasts in the top right to not cover appbar/toolbar */ +.app-bar-and-toolbar .Vue-Toastification__container.top-right { + padding-top: 104px; +} + +.app-bar .Vue-Toastification__container.top-right { + padding-top: 64px; +} + +.no-bars .Vue-Toastification__container.top-right { + padding-top: 8px; } \ No newline at end of file diff --git a/client/layouts/blank.vue b/client/layouts/blank.vue index 9d0e3bd67..3737881b9 100644 --- a/client/layouts/blank.vue +++ b/client/layouts/blank.vue @@ -5,5 +5,10 @@ \ No newline at end of file diff --git a/client/layouts/default.vue b/client/layouts/default.vue index 71c96e24b..bf398e3c1 100644 --- a/client/layouts/default.vue +++ b/client/layouts/default.vue @@ -40,6 +40,7 @@ export default { if (this.$store.state.selectedLibraryItems) { this.$store.commit('setSelectedLibraryItems', []) } + this.updateBodyClass() } }, computed: { @@ -53,11 +54,23 @@ export default { if (!this.$route.name) return false return !this.$route.name.startsWith('config') && this.$store.state.libraries.currentLibraryId }, + isShowingToolbar() { + return this.isShowingSideRail && this.$route.name !== 'upload' && this.$route.name !== 'account' + }, appContentMarginLeft() { return this.isShowingSideRail ? 80 : 0 } }, methods: { + updateBodyClass() { + if (this.isShowingToolbar) { + document.body.classList.remove('no-bars', 'app-bar') + document.body.classList.add('app-bar-and-toolbar') + } else { + document.body.classList.remove('no-bars', 'app-bar-and-toolbar') + document.body.classList.add('app-bar') + } + }, updateSocketConnectionToast(content, type, timeout) { if (this.socketConnectionToastId !== null && this.socketConnectionToastId !== undefined) { this.$toast.update(this.socketConnectionToastId, { content: content, options: { timeout: timeout, type: type, closeButton: false, position: 'bottom-center', onClose: () => null, closeOnClick: timeout !== null } }, false) @@ -521,6 +534,7 @@ export default { this.initializeSocket() }, mounted() { + this.updateBodyClass() this.resize() window.addEventListener('resize', this.resize) window.addEventListener('keydown', this.keyDown) From 6c507de5012aa953f3ab3dd7c3e9d934f83cec6c Mon Sep 17 00:00:00 2001 From: advplyr Date: Tue, 12 Jul 2022 16:21:32 -0500 Subject: [PATCH 022/100] Remove client marked dependency --- client/package-lock.json | 17 ----------------- client/package.json | 1 - 2 files changed, 18 deletions(-) diff --git a/client/package-lock.json b/client/package-lock.json index 960d50505..a08454725 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -16,7 +16,6 @@ "epubjs": "^0.3.88", "hls.js": "^1.0.7", "libarchive.js": "^1.3.0", - "marked": "^4.0.17", "nuxt": "^2.15.8", "nuxt-socket-io": "^1.1.18", "trix": "^1.3.1", @@ -9112,17 +9111,6 @@ "node": ">=0.10.0" } }, - "node_modules/marked": { - "version": "4.0.17", - "resolved": "https://registry.npmjs.org/marked/-/marked-4.0.17.tgz", - "integrity": "sha512-Wfk0ATOK5iPxM4ptrORkFemqroz0ZDxp5MWfYA7H/F+wO17NRWV5Ypxi6p3g2Xmw2bKeiYOl6oVnLHKxBA0VhA==", - "bin": { - "marked": "bin/marked.js" - }, - "engines": { - "node": ">= 12" - } - }, "node_modules/marks-pane": { "version": "1.0.9", "resolved": "https://registry.npmjs.org/marks-pane/-/marks-pane-1.0.9.tgz", @@ -24437,11 +24425,6 @@ "object-visit": "^1.0.0" } }, - "marked": { - "version": "4.0.17", - "resolved": "https://registry.npmjs.org/marked/-/marked-4.0.17.tgz", - "integrity": "sha512-Wfk0ATOK5iPxM4ptrORkFemqroz0ZDxp5MWfYA7H/F+wO17NRWV5Ypxi6p3g2Xmw2bKeiYOl6oVnLHKxBA0VhA==" - }, "marks-pane": { "version": "1.0.9", "resolved": "https://registry.npmjs.org/marks-pane/-/marks-pane-1.0.9.tgz", diff --git a/client/package.json b/client/package.json index 7f0e5dd28..21179693a 100644 --- a/client/package.json +++ b/client/package.json @@ -20,7 +20,6 @@ "epubjs": "^0.3.88", "hls.js": "^1.0.7", "libarchive.js": "^1.3.0", - "marked": "^4.0.17", "nuxt": "^2.15.8", "nuxt-socket-io": "^1.1.18", "trix": "^1.3.1", From 7c40d268578598476f87df9b0be435907dd0de5c Mon Sep 17 00:00:00 2001 From: advplyr Date: Wed, 13 Jul 2022 19:18:49 -0500 Subject: [PATCH 023/100] Fix:Sync local mobile app progress replacing local media progress id causing duplicate media progress in mobile --- server/controllers/MeController.js | 4 +++- server/objects/user/MediaProgress.js | 2 -- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/server/controllers/MeController.js b/server/controllers/MeController.js index 8003c1f13..cae844e2b 100644 --- a/server/controllers/MeController.js +++ b/server/controllers/MeController.js @@ -190,6 +190,7 @@ class MeController { const updatedLocalMediaProgress = [] var numServerProgressUpdates = 0 var localMediaProgress = req.body.localMediaProgress || [] + localMediaProgress.forEach(localProgress => { if (!localProgress.libraryItemId) { Logger.error(`[MeController] syncLocalMediaProgress invalid local media progress object`, localProgress) @@ -216,7 +217,8 @@ class MeController { Logger.debug(`[MeController] syncLocalMediaProgress server progress is more recent by ${updateTimeDifference}ms - ${mediaProgress.id}`) for (const key in localProgress) { - if (mediaProgress[key] != undefined && localProgress[key] !== mediaProgress[key]) { + // Local media progress ID uses the local library item id and server media progress uses the library item id + if (key !== 'id' && mediaProgress[key] != undefined && localProgress[key] !== mediaProgress[key]) { // Logger.debug(`[MeController] syncLocalMediaProgress key ${key} changed from ${localProgress[key]} to ${mediaProgress[key]} - ${mediaProgress.id}`) localProgress[key] = mediaProgress[key] } diff --git a/server/objects/user/MediaProgress.js b/server/objects/user/MediaProgress.js index 3f13639d1..169a9243f 100644 --- a/server/objects/user/MediaProgress.js +++ b/server/objects/user/MediaProgress.js @@ -1,5 +1,3 @@ -const Logger = require('../../Logger') - class MediaProgress { constructor(progress) { this.id = null From af7e3a03f029b60f5573c89d7e4d0d0b10bec687 Mon Sep 17 00:00:00 2001 From: advplyr Date: Wed, 13 Jul 2022 19:38:34 -0500 Subject: [PATCH 024/100] Fix:Audio player when using chapter track then playing an item without chapters --- client/components/app/StreamContainer.vue | 4 ++++ client/components/player/PlayerUi.vue | 12 +++++++++++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/client/components/app/StreamContainer.vue b/client/components/app/StreamContainer.vue index 5775cf275..cdd144fbf 100644 --- a/client/components/app/StreamContainer.vue +++ b/client/components/app/StreamContainer.vue @@ -377,6 +377,10 @@ export default { libraryItem, episodeId }) + this.$nextTick(() => { + if (this.$refs.audioPlayer) this.$refs.audioPlayer.checkUpdateChapterTrack() + }) + this.playerHandler.load(libraryItem, episodeId, true, this.initialPlaybackRate) }, pauseItem() { diff --git a/client/components/player/PlayerUi.vue b/client/components/player/PlayerUi.vue index 608f33ca6..c23c9f9f2 100644 --- a/client/components/player/PlayerUi.vue +++ b/client/components/player/PlayerUi.vue @@ -226,6 +226,13 @@ export default { }) this.updateTimestamp() }, + checkUpdateChapterTrack() { + // Changing media in player may not have chapters + if (!this.chapters.length && this.useChapterTrack) { + this.useChapterTrack = false + if (this.$refs.trackbar) this.$refs.trackbar.setUseChapterTrack(this.useChapterTrack) + } + }, seek(time) { this.$emit('seek', time) }, @@ -286,7 +293,10 @@ export default { }, init() { this.playbackRate = this.$store.getters['user/getUserSetting']('playbackRate') || 1 - this.useChapterTrack = this.$store.getters['user/getUserSetting']('useChapterTrack') || false + + var _useChapterTrack = this.$store.getters['user/getUserSetting']('useChapterTrack') || false + this.useChapterTrack = this.chapters.length ? _useChapterTrack : false + if (this.$refs.trackbar) this.$refs.trackbar.setUseChapterTrack(this.useChapterTrack) this.$emit('setPlaybackRate', this.playbackRate) }, From ccc291067d02dcadde45cd860de17381b0e86c04 Mon Sep 17 00:00:00 2001 From: advplyr Date: Thu, 14 Jul 2022 18:06:37 -0500 Subject: [PATCH 025/100] Fix:Truetype fonts format --- client/assets/fonts.css | 52 ++++++++++++++++++++--------------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/client/assets/fonts.css b/client/assets/fonts.css index b7e75d0ca..46e007aa2 100644 --- a/client/assets/fonts.css +++ b/client/assets/fonts.css @@ -74,7 +74,7 @@ font-style: normal; font-weight: 300; font-display: swap; - src: url(/fonts/Source_Sans_Pro/SourceSansPro-Light.ttf) format('ttf'); + src: url(/fonts/Source_Sans_Pro/SourceSansPro-Light.ttf) format('truetype'); unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; } @@ -84,7 +84,7 @@ font-style: normal; font-weight: 300; font-display: swap; - src: url(/fonts/Source_Sans_Pro/SourceSansPro-Light.ttf) format('ttf'); + src: url(/fonts/Source_Sans_Pro/SourceSansPro-Light.ttf) format('truetype'); unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; } @@ -94,7 +94,7 @@ font-style: normal; font-weight: 300; font-display: swap; - src: url(/fonts/Source_Sans_Pro/SourceSansPro-Light.ttf) format('ttf'); + src: url(/fonts/Source_Sans_Pro/SourceSansPro-Light.ttf) format('truetype'); unicode-range: U+1F00-1FFF; } @@ -104,7 +104,7 @@ font-style: normal; font-weight: 300; font-display: swap; - src: url(/fonts/Source_Sans_Pro/SourceSansPro-Light.ttf) format('ttf'); + src: url(/fonts/Source_Sans_Pro/SourceSansPro-Light.ttf) format('truetype'); unicode-range: U+0370-03FF; } @@ -114,7 +114,7 @@ font-style: normal; font-weight: 300; font-display: swap; - src: url(/fonts/Source_Sans_Pro/SourceSansPro-Light.ttf) format('ttf'); + src: url(/fonts/Source_Sans_Pro/SourceSansPro-Light.ttf) format('truetype'); unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+1EA0-1EF9, U+20AB; } @@ -124,7 +124,7 @@ font-style: normal; font-weight: 300; font-display: swap; - src: url(/fonts/Source_Sans_Pro/SourceSansPro-Light.ttf) format('ttf'); + src: url(/fonts/Source_Sans_Pro/SourceSansPro-Light.ttf) format('truetype'); unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; } @@ -134,7 +134,7 @@ font-style: normal; font-weight: 300; font-display: swap; - src: url(/fonts/Source_Sans_Pro/SourceSansPro-Light.ttf) format('ttf'); + src: url(/fonts/Source_Sans_Pro/SourceSansPro-Light.ttf) format('truetype'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; } @@ -154,7 +154,7 @@ font-style: normal; font-weight: 400; font-display: swap; - src: url(/fonts/Source_Sans_Pro/SourceSansPro-Regular.ttf) format('ttf'); + src: url(/fonts/Source_Sans_Pro/SourceSansPro-Regular.ttf) format('truetype'); unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; } @@ -164,7 +164,7 @@ font-style: normal; font-weight: 400; font-display: swap; - src: url(/fonts/Source_Sans_Pro/SourceSansPro-Regular.ttf) format('ttf'); + src: url(/fonts/Source_Sans_Pro/SourceSansPro-Regular.ttf) format('truetype'); unicode-range: U+1F00-1FFF; } @@ -174,7 +174,7 @@ font-style: normal; font-weight: 400; font-display: swap; - src: url(/fonts/Source_Sans_Pro/SourceSansPro-Regular.ttf) format('ttf'); + src: url(/fonts/Source_Sans_Pro/SourceSansPro-Regular.ttf) format('truetype'); unicode-range: U+0370-03FF; } @@ -184,7 +184,7 @@ font-style: normal; font-weight: 400; font-display: swap; - src: url(/fonts/Source_Sans_Pro/SourceSansPro-Regular.ttf) format('ttf'); + src: url(/fonts/Source_Sans_Pro/SourceSansPro-Regular.ttf) format('truetype'); unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+1EA0-1EF9, U+20AB; } @@ -194,7 +194,7 @@ font-style: normal; font-weight: 400; font-display: swap; - src: url(/fonts/Source_Sans_Pro/SourceSansPro-Regular.ttf) format('ttf'); + src: url(/fonts/Source_Sans_Pro/SourceSansPro-Regular.ttf) format('truetype'); unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; } @@ -204,7 +204,7 @@ font-style: normal; font-weight: 400; font-display: swap; - src: url(/fonts/Source_Sans_Pro/SourceSansPro-Regular.ttf) format('ttf'); + src: url(/fonts/Source_Sans_Pro/SourceSansPro-Regular.ttf) format('truetype'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; } @@ -214,7 +214,7 @@ font-style: normal; font-weight: 600; font-display: swap; - src: url(/fonts/Source_Sans_Pro/SourceSansPro-SemiBold.ttf) format('ttf'); + src: url(/fonts/Source_Sans_Pro/SourceSansPro-SemiBold.ttf) format('truetype'); unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; } @@ -224,7 +224,7 @@ font-style: normal; font-weight: 600; font-display: swap; - src: url(/fonts/Source_Sans_Pro/SourceSansPro-SemiBold.ttf) format('ttf'); + src: url(/fonts/Source_Sans_Pro/SourceSansPro-SemiBold.ttf) format('truetype'); unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; } @@ -234,7 +234,7 @@ font-style: normal; font-weight: 600; font-display: swap; - src: url(/fonts/Source_Sans_Pro/SourceSansPro-SemiBold.ttf) format('ttf'); + src: url(/fonts/Source_Sans_Pro/SourceSansPro-SemiBold.ttf) format('truetype'); unicode-range: U+1F00-1FFF; } @@ -244,7 +244,7 @@ font-style: normal; font-weight: 600; font-display: swap; - src: url(/fonts/Source_Sans_Pro/SourceSansPro-SemiBold.ttf) format('ttf'); + src: url(/fonts/Source_Sans_Pro/SourceSansPro-SemiBold.ttf) format('truetype'); unicode-range: U+0370-03FF; } @@ -254,7 +254,7 @@ font-style: normal; font-weight: 600; font-display: swap; - src: url(/fonts/Source_Sans_Pro/SourceSansPro-SemiBold.ttf) format('ttf'); + src: url(/fonts/Source_Sans_Pro/SourceSansPro-SemiBold.ttf) format('truetype'); unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+1EA0-1EF9, U+20AB; } @@ -264,7 +264,7 @@ font-style: normal; font-weight: 600; font-display: swap; - src: url(/fonts/Source_Sans_Pro/SourceSansPro-SemiBold.ttf) format('ttf'); + src: url(/fonts/Source_Sans_Pro/SourceSansPro-SemiBold.ttf) format('truetype'); unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; } @@ -274,7 +274,7 @@ font-style: normal; font-weight: 600; font-display: swap; - src: url(/fonts/Source_Sans_Pro/SourceSansPro-SemiBold.ttf) format('ttf'); + src: url(/fonts/Source_Sans_Pro/SourceSansPro-SemiBold.ttf) format('truetype'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; } @@ -284,7 +284,7 @@ font-style: normal; font-weight: 400; font-display: swap; - src: url(/fonts/Ubuntu_Mono/UbuntuMono-Regular.ttf) format('ttf'); + src: url(/fonts/Ubuntu_Mono/UbuntuMono-Regular.ttf) format('truetype'); unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; } @@ -294,7 +294,7 @@ font-style: normal; font-weight: 400; font-display: swap; - src: url(/fonts/Ubuntu_Mono/UbuntuMono-Regular.ttf) format('ttf'); + src: url(/fonts/Ubuntu_Mono/UbuntuMono-Regular.ttf) format('truetype'); unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; } @@ -304,7 +304,7 @@ font-style: normal; font-weight: 400; font-display: swap; - src: url(/fonts/Ubuntu_Mono/UbuntuMono-Regular.ttf) format('ttf'); + src: url(/fonts/Ubuntu_Mono/UbuntuMono-Regular.ttf) format('truetype'); unicode-range: U+1F00-1FFF; } @@ -314,7 +314,7 @@ font-style: normal; font-weight: 400; font-display: swap; - src: url(/fonts/Ubuntu_Mono/UbuntuMono-Regular.ttf) format('ttf'); + src: url(/fonts/Ubuntu_Mono/UbuntuMono-Regular.ttf) format('truetype'); unicode-range: U+0370-03FF; } @@ -324,7 +324,7 @@ font-style: normal; font-weight: 400; font-display: swap; - src: url(/fonts/Ubuntu_Mono/UbuntuMono-Regular.ttf) format('ttf'); + src: url(/fonts/Ubuntu_Mono/UbuntuMono-Regular.ttf) format('truetype'); unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; } @@ -334,6 +334,6 @@ font-style: normal; font-weight: 400; font-display: swap; - src: url(/fonts/Ubuntu_Mono/UbuntuMono-Regular.ttf) format('ttf'); + src: url(/fonts/Ubuntu_Mono/UbuntuMono-Regular.ttf) format('truetype'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; } \ No newline at end of file From 653019921ee1d9017e959b315b91bc75d54efc4a Mon Sep 17 00:00:00 2001 From: advplyr Date: Thu, 14 Jul 2022 18:32:00 -0500 Subject: [PATCH 026/100] Add:Support for OGA file extension #804, Update:Mime type for m4b and m4a to audio/mp4 --- client/plugins/constants.js | 2 +- server/utils/constants.js | 5 +++-- server/utils/globals.js | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/client/plugins/constants.js b/client/plugins/constants.js index 4c3838e40..27884222a 100644 --- a/client/plugins/constants.js +++ b/client/plugins/constants.js @@ -1,6 +1,6 @@ const SupportedFileTypes = { image: ['png', 'jpg', 'jpeg', 'webp'], - audio: ['m4b', 'mp3', 'm4a', 'flac', 'opus', 'ogg', 'mp4', 'aac', 'wma', 'aiff', 'wav'], + audio: ['m4b', 'mp3', 'm4a', 'flac', 'opus', 'ogg', 'oga', 'mp4', 'aac', 'wma', 'aiff', 'wav'], ebook: ['epub', 'pdf', 'mobi', 'azw3', 'cbr', 'cbz'], info: ['nfo'], text: ['txt'], diff --git a/server/utils/constants.js b/server/utils/constants.js index bf4c8aaf3..2429c3250 100644 --- a/server/utils/constants.js +++ b/server/utils/constants.js @@ -35,10 +35,11 @@ module.exports.PlayMethod = { module.exports.AudioMimeType = { MP3: 'audio/mpeg', - M4B: 'audio/mpeg', - M4A: 'audio/mpeg', + M4B: 'audio/mp4', + M4A: 'audio/mp4', MP4: 'audio/mp4', OGG: 'audio/ogg', + OGA: 'audio/ogg', OPUS: 'audio/ogg', AAC: 'audio/aac', FLAC: 'audio/flac', diff --git a/server/utils/globals.js b/server/utils/globals.js index 016cbc3c3..84205fce0 100644 --- a/server/utils/globals.js +++ b/server/utils/globals.js @@ -1,6 +1,6 @@ const globals = { SupportedImageTypes: ['png', 'jpg', 'jpeg', 'webp'], - SupportedAudioTypes: ['m4b', 'mp3', 'm4a', 'flac', 'opus', 'ogg', 'mp4', 'aac', 'wma', 'aiff', 'wav'], + SupportedAudioTypes: ['m4b', 'mp3', 'm4a', 'flac', 'opus', 'ogg', 'oga', 'mp4', 'aac', 'wma', 'aiff', 'wav'], SupportedEbookTypes: ['epub', 'pdf', 'mobi', 'azw3', 'cbr', 'cbz'], SupportedVideoTypes: ['mp4'], TextFileTypes: ['txt', 'nfo'], From 51b87912f8a5dc67630e45488ad3151d1bacae8c Mon Sep 17 00:00:00 2001 From: advplyr Date: Thu, 14 Jul 2022 19:00:52 -0500 Subject: [PATCH 027/100] Update:Collapsed series shows series name instead of first book title and only sorts when sorting by title #629 --- client/components/cards/LazyBookCard.vue | 3 +++ server/controllers/LibraryController.js | 13 ++++++++++++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/client/components/cards/LazyBookCard.vue b/client/components/cards/LazyBookCard.vue index 6cea7cdba..091f3b598 100644 --- a/client/components/cards/LazyBookCard.vue +++ b/client/components/cards/LazyBookCard.vue @@ -249,6 +249,7 @@ export default { }, displayTitle() { if (this.recentEpisode) return this.recentEpisode.title + if (this.collapsedSeries) return this.collapsedSeries.name if (this.orderBy === 'media.metadata.title' && this.sortingIgnorePrefix) { return this.mediaMetadata.titleIgnorePrefix } @@ -257,6 +258,7 @@ export default { displayLineTwo() { if (this.recentEpisode) return this.title if (this.isPodcast) return this.author + if (this.collapsedSeries) return '' if (this.isAuthorBookshelfView) { return this.mediaMetadata.publishedYear || '' } @@ -264,6 +266,7 @@ export default { return this.author }, displaySortLine() { + if (this.collapsedSeries) return null if (this.orderBy === 'mtimeMs') return 'Modified ' + this.$formatDate(this._libraryItem.mtimeMs, this.dateFormat) if (this.orderBy === 'birthtimeMs') return 'Born ' + this.$formatDate(this._libraryItem.birthtimeMs, this.dateFormat) if (this.orderBy === 'addedAt') return 'Added ' + this.$formatDate(this._libraryItem.addedAt, this.dateFormat) diff --git a/server/controllers/LibraryController.js b/server/controllers/LibraryController.js index dfad01c31..0bb88f2a3 100644 --- a/server/controllers/LibraryController.js +++ b/server/controllers/LibraryController.js @@ -176,7 +176,8 @@ class LibraryController { } // Handle server setting sortingIgnorePrefix - if (sortKey === 'media.metadata.title' && this.db.serverSettings.sortingIgnorePrefix) { + const sortByTitle = sortKey === 'media.metadata.title' + if (sortByTitle && this.db.serverSettings.sortingIgnorePrefix) { // BookMetadata.js has titleIgnorePrefix getter sortKey += 'IgnorePrefix' } @@ -186,6 +187,16 @@ class LibraryController { var sortArray = [ { [direction]: (li) => { + // When collapsing by series and sorting by title use the series name instead of the book title + if (payload.mediaType === 'book' && payload.collapseseries && li.media.metadata.seriesName) { + if (sortByTitle) { + return li.media.metadata.seriesName + } else { + // When not sorting by title always show the collapsed series at the end + return direction === 'desc' ? -1 : 'zzzz' + } + } + // Supports dot notation strings i.e. "media.metadata.title" return sortKey.split('.').reduce((a, b) => a[b], li) } From 277a5fa37c030d1268afd5358f8c19613e1fe7f4 Mon Sep 17 00:00:00 2001 From: advplyr Date: Thu, 14 Jul 2022 19:51:33 -0500 Subject: [PATCH 028/100] Version bump 2.0.24 --- client/package-lock.json | 4 ++-- client/package.json | 4 ++-- package-lock.json | 4 ++-- package.json | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/client/package-lock.json b/client/package-lock.json index a08454725..c685672ed 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -1,6 +1,6 @@ { "name": "audiobookshelf-client", - "version": "2.0.23", + "version": "2.0.24", "lockfileVersion": 2, "requires": true, "packages": { @@ -30804,4 +30804,4 @@ "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==" } } -} +} \ No newline at end of file diff --git a/client/package.json b/client/package.json index 21179693a..baf44e7ca 100644 --- a/client/package.json +++ b/client/package.json @@ -1,6 +1,6 @@ { "name": "audiobookshelf-client", - "version": "2.0.23", + "version": "2.0.24", "description": "Self-hosted audiobook and podcast client", "main": "index.js", "scripts": { @@ -36,4 +36,4 @@ "postcss": "^8.3.6", "tailwindcss": "^3.1.4" } -} +} \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 83f891ccb..e9af3ab7f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "audiobookshelf", - "version": "2.0.23", + "version": "2.0.24", "lockfileVersion": 2, "requires": true, "packages": { @@ -1602,4 +1602,4 @@ "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==" } } -} +} \ No newline at end of file diff --git a/package.json b/package.json index eaeb8cf20..622c3c2af 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "audiobookshelf", - "version": "2.0.23", + "version": "2.0.24", "description": "Self-hosted audiobook and podcast server", "main": "index.js", "scripts": { @@ -37,4 +37,4 @@ "socket.io": "^4.4.1", "xml2js": "^0.4.23" } -} +} \ No newline at end of file From 86ee4dcff2a4490627cae8e54818b7552a8ce640 Mon Sep 17 00:00:00 2001 From: advplyr Date: Sat, 16 Jul 2022 18:54:34 -0500 Subject: [PATCH 029/100] Update:Scanner adjustable number of parallel audio probes to use less CPU --- client/pages/config/index.vue | 45 ++++- server/Db.js | 1 - server/objects/files/AudioFile.js | 17 -- server/objects/settings/ServerSettings.js | 7 + server/scanner/MediaFileScanner.js | 55 ++++-- server/scanner/MediaProbeData.js | 16 +- server/scanner/MediaProbePool.js | 209 ++++++++++++++++++++++ server/scanner/Scanner.js | 69 ++++--- server/utils/probeWorker.js | 9 + server/utils/prober.js | 15 +- 10 files changed, 372 insertions(+), 71 deletions(-) create mode 100644 server/scanner/MediaProbePool.js create mode 100644 server/utils/probeWorker.js diff --git a/client/pages/config/index.vue b/client/pages/config/index.vue index 24d3d68d2..6baf5dd74 100644 --- a/client/pages/config/index.vue +++ b/client/pages/config/index.vue @@ -157,6 +157,17 @@
    +
    + + +

    + Max # of threads to use + info_outlined +

    +
    + +
    +

    Experimental Features

    @@ -184,6 +195,16 @@

    + +
    + + +

    + Scanner use old single threaded audio prober + info_outlined +

    +
    +
    @@ -268,7 +289,9 @@ export default { storeMetadataWithItem: 'By default metadata files are stored in /metadata/items, enabling this setting will store metadata files in your library item folders. Uses .abs file extension', coverAspectRatio: 'Prefer to use square covers over standard 1.6:1 book covers', enableEReader: 'E-reader is still a work in progress, but use this setting to open it up to all your users (or use the "Experimental Features" toggle just for use by you)', - scannerPreferOverdriveMediaMarker: 'MP3 files from Overdrive come with chapter timings embedded as custom metadata. Enabling this will use these tags for chapter timings automatically' + scannerPreferOverdriveMediaMarker: 'MP3 files from Overdrive come with chapter timings embedded as custom metadata. Enabling this will use these tags for chapter timings automatically', + scannerUseSingleThreadedProber: 'The old scanner used a single thread. Leaving it in to use as a comparison for now.', + scannerMaxThreads: 'Number of concurrent media files to scan at a time. Value of 1 will be a slower scan but less CPU usage.

    Value of 0 defaults to # of CPU cores for this server times 2 (i.e. 4-core CPU will be 8)' }, showConfirmPurgeCache: false } @@ -300,6 +323,26 @@ export default { } }, methods: { + updateScannerMaxThreads(val) { + if (!val || isNaN(val)) { + this.$toast.error('Invalid max threads must be a number') + this.newServerSettings.scannerMaxThreads = 0 + return + } + if (Number(val) < 0) { + this.$toast.error('Max threads must be >= 0') + this.newServerSettings.scannerMaxThreads = 0 + return + } + if (Math.round(Number(val)) !== Number(val)) { + this.$toast.error('Max threads must be an integer') + this.newServerSettings.scannerMaxThreads = 0 + return + } + this.updateServerSettings({ + scannerMaxThreads: Number(val) + }) + }, updateSortingPrefixes(val) { if (!val || !val.length) { this.$toast.error('Must have at least 1 prefix') diff --git a/server/Db.js b/server/Db.js index f9fac6d47..ceb80c53d 100644 --- a/server/Db.js +++ b/server/Db.js @@ -10,7 +10,6 @@ const Author = require('./objects/entities/Author') const Series = require('./objects/entities/Series') const ServerSettings = require('./objects/settings/ServerSettings') const PlaybackSession = require('./objects/PlaybackSession') -const Feed = require('./objects/Feed') class Db { constructor() { diff --git a/server/objects/files/AudioFile.js b/server/objects/files/AudioFile.js index 27c62e8e6..35cb61b05 100644 --- a/server/objects/files/AudioFile.js +++ b/server/objects/files/AudioFile.js @@ -136,23 +136,6 @@ class AudioFile { this.embeddedCoverArt = probeData.embeddedCoverArt } - validateTrackIndex() { - var numFromMeta = isNullOrNaN(this.trackNumFromMeta) ? null : Number(this.trackNumFromMeta) - var numFromFilename = isNullOrNaN(this.trackNumFromFilename) ? null : Number(this.trackNumFromFilename) - - if (numFromMeta !== null) return numFromMeta - if (numFromFilename !== null) return numFromFilename - - this.invalid = true - this.error = 'Failed to get track number' - return null - } - - setDuplicateTrackNumber(num) { - this.invalid = true - this.error = 'Duplicate track number "' + num + '"' - } - syncChapters(updatedChapters) { if (this.chapters.length !== updatedChapters.length) { this.chapters = updatedChapters.map(ch => ({ ...ch })) diff --git a/server/objects/settings/ServerSettings.js b/server/objects/settings/ServerSettings.js index 71c478282..4860d494a 100644 --- a/server/objects/settings/ServerSettings.js +++ b/server/objects/settings/ServerSettings.js @@ -1,4 +1,5 @@ const { BookCoverAspectRatio, BookshelfView } = require('../../utils/constants') +const { isNullOrNaN } = require('../../utils') const Logger = require('../../Logger') class ServerSettings { @@ -14,6 +15,8 @@ class ServerSettings { this.scannerPreferMatchedMetadata = false this.scannerDisableWatcher = false this.scannerPreferOverdriveMediaMarker = false + this.scannerUseSingleThreadedProber = false + this.scannerMaxThreads = 0 // 0 = defaults to CPUs * 2 // Metadata - choose to store inside users library item folder this.storeCoverWithItem = false @@ -68,6 +71,8 @@ class ServerSettings { this.scannerPreferMatchedMetadata = !!settings.scannerPreferMatchedMetadata this.scannerDisableWatcher = !!settings.scannerDisableWatcher this.scannerPreferOverdriveMediaMarker = !!settings.scannerPreferOverdriveMediaMarker + this.scannerUseSingleThreadedProber = !!settings.scannerUseSingleThreadedProber + this.scannerMaxThreads = isNullOrNaN(settings.scannerMaxThreads) ? 0 : Number(settings.scannerMaxThreads) this.storeCoverWithItem = !!settings.storeCoverWithItem if (settings.storeCoverWithBook != undefined) { // storeCoverWithBook was old name of setting < v2 @@ -116,6 +121,8 @@ class ServerSettings { scannerPreferMatchedMetadata: this.scannerPreferMatchedMetadata, scannerDisableWatcher: this.scannerDisableWatcher, scannerPreferOverdriveMediaMarker: this.scannerPreferOverdriveMediaMarker, + scannerUseSingleThreadedProber: this.scannerUseSingleThreadedProber, + scannerMaxThreads: this.scannerMaxThreads, storeCoverWithItem: this.storeCoverWithItem, storeMetadataWithItem: this.storeMetadataWithItem, rateLimitLoginRequests: this.rateLimitLoginRequests, diff --git a/server/scanner/MediaFileScanner.js b/server/scanner/MediaFileScanner.js index e010d1b13..38b74e0df 100644 --- a/server/scanner/MediaFileScanner.js +++ b/server/scanner/MediaFileScanner.js @@ -3,6 +3,8 @@ const Path = require('path') const AudioFile = require('../objects/files/AudioFile') const VideoFile = require('../objects/files/VideoFile') +const MediaProbePool = require('./MediaProbePool') + const prober = require('../utils/prober') const Logger = require('../Logger') const { LogLevel } = require('../utils/constants') @@ -100,19 +102,38 @@ class MediaFileScanner { } // Returns array of { MediaFile, elapsed, averageScanDuration } from audio file scan objects - async executeMediaFileScans(mediaType, mediaLibraryFiles, scanData) { - var mediaMetadataFromScan = scanData.media.metadata || null - var proms = [] - for (let i = 0; i < mediaLibraryFiles.length; i++) { - proms.push(this.scan(mediaType, mediaLibraryFiles[i], mediaMetadataFromScan)) - } - var scanStart = Date.now() - var results = await Promise.all(proms).then((scanResults) => scanResults.filter(sr => sr)) - return { - audioFiles: results.filter(r => r.audioFile).map(r => r.audioFile), - videoFiles: results.filter(r => r.videoFile).map(r => r.videoFile), - elapsed: Date.now() - scanStart, - averageScanDuration: this.getAverageScanDurationMs(results) + async executeMediaFileScans(libraryItem, mediaLibraryFiles, scanData) { + const mediaType = libraryItem.mediaType + + if (!global.ServerSettings.scannerUseSingleThreadedProber) { // New multi-threaded scanner + var scanStart = Date.now() + const probeResults = await new Promise((resolve) => { + // const probePool = new MediaProbePool(mediaType, mediaLibraryFiles, scanData, global.ServerSettings.scannerMaxThreads) + const itemBatch = MediaProbePool.initBatch(libraryItem, mediaLibraryFiles, scanData) + itemBatch.on('done', resolve) + MediaProbePool.runBatch(itemBatch) + }) + + return { + audioFiles: probeResults.audioFiles || [], + videoFiles: probeResults.videoFiles || [], + elapsed: Date.now() - scanStart, + averageScanDuration: probeResults.averageTimePerMb + } + } else { // Old single threaded scanner + var scanStart = Date.now() + var mediaMetadataFromScan = scanData.media.metadata || null + var proms = [] + for (let i = 0; i < mediaLibraryFiles.length; i++) { + proms.push(this.scan(mediaType, mediaLibraryFiles[i], mediaMetadataFromScan)) + } + var results = await Promise.all(proms).then((scanResults) => scanResults.filter(sr => sr)) + return { + audioFiles: results.filter(r => r.audioFile).map(r => r.audioFile), + videoFiles: results.filter(r => r.videoFile).map(r => r.videoFile), + elapsed: Date.now() - scanStart, + averageScanDuration: this.getAverageScanDurationMs(results) + } } } @@ -149,7 +170,6 @@ class MediaFileScanner { if (af.discNumFromMeta !== null) discsFromMeta.push(af.discNumFromMeta) if (af.trackNumFromFilename !== null) tracksFromFilename.push(af.trackNumFromFilename) if (af.trackNumFromMeta !== null) tracksFromMeta.push(af.trackNumFromMeta) - af.validateTrackIndex() // Sets error if no valid track number }) discsFromFilename.sort((a, b) => a - b) discsFromMeta.sort((a, b) => a - b) @@ -198,7 +218,8 @@ class MediaFileScanner { async scanMediaFiles(mediaLibraryFiles, scanData, libraryItem, preferAudioMetadata, preferOverdriveMediaMarker, libraryScan = null) { var hasUpdated = false - var mediaScanResult = await this.executeMediaFileScans(libraryItem.mediaType, mediaLibraryFiles, scanData) + var mediaScanResult = await this.executeMediaFileScans(libraryItem, mediaLibraryFiles, scanData) + if (libraryItem.mediaType === 'video') { if (mediaScanResult.videoFiles.length) { // TODO: Check for updates etc @@ -207,9 +228,9 @@ class MediaFileScanner { } } else if (mediaScanResult.audioFiles.length) { if (libraryScan) { - libraryScan.addLog(LogLevel.DEBUG, `Library Item "${scanData.path}" Audio file scan took ${mediaScanResult.elapsed}ms for ${mediaScanResult.audioFiles.length} with average time of ${mediaScanResult.averageScanDuration}ms`) - Logger.debug(`Library Item "${scanData.path}" Audio file scan took ${mediaScanResult.elapsed}ms for ${mediaScanResult.audioFiles.length} with average time of ${mediaScanResult.averageScanDuration}ms`) + libraryScan.addLog(LogLevel.DEBUG, `Library Item "${scanData.path}" Media file scan took ${mediaScanResult.elapsed}ms for ${mediaScanResult.audioFiles.length} with average time of ${mediaScanResult.averageScanDuration}ms per MB`) } + Logger.debug(`Library Item "${scanData.path}" Media file scan took ${mediaScanResult.elapsed}ms with ${mediaScanResult.audioFiles.length} audio files averaging ${mediaScanResult.averageScanDuration}ms per MB`) var newAudioFiles = mediaScanResult.audioFiles.filter(af => { return !libraryItem.media.findFileWithInode(af.ino) diff --git a/server/scanner/MediaProbeData.js b/server/scanner/MediaProbeData.js index 2946077c6..88edb4d7f 100644 --- a/server/scanner/MediaProbeData.js +++ b/server/scanner/MediaProbeData.js @@ -1,7 +1,7 @@ const AudioFileMetadata = require('../objects/metadata/AudioMetaTags') class MediaProbeData { - constructor() { + constructor(probeData) { this.embeddedCoverArt = null this.format = null this.duration = null @@ -26,6 +26,20 @@ class MediaProbeData { this.discNumber = null this.discTotal = null + + if (probeData) { + this.construct(probeData) + } + } + + construct(probeData) { + for (const key in probeData) { + if (key === 'audioFileMetadata' && probeData[key]) { + this[key] = new AudioFileMetadata(probeData[key]) + } else if (this[key] !== undefined) { + this[key] = probeData[key] + } + } } getEmbeddedCoverArt(videoStream) { diff --git a/server/scanner/MediaProbePool.js b/server/scanner/MediaProbePool.js new file mode 100644 index 000000000..4076c8098 --- /dev/null +++ b/server/scanner/MediaProbePool.js @@ -0,0 +1,209 @@ +const os = require('os') +const Path = require('path') +const { EventEmitter } = require('events') +const { Worker } = require("worker_threads") +const Logger = require('../Logger') +const AudioFile = require('../objects/files/AudioFile') +const VideoFile = require('../objects/files/VideoFile') +const MediaProbeData = require('./MediaProbeData') + +class LibraryItemBatch extends EventEmitter { + constructor(libraryItem, libraryFiles, scanData) { + super() + + this.id = libraryItem.id + this.mediaType = libraryItem.mediaType + this.mediaMetadataFromScan = scanData.media.metadata || null + this.libraryFilesToScan = libraryFiles + + // Results + this.totalElapsed = 0 + this.totalProbed = 0 + this.audioFiles = [] + this.videoFiles = [] + } + + done() { + this.emit('done', { + videoFiles: this.videoFiles, + audioFiles: this.audioFiles, + averageTimePerMb: Math.round(this.totalElapsed / this.totalProbed) + }) + } +} + +class MediaProbePool { + constructor() { + this.MaxThreads = 0 + this.probeWorkerScript = null + + this.itemBatchMap = {} + + this.probesRunning = [] + this.probeQueue = [] + } + + tick() { + if (this.probesRunning.length < this.MaxThreads) { + if (this.probeQueue.length > 0) { + const pw = this.probeQueue.shift() + // console.log('Unqueued probe - Remaining is', this.probeQueue.length, 'Currently running is', this.probesRunning.length) + this.startTask(pw) + } else if (!this.probesRunning.length) { + // console.log('No more probes to run') + } + } + } + + async startTask(task) { + this.probesRunning.push(task) + + const itemBatch = this.itemBatchMap[task.batchId] + + await task.start().then((taskResult) => { + itemBatch.libraryFilesToScan = itemBatch.libraryFilesToScan.filter(lf => lf.ino !== taskResult.libraryFile.ino) + + var fileSizeMb = taskResult.libraryFile.metadata.size / (1024 * 1024) + var elapsedPerMb = Math.round(taskResult.elapsed / fileSizeMb) + + const probeData = new MediaProbeData(taskResult.data) + + if (itemBatch.mediaType === 'video') { + if (!probeData.videoStream) { + Logger.error('[MediaProbePool] Invalid video file no video stream') + } else { + itemBatch.totalElapsed += elapsedPerMb + itemBatch.totalProbed++ + + var videoFile = new VideoFile() + videoFile.setDataFromProbe(libraryFile, probeData) + itemBatch.videoFiles.push(videoFile) + } + } else { + if (!probeData.audioStream) { + Logger.error('[MediaProbePool] Invalid audio file no audio stream') + } else { + itemBatch.totalElapsed += elapsedPerMb + itemBatch.totalProbed++ + + var audioFile = new AudioFile() + audioFile.trackNumFromMeta = probeData.trackNumber + audioFile.discNumFromMeta = probeData.discNumber + if (itemBatch.mediaType === 'book') { + const { trackNumber, discNumber } = this.getTrackAndDiscNumberFromFilename(itemBatch.mediaMetadataFromScan, taskResult.libraryFile) + audioFile.trackNumFromFilename = trackNumber + audioFile.discNumFromFilename = discNumber + } + audioFile.setDataFromProbe(taskResult.libraryFile, probeData) + + itemBatch.audioFiles.push(audioFile) + } + } + + this.probesRunning = this.probesRunning.filter(tq => tq.mediaPath !== task.mediaPath) + this.tick() + }).catch((error) => { + itemBatch.libraryFilesToScan = itemBatch.libraryFilesToScan.filter(lf => lf.ino !== taskResult.libraryFile.ino) + + Logger.error('[MediaProbePool] Task failed', error) + this.probesRunning = this.probesRunning.filter(tq => tq.mediaPath !== task.mediaPath) + this.tick() + }) + + if (!itemBatch.libraryFilesToScan.length) { + itemBatch.done() + delete this.itemBatchMap[itemBatch.id] + } + } + + buildTask(libraryFile, batchId) { + return { + batchId, + mediaPath: libraryFile.metadata.path, + start: () => { + return new Promise((resolve, reject) => { + const startTime = Date.now() + + const worker = new Worker(this.probeWorkerScript) + worker.on("message", ({ data }) => { + if (data.error) { + reject(data.error) + } else { + resolve({ + data, + elapsed: Date.now() - startTime, + libraryFile + }) + } + }) + worker.postMessage({ + mediaPath: libraryFile.metadata.path + }) + }) + } + } + } + + initBatch(libraryItem, libraryFiles, scanData) { + this.MaxThreads = global.ServerSettings.scannerMaxThreads || (os.cpus().length * 2) + this.probeWorkerScript = Path.join(global.appRoot, 'server/utils/probeWorker.js') + + Logger.debug(`[MediaProbePool] Run item batch ${libraryItem.id} with`, libraryFiles.length, 'files and max concurrent of', this.MaxThreads) + + const itemBatch = new LibraryItemBatch(libraryItem, libraryFiles, scanData) + this.itemBatchMap[itemBatch.id] = itemBatch + + return itemBatch + } + + runBatch(itemBatch) { + for (const libraryFile of itemBatch.libraryFilesToScan) { + const probeTask = this.buildTask(libraryFile, itemBatch.id) + + if (this.probesRunning.length < this.MaxThreads) { + this.startTask(probeTask) + } else { + this.probeQueue.push(probeTask) + } + } + } + + getTrackAndDiscNumberFromFilename(mediaMetadataFromScan, audioLibraryFile) { + const { title, author, series, publishedYear } = mediaMetadataFromScan + const { filename, path } = audioLibraryFile.metadata + var partbasename = Path.basename(filename, Path.extname(filename)) + + // Remove title, author, series, and publishedYear from filename if there + if (title) partbasename = partbasename.replace(title, '') + if (author) partbasename = partbasename.replace(author, '') + if (series) partbasename = partbasename.replace(series, '') + if (publishedYear) partbasename = partbasename.replace(publishedYear) + + // Look for disc number + var discNumber = null + var discMatch = partbasename.match(/\b(disc|cd) ?(\d\d?)\b/i) + if (discMatch && discMatch.length > 2 && discMatch[2]) { + if (!isNaN(discMatch[2])) { + discNumber = Number(discMatch[2]) + } + + // Remove disc number from filename + partbasename = partbasename.replace(/\b(disc|cd) ?(\d\d?)\b/i, '') + } + + // Look for disc number in folder path e.g. /Book Title/CD01/audiofile.mp3 + var pathdir = Path.dirname(path).split('/').pop() + if (pathdir && /^cd\d{1,3}$/i.test(pathdir)) { + var discFromFolder = Number(pathdir.replace(/cd/i, '')) + if (!isNaN(discFromFolder) && discFromFolder !== null) discNumber = discFromFolder + } + + var numbersinpath = partbasename.match(/\d{1,4}/g) + var trackNumber = numbersinpath && numbersinpath.length ? parseInt(numbersinpath[0]) : null + return { + trackNumber, + discNumber + } + } +} +module.exports = new MediaProbePool() \ No newline at end of file diff --git a/server/scanner/Scanner.js b/server/scanner/Scanner.js index d8bdd68f5..8c49722f1 100644 --- a/server/scanner/Scanner.js +++ b/server/scanner/Scanner.js @@ -205,20 +205,27 @@ class Scanner { checkRes.libraryItem = libraryItem checkRes.scanData = dataFound - // If this item will go over max size then push current chunk - if (libraryItem.audioFileTotalSize + itemDataToRescanSize > MaxSizePerChunk && itemDataToRescan.length > 0) { - itemDataToRescanChunks.push(itemDataToRescan) - itemDataToRescanSize = 0 - itemDataToRescan = [] + console.log('Has New Library Files', libraryItem.media.metadata.title, 'num new', checkRes.newLibraryFiles.length) + + if (global.ServerSettings.scannerUseSingleThreadedProber) { + // If this item will go over max size then push current chunk + if (libraryItem.audioFileTotalSize + itemDataToRescanSize > MaxSizePerChunk && itemDataToRescan.length > 0) { + itemDataToRescanChunks.push(itemDataToRescan) + itemDataToRescanSize = 0 + itemDataToRescan = [] + } + + itemDataToRescan.push(checkRes) + itemDataToRescanSize += libraryItem.audioFileTotalSize + if (itemDataToRescanSize >= MaxSizePerChunk) { + itemDataToRescanChunks.push(itemDataToRescan) + itemDataToRescanSize = 0 + itemDataToRescan = [] + } + } else { + itemDataToRescan.push(checkRes) } - itemDataToRescan.push(checkRes) - itemDataToRescanSize += libraryItem.audioFileTotalSize - if (itemDataToRescanSize >= MaxSizePerChunk) { - itemDataToRescanChunks.push(itemDataToRescan) - itemDataToRescanSize = 0 - itemDataToRescan = [] - } } else if (libraryScan.findCovers && libraryItem.media.shouldSearchForCover) { // Search cover libraryScan.resultsUpdated++ itemsToFindCovers.push(libraryItem) @@ -235,27 +242,31 @@ class Scanner { // Potential NEW Library Items for (let i = 0; i < libraryItemDataFound.length; i++) { var dataFound = libraryItemDataFound[i] - + console.log('Potential new library item data') var hasMediaFile = dataFound.libraryFiles.some(lf => lf.isMediaFile) if (!hasMediaFile) { libraryScan.addLog(LogLevel.WARN, `Item found "${libraryItemDataFound.path}" has no media files`) } else { - var mediaFileSize = 0 - dataFound.libraryFiles.filter(lf => lf.fileType === 'audio' || lf.fileType === 'video').forEach(lf => mediaFileSize += lf.metadata.size) + if (global.ServerSettings.scannerUseSingleThreadedProber) { + // If this item will go over max size then push current chunk + var mediaFileSize = 0 + dataFound.libraryFiles.filter(lf => lf.fileType === 'audio' || lf.fileType === 'video').forEach(lf => mediaFileSize += lf.metadata.size) + if (mediaFileSize + newItemDataToScanSize > MaxSizePerChunk && newItemDataToScan.length > 0) { + newItemDataToScanChunks.push(newItemDataToScan) + newItemDataToScanSize = 0 + newItemDataToScan = [] + } - // If this item will go over max size then push current chunk - if (mediaFileSize + newItemDataToScanSize > MaxSizePerChunk && newItemDataToScan.length > 0) { - newItemDataToScanChunks.push(newItemDataToScan) - newItemDataToScanSize = 0 - newItemDataToScan = [] - } + newItemDataToScan.push(dataFound) + newItemDataToScanSize += mediaFileSize - newItemDataToScan.push(dataFound) - newItemDataToScanSize += mediaFileSize - if (newItemDataToScanSize >= MaxSizePerChunk) { - newItemDataToScanChunks.push(newItemDataToScan) - newItemDataToScanSize = 0 - newItemDataToScan = [] + if (newItemDataToScanSize >= MaxSizePerChunk) { + newItemDataToScanChunks.push(newItemDataToScan) + newItemDataToScanSize = 0 + newItemDataToScan = [] + } + } else { // Chunking is not necessary for new scanner + newItemDataToScan.push(dataFound) } } } @@ -272,14 +283,14 @@ class Scanner { await this.updateLibraryItemChunk(itemsToUpdate) if (this.cancelLibraryScan[libraryScan.libraryId]) return true } + + // Chunking will be removed when legacy single threaded scanner is removed for (let i = 0; i < itemDataToRescanChunks.length; i++) { await this.rescanLibraryItemDataChunk(itemDataToRescanChunks[i], libraryScan) if (this.cancelLibraryScan[libraryScan.libraryId]) return true - // console.log('Rescan chunk done', i, 'of', itemDataToRescanChunks.length) } for (let i = 0; i < newItemDataToScanChunks.length; i++) { await this.scanNewLibraryItemDataChunk(newItemDataToScanChunks[i], libraryScan) - // console.log('New scan chunk done', i, 'of', newItemDataToScanChunks.length) if (this.cancelLibraryScan[libraryScan.libraryId]) return true } } diff --git a/server/utils/probeWorker.js b/server/utils/probeWorker.js new file mode 100644 index 000000000..2a93fce93 --- /dev/null +++ b/server/utils/probeWorker.js @@ -0,0 +1,9 @@ +const { parentPort } = require("worker_threads") +const prober = require('./prober') + +parentPort.on("message", async ({ mediaPath }) => { + const results = await prober.probe(mediaPath) + parentPort.postMessage({ + data: results, + }) +}) \ No newline at end of file diff --git a/server/utils/prober.js b/server/utils/prober.js index ec047fbfb..770c235e4 100644 --- a/server/utils/prober.js +++ b/server/utils/prober.js @@ -220,19 +220,18 @@ function getDefaultAudioStream(audioStreams) { function parseProbeData(data, verbose = false) { try { var { format, streams, chapters } = data - var { format_long_name, duration, size, bit_rate } = format - var sizeBytes = !isNaN(size) ? Number(size) : null + var sizeBytes = !isNaN(format.size) ? Number(format.size) : null var sizeMb = sizeBytes !== null ? Number((sizeBytes / (1024 * 1024)).toFixed(2)) : null // Logger.debug('Parsing Data for', Path.basename(format.filename)) var tags = parseTags(format, verbose) var cleanedData = { - format: format_long_name, - duration: !isNaN(duration) ? Number(duration) : null, + format: format.format_long_name || format.name || 'Unknown', + duration: !isNaN(format.duration) ? Number(format.duration) : null, size: sizeBytes, sizeMb, - bit_rate: !isNaN(bit_rate) ? Number(bit_rate) : null, + bit_rate: !isNaN(format.bit_rate) ? Number(format.bit_rate) : null, ...tags } if (verbose && format.tags) { @@ -278,6 +277,12 @@ function probe(filepath, verbose = false) { return ffprobe(filepath) .then(raw => { + if (raw.error) { + return { + error: raw.error.string + } + } + var rawProbeData = parseProbeData(raw, verbose) if (!rawProbeData || (!rawProbeData.audio_stream && !rawProbeData.video_stream)) { return { From 7b83ab897035a6cb5c839efc0c8d5dfd7373fe81 Mon Sep 17 00:00:00 2001 From: revilo951 Date: Mon, 18 Jul 2022 10:12:02 +1000 Subject: [PATCH 030/100] Add restart and fix volumes Added `restart: unless-stopped` Adjust volumes - probably shouldn't be scattering the volumes around the root dir? https://docs.docker.com/compose/compose-file/compose-file-v3/#short-syntax-3 --- docker-compose.yml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index 2f2d995b8..43acbface 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -7,6 +7,7 @@ services: ports: - 13378:80 volumes: - - /audiobooks:/audiobooks - - /metadata:/metadata - - /config:/config + - ./audiobooks:/audiobooks + - ./metadata:/metadata + - ./config:/config + restart: unless-stopped From 9e7b84f28915876564544dfa0132e8f1104f09f2 Mon Sep 17 00:00:00 2001 From: advplyr Date: Mon, 18 Jul 2022 17:19:16 -0500 Subject: [PATCH 031/100] Update:JWT signing --- client/components/modals/AccountModal.vue | 11 +++++++-- client/pages/config/users/_id/index.vue | 26 ++++++++++++--------- client/store/user.js | 4 ++++ index.js | 1 - server/Auth.js | 28 +++++++++++++++++++---- server/Server.js | 9 +++++--- server/controllers/MiscController.js | 2 +- server/controllers/UserController.js | 8 ++++++- server/objects/settings/ServerSettings.js | 11 ++++++++- 9 files changed, 76 insertions(+), 24 deletions(-) diff --git a/client/components/modals/AccountModal.vue b/client/components/modals/AccountModal.vue index 8f572b224..454374584 100644 --- a/client/components/modals/AccountModal.vue +++ b/client/components/modals/AccountModal.vue @@ -146,7 +146,6 @@ export default { watch: { show: { handler(newVal) { - console.log('accoutn modal show change', newVal) if (newVal) { this.init() } @@ -162,6 +161,9 @@ export default { this.$emit('input', val) } }, + user() { + return this.$store.state.user.user + }, title() { return this.isNew ? 'Add New Account' : `Update ${(this.account || {}).username}` }, @@ -250,6 +252,12 @@ export default { this.$toast.error(`Failed to update account: ${data.error}`) } else { console.log('Account updated', data.user) + + if (data.user.id === this.user.id && data.user.token !== this.user.token) { + console.log('Current user token was updated') + this.$store.commit('user/setUserToken', data.user.token) + } + this.$toast.success('Account updated') this.show = false } @@ -305,7 +313,6 @@ export default { this.isNew = !this.account if (this.account) { - console.log(this.account) this.newUser = { username: this.account.username, password: this.account.password, diff --git a/client/pages/config/users/_id/index.vue b/client/pages/config/users/_id/index.vue index ed234e35b..78b9d0e07 100644 --- a/client/pages/config/users/_id/index.vue +++ b/client/pages/config/users/_id/index.vue @@ -13,11 +13,12 @@

    {{ username }}

    -
    -

    - API Token:
    {{ userToken }}content_copy -

    +
    + + +
    + content_copy +
    @@ -138,12 +139,15 @@ export default { this.$copyToClipboard(str, this) }, async init() { - this.listeningSessions = await this.$axios.$get(`/api/users/${this.user.id}/listening-sessions?page=0&itemsPerPage=10`).then((data) => { - return data.sessions || [] - }).catch((err) => { - console.error('Failed to load listening sesions', err) - return [] - }) + this.listeningSessions = await this.$axios + .$get(`/api/users/${this.user.id}/listening-sessions?page=0&itemsPerPage=10`) + .then((data) => { + return data.sessions || [] + }) + .catch((err) => { + console.error('Failed to load listening sesions', err) + return [] + }) this.listeningStats = await this.$axios.$get(`/api/users/${this.user.id}/listening-stats`).catch((err) => { console.error('Failed to load listening sesions', err) return [] diff --git a/client/store/user.js b/client/store/user.js index 9913c684d..c5daa9cec 100644 --- a/client/store/user.js +++ b/client/store/user.js @@ -136,6 +136,10 @@ export const mutations = { localStorage.removeItem('token') } }, + setUserToken(state, token) { + state.user.token = token + localStorage.setItem('token', user.token) + }, updateMediaProgress(state, { id, data }) { if (!state.user) return if (!data) { diff --git a/index.js b/index.js index 4400312e7..c15a9e0b0 100644 --- a/index.js +++ b/index.js @@ -1,4 +1,3 @@ -if (process.env.TOKEN_SECRET == null) process.env.TOKEN_SECRET = '09f26e402586e2faa8da4c98a35f1b20d6b033c6097befa8be3486a829587fe2f90a832bd3ff9d42710a4da095a2ce285b009f0c3730cd9b8e1af3eb84df6611' const server = require('./server/Server') global.appRoot = __dirname diff --git a/server/Auth.js b/server/Auth.js index 29fdbffcf..68bc09339 100644 --- a/server/Auth.js +++ b/server/Auth.js @@ -31,6 +31,26 @@ class Auth { } } + async initTokenSecret() { + if (process.env.TOKEN_SECRET) { // User can supply their own token secret + Logger.debug(`[Auth] Setting token secret - using user passed in TOKEN_SECRET env var`) + this.db.serverSettings.tokenSecret = process.env.TOKEN_SECRET + } else { + Logger.debug(`[Auth] Setting token secret - using random bytes`) + this.db.serverSettings.tokenSecret = require('crypto').randomBytes(256).toString('base64') + } + await this.db.updateServerSettings() + + // New token secret creation added in v2.1.0 so generate new API tokens for each user + if (this.db.users.length) { + for (const user of this.db.users) { + user.token = await this.generateAccessToken({ userId: user.id, username: user.username }) + Logger.warn(`[Auth] User ${user.username} api token has been updated using new token secret`) + } + await this.db.updateEntities('user', this.db.users) + } + } + async authMiddleware(req, res, next) { var token = null @@ -74,7 +94,7 @@ class Auth { } generateAccessToken(payload) { - return jwt.sign(payload, process.env.TOKEN_SECRET); + return jwt.sign(payload, global.ServerSettings.tokenSecret); } authenticateUser(token) { @@ -83,12 +103,12 @@ class Auth { verifyToken(token) { return new Promise((resolve) => { - jwt.verify(token, process.env.TOKEN_SECRET, (err, payload) => { + jwt.verify(token, global.ServerSettings.tokenSecret, (err, payload) => { if (!payload || err) { Logger.error('JWT Verify Token Failed', err) return resolve(null) } - var user = this.users.find(u => u.id === payload.userId) + var user = this.users.find(u => u.id === payload.userId && u.username === payload.username) resolve(user || null) }) }) @@ -98,7 +118,7 @@ class Auth { return { user: user.toJSONForBrowser(), userDefaultLibraryId: user.getDefaultLibraryId(this.db.libraries), - serverSettings: this.db.serverSettings.toJSON(), + serverSettings: this.db.serverSettings.toJSONForBrowser(), Source: global.Source } } diff --git a/server/Server.js b/server/Server.js index 0d75eaeaa..b80a6942c 100644 --- a/server/Server.js +++ b/server/Server.js @@ -136,6 +136,11 @@ class Server { await this.db.init() } + // Create token secret if does not exist (Added v2.1.0) + if (!this.db.serverSettings.tokenSecret) { + await this.auth.initTokenSecret() + } + await this.checkUserMediaProgress() // Remove invalid user item progress await this.purgeMetadata() // Remove metadata folders without library item await this.cacheManager.ensureCachePaths() @@ -314,7 +319,7 @@ class Server { const newRoot = req.body.newRoot let rootPash = newRoot.password ? await this.auth.hashPass(newRoot.password) : '' if (!rootPash) Logger.warn(`[Server] Creating root user with no password`) - let rootToken = await this.auth.generateAccessToken({ userId: 'root' }) + let rootToken = await this.auth.generateAccessToken({ userId: 'root', username: newRoot.username }) await this.db.createRootUser(newRoot.username, rootPash, rootToken) res.sendStatus(200) @@ -459,8 +464,6 @@ class Server { await this.db.updateEntity('user', user) const initialPayload = { - // TODO: this is sent with user auth now, update mobile app to use that then remove this - serverSettings: this.db.serverSettings.toJSON(), metadataPath: global.MetadataPath, configPath: global.ConfigPath, user: client.user.toJSONForBrowser(), diff --git a/server/controllers/MiscController.js b/server/controllers/MiscController.js index 399ce7428..c760b7daa 100644 --- a/server/controllers/MiscController.js +++ b/server/controllers/MiscController.js @@ -242,7 +242,7 @@ class MiscController { const userResponse = { user: req.user, userDefaultLibraryId: req.user.getDefaultLibraryId(this.db.libraries), - serverSettings: this.db.serverSettings.toJSON(), + serverSettings: this.db.serverSettings.toJSONForBrowser(), Source: global.Source } res.json(userResponse) diff --git a/server/controllers/UserController.js b/server/controllers/UserController.js index f8b496384..6e2f4b9bc 100644 --- a/server/controllers/UserController.js +++ b/server/controllers/UserController.js @@ -43,7 +43,7 @@ class UserController { account.id = getId('usr') account.pash = await this.auth.hashPass(account.password) delete account.password - account.token = await this.auth.generateAccessToken({ userId: account.id }) + account.token = await this.auth.generateAccessToken({ userId: account.id, username }) account.createdAt = Date.now() var newUser = new User(account) var success = await this.db.insertEntity('user', newUser) @@ -74,12 +74,14 @@ class UserController { } var account = req.body + var shouldUpdateToken = false if (account.username !== undefined && account.username !== user.username) { var usernameExists = this.db.users.find(u => u.username.toLowerCase() === account.username.toLowerCase()) if (usernameExists) { return res.status(500).send('Username already taken') } + shouldUpdateToken = true } // Updating password @@ -90,6 +92,10 @@ class UserController { var hasUpdated = user.update(account) if (hasUpdated) { + if (shouldUpdateToken) { + user.token = await this.auth.generateAccessToken({ userId: user.id, username: user.username }) + Logger.info(`[UserController] User ${user.username} was generated a new api token`) + } await this.db.updateEntity('user', user) } diff --git a/server/objects/settings/ServerSettings.js b/server/objects/settings/ServerSettings.js index 4860d494a..ddb8a086d 100644 --- a/server/objects/settings/ServerSettings.js +++ b/server/objects/settings/ServerSettings.js @@ -5,6 +5,7 @@ const Logger = require('../../Logger') class ServerSettings { constructor(settings) { this.id = 'server-settings' + this.tokenSecret = null // Scanner this.scannerParseSubtitle = false @@ -63,6 +64,7 @@ class ServerSettings { } construct(settings) { + this.tokenSecret = settings.tokenSecret this.scannerFindCovers = !!settings.scannerFindCovers this.scannerCoverProvider = settings.scannerCoverProvider || 'google' this.scannerParseSubtitle = settings.scannerParseSubtitle @@ -110,9 +112,10 @@ class ServerSettings { } } - toJSON() { + toJSON() { // Use toJSONForBrowser if sending to client return { id: this.id, + tokenSecret: this.tokenSecret, // Do not return to client scannerFindCovers: this.scannerFindCovers, scannerCoverProvider: this.scannerCoverProvider, scannerParseSubtitle: this.scannerParseSubtitle, @@ -145,6 +148,12 @@ class ServerSettings { } } + toJSONForBrowser() { + const json = this.toJSON() + delete json.tokenSecret + return json + } + update(payload) { var hasUpdates = false for (const key in payload) { From 1c9e56ce2e76deafbc9fbb962f3cde76cc9f287e Mon Sep 17 00:00:00 2001 From: advplyr Date: Mon, 18 Jul 2022 17:44:01 -0500 Subject: [PATCH 032/100] Fix:Libraries table to use draggable handle for items so they can be clicked and edited #839 --- client/assets/draggable.css | 13 ++++++++++--- client/components/tables/library/LibrariesTable.vue | 2 +- client/components/tables/library/LibraryItem.vue | 2 +- 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/client/assets/draggable.css b/client/assets/draggable.css index 48dca6b80..31271e675 100644 --- a/client/assets/draggable.css +++ b/client/assets/draggable.css @@ -1,34 +1,40 @@ .flip-list-move { transition: transform 0.5s; } + .no-move { transition: transform 0s; } + .ghost { opacity: 0.5; background-color: rgba(255, 255, 255, 0.25); } + .list-group { min-height: 30px; } -#librariesTable .item { - cursor: n-resize; -} + .drag-handle { cursor: n-resize; } + .list-group-item:not(.exclude) { cursor: n-resize; } + .list-group-item.exclude { cursor: not-allowed; } + .list-group-item:not(.ghost):not(.exclude):hover { background-color: rgba(0, 0, 0, 0.1); } + .list-group-item:nth-child(even):not(.ghost):not(.exclude) { background-color: rgba(0, 0, 0, 0.25); } + .list-group-item:nth-child(even):not(.ghost):not(.exclude):hover { background-color: rgba(0, 0, 0, 0.1); } @@ -36,6 +42,7 @@ .list-group-item.exclude:not(.ghost) { background-color: rgba(255, 0, 0, 0.25); } + .list-group-item.exclude:not(.ghost):hover { background-color: rgba(223, 0, 0, 0.25); } \ No newline at end of file diff --git a/client/components/tables/library/LibrariesTable.vue b/client/components/tables/library/LibrariesTable.vue index 329f0a1ec..86ddec476 100644 --- a/client/components/tables/library/LibrariesTable.vue +++ b/client/components/tables/library/LibrariesTable.vue @@ -6,7 +6,7 @@ add
    - + diff --git a/client/pages/config/sessions.vue b/client/pages/config/sessions.vue index 628d58bc4..8eb3c5980 100644 --- a/client/pages/config/sessions.vue +++ b/client/pages/config/sessions.vue @@ -39,7 +39,7 @@

    {{ $elapsedPretty(session.timeListening) }}

    - +

    {{ $secondsToTimestamp(session.currentTime) }}

    @@ -57,7 +57,7 @@

    No sessions yet...

    - + @@ -89,7 +89,8 @@ export default { total: 0, currentPage: 0, userFilter: null, - selectedUser: '' + selectedUser: '', + processingGoToTimestamp: false } }, computed: { @@ -110,6 +111,41 @@ export default { } }, methods: { + async clickCurrentTime(session) { + if (this.processingGoToTimestamp) return + this.processingGoToTimestamp = true + const libraryItem = await this.$axios.$get(`/api/items/${session.libraryItemId}`).catch((error) => { + console.error('Failed to get library item', error) + return null + }) + + if (!libraryItem) { + this.$toast.error('Failed to get library item') + this.processingGoToTimestamp = false + return + } + if (session.episodeId && !libraryItem.media.episodes.find((ep) => ep.id === session.episodeId)) { + this.$toast.error('Failed to get podcast episode') + this.processingGoToTimestamp = false + return + } + + const payload = { + message: `Start playback for "${session.displayTitle}" at ${this.$secondsToTimestamp(session.currentTime)}?`, + callback: (confirmed) => { + if (confirmed) { + this.$eventBus.$emit('play-item', { + libraryItemId: libraryItem.id, + episodeId: session.episodeId || null, + startTime: session.currentTime + }) + } + this.processingGoToTimestamp = false + }, + type: 'yesNo' + } + this.$store.commit('globals/setConfirmPrompt', payload) + }, updateUserFilter() { this.loadSessions(0) }, diff --git a/client/store/globals.js b/client/store/globals.js index f1bb51f4b..8a5edc36a 100644 --- a/client/store/globals.js +++ b/client/store/globals.js @@ -6,6 +6,8 @@ export const state = () => ({ showEditCollectionModal: false, showEditPodcastEpisode: false, showViewPodcastEpisodeModal: false, + showConfirmPrompt: false, + confirmPromptOptions: null, showEditAuthorModal: false, selectedEpisode: null, selectedCollection: null, @@ -69,6 +71,13 @@ export const mutations = { setShowViewPodcastEpisodeModal(state, val) { state.showViewPodcastEpisodeModal = val }, + setShowConfirmPrompt(state, val) { + state.showConfirmPrompt = val + }, + setConfirmPrompt(state, options) { + state.confirmPromptOptions = options + state.showConfirmPrompt = true + }, setEditCollection(state, collection) { state.selectedCollection = collection state.showEditCollectionModal = true From 3cf8b9dca9de91a11261e7e8252613f906f3ace0 Mon Sep 17 00:00:00 2001 From: advplyr Date: Sat, 30 Jul 2022 11:53:48 -0500 Subject: [PATCH 051/100] Update start playback from bookmark time confirm to new confirm prompt --- .../components/modals/bookmarks/BookmarkItem.vue | 2 +- client/pages/item/_id/index.vue | 14 +++++++++++--- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/client/components/modals/bookmarks/BookmarkItem.vue b/client/components/modals/bookmarks/BookmarkItem.vue index 68ff834f2..fc35bf33e 100644 --- a/client/components/modals/bookmarks/BookmarkItem.vue +++ b/client/components/modals/bookmarks/BookmarkItem.vue @@ -1,5 +1,5 @@