diff --git a/package-lock.json b/package-lock.json index fd75013..b6a01ff 100644 --- a/package-lock.json +++ b/package-lock.json @@ -506,17 +506,20 @@ "ansi-colors": { "version": "3.2.3", "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.3.tgz", - "integrity": "sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw==" + "integrity": "sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw==", + "dev": true }, "ansi-regex": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==" + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true }, "ansi-styles": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, "requires": { "color-convert": "^1.9.0" } @@ -566,6 +569,7 @@ "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, "requires": { "sprintf-js": "~1.0.2" } @@ -883,7 +887,8 @@ "browser-stdout": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", - "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==" + "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", + "dev": true }, "browserify-aes": { "version": "1.2.0", @@ -1071,7 +1076,8 @@ "camelcase": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==" + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true }, "caseless": { "version": "0.12.0", @@ -1082,6 +1088,7 @@ "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, "requires": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", @@ -1199,6 +1206,7 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", + "dev": true, "requires": { "string-width": "^3.1.0", "strip-ansi": "^5.2.0", @@ -1229,6 +1237,7 @@ "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, "requires": { "color-name": "1.1.3" } @@ -1236,7 +1245,8 @@ "color-name": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true }, "colorette": { "version": "1.0.8", @@ -1491,7 +1501,8 @@ "decamelize": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true }, "decode-uri-component": { "version": "0.2.0", @@ -1729,7 +1740,8 @@ "diff": { "version": "3.5.0", "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", - "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==" + "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", + "dev": true }, "diffie-hellman": { "version": "5.0.3", @@ -1800,7 +1812,8 @@ "emoji-regex": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==" + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "dev": true }, "emojis-list": { "version": "2.1.0", @@ -1877,7 +1890,8 @@ "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=" + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true }, "escodegen": { "version": "1.13.0", @@ -1911,7 +1925,8 @@ "esprima": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true }, "esrecurse": { "version": "4.2.1", @@ -2301,6 +2316,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, "requires": { "locate-path": "^3.0.0" } @@ -2352,6 +2368,7 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/flat/-/flat-4.1.0.tgz", "integrity": "sha512-Px/TiLIznH7gEDlPXcUD4KnBusa6kR6ayRUVcnEAbreRIuhkqow/mun59BuRXwoYk7ZQOLW1ZM05ilIvK38hFw==", + "dev": true, "requires": { "is-buffer": "~2.0.3" }, @@ -2359,7 +2376,8 @@ "is-buffer": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.4.tgz", - "integrity": "sha512-Kq1rokWXOPXWuaMAqZiJW4XxsmD9zGx9q4aePabbn3qCRGedtH7Cm+zV8WETitMfu1wdh+Rvd6w5egwSngUX2A==" + "integrity": "sha512-Kq1rokWXOPXWuaMAqZiJW4XxsmD9zGx9q4aePabbn3qCRGedtH7Cm+zV8WETitMfu1wdh+Rvd6w5egwSngUX2A==", + "dev": true } } }, @@ -3219,7 +3237,8 @@ "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==" + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true }, "get-own-enumerable-property-symbols": { "version": "3.0.2", @@ -3406,7 +3425,8 @@ "growl": { "version": "1.10.5", "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", - "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==" + "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", + "dev": true }, "har-schema": { "version": "2.0.0", @@ -3433,7 +3453,8 @@ "has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true }, "has-symbols": { "version": "1.0.0", @@ -3497,7 +3518,8 @@ "he": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==" + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "dev": true }, "hmac-drbg": { "version": "1.0.1", @@ -3929,6 +3951,7 @@ "version": "3.13.1", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", + "dev": true, "requires": { "argparse": "^1.0.7", "esprima": "^4.0.0" @@ -4103,6 +4126,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, "requires": { "p-locate": "^3.0.0", "path-exists": "^3.0.0" @@ -4117,6 +4141,7 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==", + "dev": true, "requires": { "chalk": "^2.0.1" } @@ -4505,6 +4530,7 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/mocha/-/mocha-7.0.0.tgz", "integrity": "sha512-CirsOPbO3jU86YKjjMzFLcXIb5YiGLUrjrXFHoJ3e2z9vWiaZVCZQ2+gtRGMPWF+nFhN6AWwLM/juzAQ6KRkbA==", + "dev": true, "requires": { "ansi-colors": "3.2.3", "browser-stdout": "1.3.1", @@ -4536,6 +4562,7 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==", + "dev": true, "requires": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" @@ -4544,12 +4571,14 @@ "binary-extensions": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.0.0.tgz", - "integrity": "sha512-Phlt0plgpIIBOGTT/ehfFnbNlfsDEiqmzE2KRXoX1bLIlir4X/MR+zSyBEkL05ffWgnRSf/DXv+WrUAVr93/ow==" + "integrity": "sha512-Phlt0plgpIIBOGTT/ehfFnbNlfsDEiqmzE2KRXoX1bLIlir4X/MR+zSyBEkL05ffWgnRSf/DXv+WrUAVr93/ow==", + "dev": true }, "braces": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, "requires": { "fill-range": "^7.0.1" } @@ -4558,6 +4587,7 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.3.0.tgz", "integrity": "sha512-dGmKLDdT3Gdl7fBUe8XK+gAtGmzy5Fn0XkkWQuYxGIgWVPPse2CxFA5mtrlD0TOHaHjEUqkWNyP1XdHoJES/4A==", + "dev": true, "requires": { "anymatch": "~3.1.1", "braces": "~3.0.2", @@ -4573,6 +4603,7 @@ "version": "3.2.6", "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "dev": true, "requires": { "ms": "^2.1.1" } @@ -4581,6 +4612,7 @@ "version": "7.0.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, "requires": { "to-regex-range": "^5.0.1" } @@ -4589,12 +4621,14 @@ "version": "2.1.2", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.2.tgz", "integrity": "sha512-R4wDiBwZ0KzpgOWetKDug1FZcYhqYnUYKtfZYt4mD5SBz76q0KR4Q9o7GIPamsVPGmW3EYPPJ0dOOjvx32ldZA==", + "dev": true, "optional": true }, "glob": { "version": "7.1.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", + "dev": true, "requires": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -4608,6 +4642,7 @@ "version": "5.1.0", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.0.tgz", "integrity": "sha512-qjtRgnIVmOfnKUE3NJAQEdk+lKrxfw8t5ke7SXtfMTHcjsBfOfWXCQfdb30zfDoZQ2IRSIiidmjtbHZPZ++Ihw==", + "dev": true, "requires": { "is-glob": "^4.0.1" } @@ -4616,6 +4651,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, "requires": { "binary-extensions": "^2.0.0" } @@ -4623,12 +4659,14 @@ "is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=" + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true }, "is-glob": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "dev": true, "requires": { "is-extglob": "^2.1.1" } @@ -4636,12 +4674,14 @@ "is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true }, "minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, "requires": { "brace-expansion": "^1.1.7" } @@ -4649,12 +4689,14 @@ "ms": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true }, "readdirp": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.2.0.tgz", "integrity": "sha512-crk4Qu3pmXwgxdSgGhgA/eXiJAPQiX4GMOZZMXnqKxHX7TaoL+3gQVo/WeuAiogr07DpnfjIMpXXa+PAIvwPGQ==", + "dev": true, "requires": { "picomatch": "^2.0.4" } @@ -4663,6 +4705,7 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.0.0.tgz", "integrity": "sha512-on9Kwidc1IUQo+bQdhi8+Tijpo0e1SS6RoGo2guUwn5vdaxw8RXOF9Vb2ws+ihWOmh4JnCJOvaziZWP1VABaLg==", + "dev": true, "requires": { "has-flag": "^3.0.0" } @@ -4671,6 +4714,7 @@ "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==", + "dev": true, "requires": { "is-number": "^7.0.0" } @@ -4679,6 +4723,7 @@ "version": "13.3.0", "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.0.tgz", "integrity": "sha512-2eehun/8ALW8TLoIl7MVaRUrg+yCnenu8B4kBlRxj3GJGDKU1Og7sMXPNm1BYyM1DOJmTZ4YeN/Nwxv+8XJsUA==", + "dev": true, "requires": { "cliui": "^5.0.0", "find-up": "^3.0.0", @@ -4870,6 +4915,7 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/node-environment-flags/-/node-environment-flags-1.0.6.tgz", "integrity": "sha512-5Evy2epuL+6TM0lCQGpFIj6KwiEsGh1SrHUhTbNX+sLbBtjidPZFAnVK9y5yU1+h//RitLbRHTIMyxQPtxMdHw==", + "dev": true, "requires": { "object.getownpropertydescriptors": "^2.0.3", "semver": "^5.7.0" @@ -4981,7 +5027,8 @@ "normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==" + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true }, "npm-bundled": { "version": "1.0.6", @@ -5082,6 +5129,7 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", + "dev": true, "requires": { "define-properties": "^1.1.2", "function-bind": "^1.1.1", @@ -5367,6 +5415,7 @@ "version": "2.2.1", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.1.tgz", "integrity": "sha512-85Tk+90UCVWvbDavCLKPOLC9vvY8OwEX/RtKF+/1OADJMVlFfEHOiMTPVyxg7mk/dKa+ipdHm0OUkTvCpMTuwg==", + "dev": true, "requires": { "p-try": "^2.0.0" } @@ -5375,6 +5424,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, "requires": { "p-limit": "^2.0.0" } @@ -5550,7 +5600,8 @@ "picomatch": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.1.tgz", - "integrity": "sha512-ISBaA8xQNmwELC7eOjqFKMESB2VIqt4PPDD0nsS95b/9dZXvVKOlz9keMSnoGGKcOHXfTvDD6WMaRoSc9UuhRA==" + "integrity": "sha512-ISBaA8xQNmwELC7eOjqFKMESB2VIqt4PPDD0nsS95b/9dZXvVKOlz9keMSnoGGKcOHXfTvDD6WMaRoSc9UuhRA==", + "dev": true }, "pify": { "version": "3.0.0", @@ -5940,12 +5991,14 @@ "require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=" + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "dev": true }, "require-main-filename": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", - "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==" + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", + "dev": true }, "requirejs": { "version": "2.3.6", @@ -6461,7 +6514,8 @@ "sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true }, "sqlite3": { "version": "4.1.0", @@ -6605,6 +6659,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, "requires": { "emoji-regex": "^7.0.1", "is-fullwidth-code-point": "^2.0.0", @@ -6652,6 +6707,7 @@ "version": "5.2.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, "requires": { "ansi-regex": "^4.1.0" } @@ -6680,6 +6736,7 @@ "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, "requires": { "has-flag": "^3.0.0" } @@ -7306,7 +7363,8 @@ "which-module": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=" + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", + "dev": true }, "wide-align": { "version": "1.1.3", @@ -7359,6 +7417,7 @@ "version": "5.1.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", + "dev": true, "requires": { "ansi-styles": "^3.2.0", "string-width": "^3.0.0", @@ -7421,7 +7480,8 @@ "y18n": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", - "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==" + "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", + "dev": true }, "yallist": { "version": "2.1.2", @@ -7451,6 +7511,7 @@ "version": "13.1.1", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.1.tgz", "integrity": "sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ==", + "dev": true, "requires": { "camelcase": "^5.0.0", "decamelize": "^1.2.0" @@ -7460,6 +7521,7 @@ "version": "1.6.0", "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-1.6.0.tgz", "integrity": "sha512-W9tKgmSn0DpSatfri0nx52Joq5hVXgeLiqR/5G0sZNDoLZFOr/xjBUDcShCOGNsBnEMNo1KAMBkTej1Hm62HTw==", + "dev": true, "requires": { "flat": "^4.1.0", "lodash": "^4.17.15", @@ -7470,6 +7532,7 @@ "version": "13.3.0", "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.0.tgz", "integrity": "sha512-2eehun/8ALW8TLoIl7MVaRUrg+yCnenu8B4kBlRxj3GJGDKU1Og7sMXPNm1BYyM1DOJmTZ4YeN/Nwxv+8XJsUA==", + "dev": true, "requires": { "cliui": "^5.0.0", "find-up": "^3.0.0", diff --git a/package.json b/package.json index 24dd6c5..d94eeb2 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,8 @@ "version": "1.0.0", "scripts": { "tsc": "tsc", - "start": "npm run build; node lib/src/Launcher.js", + "start": "npm run build; node lib/src/backend/Launcher.js", + "start-backend": "npm run build-backend; node lib/src/backend/Launcher.js", "build": "npm run clean; npm run build-backend; npm run build-frontend", "test": "npm run clean && npm run build-backend && mocha lib/test/backendTest.js", "build-backend": "tsc;", @@ -36,7 +37,6 @@ "loadson": "^1.0.0", "log4js": "^4.5.1", "lowdb": "^1.0.0", - "mocha": "^7.0.0", "node-fetch": "^2.6.0", "path": "^0.12.7", "reflect-metadata": "^0.1.13", @@ -56,6 +56,7 @@ "@types/node": "^11.13.19", "@types/semver": "^6.0.1", "madge": "^3.6.0", + "mocha": "^7.0.0", "terser-webpack-plugin": "^1.4.1", "ts-loader": "^5.3.3", "typescript": "^3.5.3", diff --git a/src/backend/Admin/Admin.ts b/src/backend/Admin/Admin.ts index 14775a8..27a4a7e 100644 --- a/src/backend/Admin/Admin.ts +++ b/src/backend/Admin/Admin.ts @@ -10,14 +10,15 @@ import * as express from 'express'; import { GuildManager } from '../Components/Guild/GuildManager'; import { ItemManager } from '../Components/Item/ItemManager'; import { RaidManager } from '../Components/Raid/RaidManager'; -import { CharacterManager } from '../Components/User/CharacterManager'; -import { LoginManager } from '../Components/User/LoginManager'; +import { CharacterManager } from '../Components/Character/CharacterManager'; +import { LoginManager } from '../Components/Login/LoginManager'; import { RootComponent } from '../Injector/ServiceDecorator'; import { TableDefinitionExporter } from '../Types/Interfaces'; import { AdminConf, TableDefiniton } from '../Types/Types'; import { RPCConfigLoader } from '../Components/RPCConfigLoader'; import { FrontworkComponent } from '../Types/FrontworkComponent'; import { IAdmin } from './Interface'; +import { Injector } from '../Injector/Injector'; const logger = getLogger("admin", 'debug') @@ -64,11 +65,16 @@ implements TableDefinitionExporter, IAdmin { await this.makeKnex() this.startWebsocket() await Promise.all( this.frontworkComponents.map(c => c.initialize?c.initialize():undefined )) + logger.debug(this.frontworkComponents.length+" components initialized") this.startWebserver() } stop(){ - process.exit(0); + Promise.race([ + Promise.all( this.frontworkComponents.map(c => c.stop?c.stop():undefined )), + new Promise((res, rej) => { setTimeout(res, 250);}) + ]).catch(e => logger.warn(e)) + .finally(() => { process.exit(0) }) } protected configChangeHandler = (conf:AdminConf, key?:string) => { @@ -95,6 +101,7 @@ implements TableDefinitionExporter, IAdmin { this.rpcServer = new RPCServer(20000, [ ...this.frontworkComponents, ]) + logger.debug("Websocket up on", 20000) } private startWebserver(){ @@ -183,6 +190,5 @@ implements TableDefinitionExporter, IAdmin { process.on( 'SIGINT', function() { logger.info("Shutting down from SIGINT (Ctrl-C)" ); - // some other closing procedures go here - process.exit(0); + Injector.resolve(FrontworkAdmin).stop() }) diff --git a/src/backend/Components/User/CharacterManager.ts b/src/backend/Components/Character/CharacterManager.ts similarity index 88% rename from src/backend/Components/User/CharacterManager.ts rename to src/backend/Components/Character/CharacterManager.ts index 2496bc7..2371004 100644 --- a/src/backend/Components/User/CharacterManager.ts +++ b/src/backend/Components/Character/CharacterManager.ts @@ -3,20 +3,22 @@ import { Inject, Module } from "../../Injector/ServiceDecorator"; import { TableDefiniton, Character } from "../../Types/Types"; import { CharacterManagerIfc } from "./RPCInterface"; import { FrontworkComponent } from "../../Types/FrontworkComponent"; -import { FrontworkAdmin } from "../../Admin/Admin"; -import { LoginManager } from "./LoginManager"; import { getSpecTableData, SpecT } from "../../Types/PlayerSpecs"; import { IAdmin } from "../../Admin/Interface"; +import { ILoginManager } from "../Login/Interface"; +import { ICharacterManager } from "./Interface"; +import { getLogger } from "log4js"; -@Module() +@Module(ICharacterManager) export class CharacterManager -implements FrontworkComponent{ +implements FrontworkComponent, ICharacterManager{ name = "CharacterManager" as "CharacterManager"; @Inject(IAdmin) private admin: IAdmin - private loginManager : LoginManager + @Inject(ILoginManager) + private loginManager : any exportRPCs = () => [ { @@ -60,17 +62,20 @@ implements FrontworkComponent{ ] private initialized = false + initialize = async () => { - if(!this.initialized) this.initialized = true //initialize spec table + + getLogger('CharacterManager').debug('inserting specs') + await this.admin.knex('specs').insert(getSpecTableData()).catch(e => { console.log("skipping spec insertion") }) } createCharacter = async (userToken: string, character : Character) : Promise => { try{ - + const user = this.loginManager.getUserRecordByToken(userToken) await this.admin.knex('characters').insert(character) const char : Character = await this.admin.knex.select('*').from('characters').where(character).first() return char diff --git a/src/backend/Components/Character/Interface.ts b/src/backend/Components/Character/Interface.ts new file mode 100644 index 0000000..b601621 --- /dev/null +++ b/src/backend/Components/Character/Interface.ts @@ -0,0 +1,9 @@ +import { Character } from "../../Types/Types" +import { SpecT } from "../../Types/PlayerSpecs" + + +export class ICharacterManager{ + createCharacter: (usertoken: string, char : Character) => Promise + getSpecId: (clazz: c, name: SpecT[c]) => Promise + getCharacters: () => Promise +} \ No newline at end of file diff --git a/src/backend/Components/Character/RPCInterface.ts b/src/backend/Components/Character/RPCInterface.ts new file mode 100644 index 0000000..606421f --- /dev/null +++ b/src/backend/Components/Character/RPCInterface.ts @@ -0,0 +1,15 @@ +import { ICharacterManager } from "./Interface" + + +export type CharacterManagerIfc = { + CharacterManager: { + getSpecId : ICharacterManager['getSpecId'] + getCharacters : ICharacterManager['getCharacters'] + } +} + +export type CharacterManagerFeatureIfc = { + createCharacter: { + createCharacter: ICharacterManager['createCharacter'] + } +} \ No newline at end of file diff --git a/src/backend/Components/Guild/GuildManager.ts b/src/backend/Components/Guild/GuildManager.ts index dbf86cd..bd55a6a 100644 --- a/src/backend/Components/Guild/GuildManager.ts +++ b/src/backend/Components/Guild/GuildManager.ts @@ -1,10 +1,10 @@ import { ConfigLoader } from "loadson"; import { Inject, Module } from "../../Injector/ServiceDecorator"; import { GuildManagerFeatureIfc, GuildManagerIfc } from "./RPCInterface"; -import { FrontworkAdmin } from "../../Admin/Admin"; import { FrontworkComponent } from "../../Types/FrontworkComponent"; import { _Rank, Rank } from "../../Types/Types"; import { IAdmin } from "../../Admin/Interface"; +import { IGuildManager } from "./Interface"; export type Guild = { name: string @@ -12,55 +12,51 @@ export type Guild = { description: string } -@Module() +@Module(IGuildManager) export class GuildManager -implements FrontworkComponent{ +implements FrontworkComponent, IGuildManager{ name = "GuildManager" as "GuildManager"; @Inject(IAdmin) - private admin + private admin : IAdmin - guild: ConfigLoader - - constructor(){ - this.guild = new ConfigLoader({ - name: "guild", - getDefaultConfig: () => { - return { - name: "Tranquil", - realm: "Gandling EU", - description: "Wee woo" - } + guild: ConfigLoader = new ConfigLoader({ + name: "guild", + getDefaultConfig: () => { + return { + name: "Tranquil", + realm: "Gandling EU", + description: "Wee woo" } - }, "./config") - } + } + }, "./config") exportRPCs = () => [{ name: 'getHeadCount' as 'getHeadCount', - call: this.headCount + call: this.getHeadCount },{ name: 'getGuildInfo' as 'getGuildInfo', - call: async () => this.guild.getConfig() + call: this.getGuildInfo }] exportRPCFeatures = () => [{ name: 'manageGuild' as 'manageGuild', exportRPCs: () => [{ name: 'setName' as 'setName', - call: async (name:string) => this.guild.setConfigKey('name', name) + call: this.setName },{ name: 'setRealm' as 'setRealm', - call: async (realm:string) => this.guild.setConfigKey('realm', realm) + call: this.setRealm }, { name: 'setDescription' as 'setDescription', - call: async (description: string) => this.guild.setConfigKey('description', description) + call: this.setDescription }] }] getTableDefinitions = () => [] - headCount = async () => await Promise.all( + getHeadCount = async() : Promise<{ rank: Rank; count: number; }[]> => await Promise.all( _Rank.map(async r => { const res = await this.admin.knex .select('*') @@ -76,4 +72,8 @@ implements FrontworkComponent{ }) ) + getGuildInfo = async () => this.guild.getConfig() + setName = async (name:string) => this.guild.setConfigKey('name', name) + setDescription = async (description: string) => this.guild.setConfigKey('description', description) + setRealm = async (realm:string) => this.guild.setConfigKey('realm', realm) } \ No newline at end of file diff --git a/src/backend/Components/Guild/Interface.ts b/src/backend/Components/Guild/Interface.ts new file mode 100644 index 0000000..162f07c --- /dev/null +++ b/src/backend/Components/Guild/Interface.ts @@ -0,0 +1,10 @@ +import { Rank } from "../../Types/Types" +import { Guild } from "./GuildManager" + +export class IGuildManager{ + getHeadCount: () => Promise<{rank:Rank, count: number}[]> + getGuildInfo: () => Promise + setName: (name:string) => Promise + setRealm: (realm:string) => Promise + setDescription: (description:string) => Promise +} \ No newline at end of file diff --git a/src/backend/Components/Guild/RPCInterface.ts b/src/backend/Components/Guild/RPCInterface.ts index f5a708e..b3712d5 100644 --- a/src/backend/Components/Guild/RPCInterface.ts +++ b/src/backend/Components/Guild/RPCInterface.ts @@ -1,17 +1,16 @@ -import { Guild } from "./GuildManager" -import { Rank } from "../../Types/Types" +import { IGuildManager } from "./Interface" export type GuildManagerIfc = { GuildManager: { - getHeadCount: () => Promise<{rank:Rank, count: number}[]> - getGuildInfo: () => Promise + getHeadCount: IGuildManager['getHeadCount'] + getGuildInfo: IGuildManager['getGuildInfo'] } } export type GuildManagerFeatureIfc = { manageGuild: { - setName: (name:string) => Promise - setRealm: (realm:string) => Promise - setDescription: (description:string) => Promise + setName: IGuildManager['setName'] + setRealm: IGuildManager['setRealm'] + setDescription: IGuildManager['setDescription'] } } \ No newline at end of file diff --git a/src/backend/Components/Item/Interface.ts b/src/backend/Components/Item/Interface.ts new file mode 100644 index 0000000..650fd2a --- /dev/null +++ b/src/backend/Components/Item/Interface.ts @@ -0,0 +1,6 @@ +import { Item } from "../../Types/Types" + +export class IItemManager{ + getItems: () => Promise + getItem: (name:string) => Promise +} \ No newline at end of file diff --git a/src/backend/Components/Item/ItemManager.ts b/src/backend/Components/Item/ItemManager.ts index 4ba9825..b833034 100644 --- a/src/backend/Components/Item/ItemManager.ts +++ b/src/backend/Components/Item/ItemManager.ts @@ -4,30 +4,22 @@ import { Inject, Module } from "../../Injector/ServiceDecorator"; import { ItemManagerFeatureIfc, ItemManagerIfc } from "./RPCInterface"; import { FrontworkComponent } from "../../Types/FrontworkComponent"; import { TableDefinitionExporter } from "../../Types/Interfaces"; -import { FrontworkAdmin } from "../../Admin/Admin"; -import { TableDefiniton } from "../../Types/Types"; +import { TableDefiniton, Item } from "../../Types/Types"; import { IAdmin } from "../../Admin/Interface"; +import { IItemManager } from "./Interface"; +import { getLogger } from "log4js"; const fetch = require('node-fetch') const xml2js = require('xml2js'); const parser = new xml2js.Parser(/* options */); -export type Item = { - id?:number - name:string - iconname:string - url:string - quality:string - hidden:boolean -} - -@Module() +@Module(IItemManager) export class ItemManager -implements FrontworkComponent, TableDefinitionExporter{ +implements FrontworkComponent, TableDefinitionExporter, IItemManager{ name = "ItemManager" as "ItemManager"; @Inject(IAdmin) - private admin: FrontworkAdmin + private admin: IAdmin exportRPCs(): RPC[]{ return [{ @@ -99,6 +91,8 @@ implements FrontworkComponent, TableDefin this.initialized = true const allItems = [...T1] + getLogger('ItemManager').debug('Checking items') + const countCache = await this.countItems() if(countCache != allItems.length){ const items:Item[] = await Promise.all(allItems.map((i) => this.getItem(i))) @@ -107,8 +101,7 @@ implements FrontworkComponent, TableDefin .knex('items') .insert(items) }catch(e){ - console.log(e) - console.info("Skipping item insertion") + getLogger('ItemManager').debug("Skipping item insertion") } } } diff --git a/src/backend/Components/Item/RPCInterface.ts b/src/backend/Components/Item/RPCInterface.ts index f9c2ffd..288a4e4 100644 --- a/src/backend/Components/Item/RPCInterface.ts +++ b/src/backend/Components/Item/RPCInterface.ts @@ -1,4 +1,11 @@ -import { RPCInterface } from "rpclibrary" +import { IItemManager } from "./Interface" -export type ItemManagerIfc = RPCInterface -export type ItemManagerFeatureIfc = RPCInterface \ No newline at end of file +export type ItemManagerIfc = { + ItemManager: { + getItem: IItemManager['getItem'] + getItems: IItemManager['getItems'] + } +} + +export type ItemManagerFeatureIfc = { +} \ No newline at end of file diff --git a/src/backend/Components/Login/Interface.ts b/src/backend/Components/Login/Interface.ts new file mode 100644 index 0000000..7614db6 --- /dev/null +++ b/src/backend/Components/Login/Interface.ts @@ -0,0 +1,11 @@ +import { Auth, Rank, User, RPCPermission } from "../../Types/Types" + +export class ILoginManager{ + login: (username:string, pwHash:string) => Promise + logout: (username: string, tokenValue :string) => Promise + getAuth: (tokenValue: string) => Promise + createUser: (user:User) => Promise + setPermission: (perm: RPCPermission) => Promise + getPermissions: () => Promise + checkToken: (token: string, rank: Rank) => boolean +} \ No newline at end of file diff --git a/src/backend/Components/User/LoginManager.ts b/src/backend/Components/Login/LoginManager.ts similarity index 78% rename from src/backend/Components/User/LoginManager.ts rename to src/backend/Components/Login/LoginManager.ts index 2d5b4cb..248659e 100644 --- a/src/backend/Components/User/LoginManager.ts +++ b/src/backend/Components/Login/LoginManager.ts @@ -4,11 +4,13 @@ import { FrontworkAdmin } from "../../Admin/Admin"; import { GuildManager } from "../Guild/GuildManager"; import { ItemManager } from "../Item/ItemManager"; import { RaidManager } from "../Raid/RaidManager"; -import { CharacterManager } from "./CharacterManager"; +import { CharacterManager } from "../Character/CharacterManager"; import { LoginManagerIfc, LoginManagerFeatureIfc } from "./RPCInterface"; import { FrontworkComponent } from "../../Types/FrontworkComponent"; import { Rank, User, Auth, _Rank, TableDefiniton, RPCPermission, FrontcraftFeatureIfc, AnyRPCExporter, Token } from "../../Types/Types"; import { IAdmin } from "../../Admin/Interface"; +import { ILoginManager } from "./Interface"; +import { getLogger } from "log4js"; const uuid = require('uuid/v4') @@ -21,9 +23,9 @@ type Serverstate = { } -@Module() +@Module(ILoginManager) export class LoginManager -implements FrontworkComponent{ +implements FrontworkComponent, ILoginManager{ name = "Authenticator" as "Authenticator"; @Inject(IAdmin) @@ -61,7 +63,7 @@ implements FrontworkComponent{ call: this.getAuth },{ name: 'checkToken' as 'checkToken', - call: async (tokenValue : string, rank: Rank) => this.checkToken(tokenValue, rank) + call: this.checkToken },{ name: 'createUser' as 'createUser', call: this.createUser @@ -111,31 +113,52 @@ implements FrontworkComponent{ initialize = async () => { this.exporters = [this.guild, this.item, this.raid, this.character] //set up permissions + getLogger('LoginManager').debug('inserting permissions') + await Promise.all( [this, ...this.exporters].flatMap(exp => exp.exportRPCFeatures().map(async (feature) => { try{ await this.admin.knex.insert({ name: feature.name }).into('rpcpermissions') - }catch(e){} + }catch(e){ + console.log(e); + } }))) //start rankServers - const rankServers : any = {} + getLogger('LoginManager').debug('Starting rank servers') - for(let i = 0; i < _Rank.length; i++){ - const rank:Rank = _Rank[i] + let rankServers = { } as any + await Promise.all(_Rank.map(async (r,i) => { const port = 20001 + i - const rankServer = await this.startRankServer(rank, port) - rankServers[rank] = { + const rankServer = await this.startRankServer(r, port) + rankServers[r] = { server: rankServer, port: port, allowed: [] } - } + })) this.rankServers = rankServers + setInterval(this.checkExpiredSessions, 600_000) } + stop = async () => { + Object.values(this.userLogins).forEach(x => Object.values(x.connections).forEach(c => c.destroy())) + + await Promise.all(Object + .values(this.rankServers) + .map(async state => { + try{ + //return await state.server.destroy() + }catch(e){ + getLogger('LoginManager').warn(e) + } + }) + ); + + } + checkExpiredSessions = () => { Object.values(this.userLogins).map(userLogin => { const auth = userLogin.auth @@ -146,11 +169,13 @@ implements FrontworkComponent{ } checkConnection = async (socket: Socket) => { - let data : any = false + let data : any let tries = 0 while(!data){ tries ++ if(tries === 5){ + getLogger('LoginManager').debug('Connection check failed for connection *'+socket.port) + socket.destroy() return } @@ -282,18 +307,37 @@ implements FrontworkComponent{ } startRankServer = async (rank : Rank, port: number) : Promise => { - const allowedRPCs = await this.getRPCForRank(rank) - let rpcServer : RPCServer = new RPCServer(port, allowedRPCs, { - closeHandler: (socket) => { - Object.values(this.userLogins) - .forEach(login => delete login.connections[socket.port]) - }, - connectionHandler: (socket) => { - this.checkConnection(socket).catch(() => {}) //sometimes times out if you go too fast - }, - sesame: (sesame) => this.checkToken(sesame, rank) - }) + const allowedRPCs = await this.getRPCForRank(rank) + let rpcServer + let n = 0 + while(!rpcServer){ + n++ + await Promise.race([ + new Promise((res, rej) => { + rpcServer = new RPCServer(port, allowedRPCs, { + closeHandler: (socket) => { + Object.values(this.userLogins) + .forEach(login => delete login.connections[socket.port]) + + }, + connectionHandler: (socket) => { + this.checkConnection(socket).catch((e) => { + console.log(e); + }) //sometimes times out if you go too fast + }, + errorHandler: (socket, e, rpcName, args) => { + console.log(rpcName, args); + }, + sesame: (sesame) => this.checkToken(sesame, rank) + }) + res() + }), + new Promise((res, rej) => setTimeout(res, 500)) + ]) + if(!rpcServer && n>1) + getLogger('LoginManager').warn("createServer retry nr.", n, 'port', port) + } return rpcServer } diff --git a/src/backend/Components/Login/RPCInterface.ts b/src/backend/Components/Login/RPCInterface.ts new file mode 100644 index 0000000..6304eb8 --- /dev/null +++ b/src/backend/Components/Login/RPCInterface.ts @@ -0,0 +1,18 @@ +import { ILoginManager } from "./Interface" + +export type LoginManagerIfc = { + Authenticator: { + checkToken: ILoginManager['checkToken'] + login: ILoginManager['login'] + logout: ILoginManager['logout'] + createUser: ILoginManager['createUser'] + getAuth: ILoginManager['getAuth'] + } +} + +export type LoginManagerFeatureIfc = { + modifyPermissions: { + setPermission: ILoginManager['setPermission'] + getPermissions: ILoginManager['getPermissions'] + } +} diff --git a/src/backend/Components/Raid/Interface.ts b/src/backend/Components/Raid/Interface.ts new file mode 100644 index 0000000..eb0efde --- /dev/null +++ b/src/backend/Components/Raid/Interface.ts @@ -0,0 +1,10 @@ +import { User, Raid, Signup } from "../../Types/Types" + +export class IRaidManager{ + getRaids: () => Promise + createRaid: (raid:Raid) => Promise + addSignup: (signup: Signup) => Promise + removeSignup: (signup: Signup) => Promise + getSignups: (raid:Raid) => Promise + sign: (user:User, raid:Raid, attending:boolean) => Promise +} diff --git a/src/backend/Components/Raid/RPCInterface.ts b/src/backend/Components/Raid/RPCInterface.ts index 45b6ab6..f0c38c0 100644 --- a/src/backend/Components/Raid/RPCInterface.ts +++ b/src/backend/Components/Raid/RPCInterface.ts @@ -1,20 +1,19 @@ -import { Raid, Signup, User } from "../../Types/Types" +import { IRaidManager } from "./Interface" export type RaidManagerIfc = { RaidManager:{ - getRaids: () => Promise + getRaids: IRaidManager['getRaids'] } } export type RaidManagerFeatureIfc = { manageRaid: { - createRaid: (raid:Raid) => Promise - addSignup: (signup: Signup) => Promise - removeSignup: (signup: Signup) => Promise + createRaid: IRaidManager['createRaid'] + addSignup: IRaidManager['addSignup'] + removeSignup: IRaidManager['removeSignup'] } signup: { - getRaids: () => Promise - getSingups: (raid:Raid) => Promise - sign: (user:User, raid:Raid, attending:boolean) => Promise + getSignups: IRaidManager['getSignups'] + sign: IRaidManager['sign'] } } \ No newline at end of file diff --git a/src/backend/Components/Raid/RaidManager.ts b/src/backend/Components/Raid/RaidManager.ts index 621f67d..95b8390 100644 --- a/src/backend/Components/Raid/RaidManager.ts +++ b/src/backend/Components/Raid/RaidManager.ts @@ -1,17 +1,17 @@ import { Inject, Module } from "../../Injector/ServiceDecorator"; import { RaidManagerIfc, RaidManagerFeatureIfc } from "./RPCInterface"; import { FrontworkComponent } from "../../Types/FrontworkComponent"; -import { FrontworkAdmin } from "../../Admin/Admin"; import { TableDefiniton, Signup, Raid, User } from "../../Types/Types"; import { IAdmin } from "../../Admin/Interface"; +import { IRaidManager } from "./Interface"; -@Module() +@Module(IRaidManager) export class RaidManager -implements FrontworkComponent{ +implements FrontworkComponent, IRaidManager{ name = "RaidManager" as "RaidManager"; @Inject(IAdmin) - private admin: FrontworkAdmin + private admin: IAdmin exportRPCs = () => [{ name: 'getRaids' as 'getRaids', @@ -34,7 +34,7 @@ implements FrontworkComponent{ },{ name: 'signup' as 'signup', exportRPCs: () => [{ - name: 'getSingups' as 'getSingups', + name: 'getSignups' as 'getSignups', call: this.getSignups },{ name: 'sign' as 'sign', @@ -87,7 +87,7 @@ implements FrontworkComponent{ .select('*') .from('raids') - getSignups = async (raid:Raid) => await this.admin.knex + getSignups = async (raid:Raid) : Promise => await this.admin.knex .select('*') .from('signups') .where('raid_id', '=', raid.id!) diff --git a/src/backend/Components/User/RPCInterface.ts b/src/backend/Components/User/RPCInterface.ts deleted file mode 100644 index 57158e9..0000000 --- a/src/backend/Components/User/RPCInterface.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { Auth, Rank, User, RPCPermission, Character } from "../../Types/Types" -import { SpecT } from "../../Types/PlayerSpecs" - -export type LoginManagerIfc = { - Authenticator: { - login: (username:string, pwHash:string) => Promise - logout: (username: string, tokenValue :string) => Promise - getAuth: (tokenValue: string) => Promise - checkToken: (token: string, rank: Rank) => Promise - createUser: (user:User) => Promise - } -} - -export type LoginManagerFeatureIfc = { - modifyPermissions: { - setPermission: (perm: RPCPermission) => Promise - getPermissions: () => Promise - } -} - -export type CharacterManagerIfc = { - CharacterManager: { - getSpecId : (clazz: c, name: SpecT[c]) => Promise - getCharacters : () => Promise - } -} - -export type CharacterManagerFeatureIfc = { - createCharacter: { - createCharacter: (usertoken: string, char : Character) => Promise - } -} \ No newline at end of file diff --git a/src/backend/Injector/Injector.ts b/src/backend/Injector/Injector.ts index e8de506..76e7d8a 100644 --- a/src/backend/Injector/Injector.ts +++ b/src/backend/Injector/Injector.ts @@ -12,7 +12,8 @@ export const Injector = new class { rootInterface : Type root : Type - rootModules : Type[] = [] + rootModules: Type[] = [] + modules : {ifc?: Type, implementation: Type}[] = [] moduleObjs : {[key in string] : FrontworkComponent} = {} @@ -28,9 +29,11 @@ export const Injector = new class { return this.moduleObjs[target.name] as any if(target.name === this.rootInterface.name || target.name === this.root.name){ - let modules = this.rootModules.map(m => { - const module = new m() - this.moduleObjs[m.name] = module + let modules = this.modules.map(m => { + const module = new m.implementation() + if(m.ifc) + this.moduleObjs[m.ifc.name] = module + this.moduleObjs[m.implementation.name] = module return module }) const rootobj = new this.root(modules); @@ -42,11 +45,9 @@ export const Injector = new class { if(this.moduleObjs[i.what.name]) i.target[i.where] = this.moduleObjs[i.what.name] else - this.injectionQueue.push() + this.injectionQueue.push(i) } - this.injectionQueue.forEach(i => { - i.target[i.where] = this.moduleObjs[i.what.name] - }) + return rootobj } this.moduleObjs[target.name] = new target() diff --git a/src/backend/Injector/ServiceDecorator.ts b/src/backend/Injector/ServiceDecorator.ts index 380465e..c202836 100644 --- a/src/backend/Injector/ServiceDecorator.ts +++ b/src/backend/Injector/ServiceDecorator.ts @@ -6,9 +6,12 @@ import { FrontworkComponent } from "../Types/FrontworkComponent"; * @returns {GenericClassDecorator>} * @constructor */ -export const Module = (...args) : GenericClassDecorator> => { +export const Module = (ifc?: Type) : GenericClassDecorator> => { return (target: Type) => { - Injector.rootModules.push(target) + Injector.modules.push({ + ifc: ifc, + implementation: target + }) } } diff --git a/src/backend/Launcher.ts b/src/backend/Launcher.ts index c00f0f0..0546aa0 100644 --- a/src/backend/Launcher.ts +++ b/src/backend/Launcher.ts @@ -1,5 +1,6 @@ import { Injector } from './Injector/Injector'; import { IAdmin } from './Admin/Interface'; +import "./Admin/Admin" require('events').EventEmitter.defaultMaxListeners = 0; Injector.resolve(IAdmin).start() \ No newline at end of file diff --git a/src/backend/Types/FrontworkComponent.ts b/src/backend/Types/FrontworkComponent.ts index 6cd8bd2..185285b 100644 --- a/src/backend/Types/FrontworkComponent.ts +++ b/src/backend/Types/FrontworkComponent.ts @@ -20,4 +20,5 @@ export interface FrontworkComponent< getTableDefinitions(): TableDefiniton[] initialize?(): Promise + stop?() : Promise } \ No newline at end of file diff --git a/src/backend/Types/Types.ts b/src/backend/Types/Types.ts index f66086c..aa88ce8 100644 --- a/src/backend/Types/Types.ts +++ b/src/backend/Types/Types.ts @@ -1,8 +1,16 @@ import * as Knex from "knex" import { RPCExporter } from "rpclibrary"; import { RaidManagerIfc, RaidManagerFeatureIfc } from "../Components/Raid/RPCInterface"; -import { LoginManagerIfc, CharacterManagerIfc, LoginManagerFeatureIfc, CharacterManagerFeatureIfc } from "../Components/User/RPCInterface"; +import { LoginManagerIfc, LoginManagerFeatureIfc } from "../Components/Login/RPCInterface"; +import { CharacterManagerIfc, CharacterManagerFeatureIfc } from "../Components/Character/RPCInterface"; +export type FrontcraftIfc = RaidManagerIfc + & LoginManagerIfc + & CharacterManagerIfc + +export type FrontcraftFeatureIfc = RaidManagerFeatureIfc + & LoginManagerFeatureIfc + & CharacterManagerFeatureIfc export declare type NotificationSeverity = 'Info' | 'Important' | 'Error'; @@ -30,6 +38,15 @@ export type RPCPermission = { [rank in Rank] : boolean } +export type Item = { + id?:number + name:string + iconname:string + url:string + quality:string + hidden:boolean +} + export type User = { id?: number name: string @@ -67,13 +84,6 @@ export type Token = { export type Auth = {port: number, user: User, token: Token} -export type FrontcraftIfc = RaidManagerIfc - & LoginManagerIfc - & CharacterManagerIfc - -export type FrontcraftFeatureIfc = RaidManagerFeatureIfc - & LoginManagerFeatureIfc - & CharacterManagerFeatureIfc export type Spec = { id?: number,