diff --git a/package-lock.json b/package-lock.json index 241c64ad..2c693fe0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,9 +1,19 @@ { "name": "@al/core", - "version": "1.0.178", + "version": "2.0.0", "lockfileVersion": 1, "requires": true, "dependencies": { + "@ampproject/remapping": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz", + "integrity": "sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==", + "dev": true, + "requires": { + "@jridgewell/gen-mapping": "^0.1.0", + "@jridgewell/trace-mapping": "^0.3.9" + } + }, "@babel/code-frame": { "version": "7.16.0", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.0.tgz", @@ -14,85 +24,107 @@ } }, "@babel/compat-data": { - "version": "7.16.4", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.16.4.tgz", - "integrity": "sha512-1o/jo7D+kC9ZjHX5v+EHrdjl3PhxMrLSOTGsOdHJ+KL8HCaEK6ehrVL2RS6oHDZp+L7xLirLrPmQtEng769J/Q==", + "version": "7.18.8", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.18.8.tgz", + "integrity": "sha512-HSmX4WZPPK3FUxYp7g2T6EyO8j96HlZJlxmKPSh6KAcqwyDrfx7hKjXpAW/0FhFfTJsR0Yt4lAjLI2coMptIHQ==", "dev": true }, "@babel/core": { - "version": "7.16.5", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.16.5.tgz", - "integrity": "sha512-wUcenlLzuWMZ9Zt8S0KmFwGlH6QKRh3vsm/dhDA3CHkiTA45YuG1XkHRcNRl73EFPXDp/d5kVOU0/y7x2w6OaQ==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.16.0", - "@babel/generator": "^7.16.5", - "@babel/helper-compilation-targets": "^7.16.3", - "@babel/helper-module-transforms": "^7.16.5", - "@babel/helpers": "^7.16.5", - "@babel/parser": "^7.16.5", - "@babel/template": "^7.16.0", - "@babel/traverse": "^7.16.5", - "@babel/types": "^7.16.0", + "version": "7.18.10", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.18.10.tgz", + "integrity": "sha512-JQM6k6ENcBFKVtWvLavlvi/mPcpYZ3+R+2EySDEMSMbp7Mn4FexlbbJVrx2R7Ijhr01T8gyqrOaABWIOgxeUyw==", + "dev": true, + "requires": { + "@ampproject/remapping": "^2.1.0", + "@babel/code-frame": "^7.18.6", + "@babel/generator": "^7.18.10", + "@babel/helper-compilation-targets": "^7.18.9", + "@babel/helper-module-transforms": "^7.18.9", + "@babel/helpers": "^7.18.9", + "@babel/parser": "^7.18.10", + "@babel/template": "^7.18.10", + "@babel/traverse": "^7.18.10", + "@babel/types": "^7.18.10", "convert-source-map": "^1.7.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", - "json5": "^2.1.2", - "semver": "^6.3.0", - "source-map": "^0.5.0" + "json5": "^2.2.1", + "semver": "^6.3.0" }, "dependencies": { - "json5": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz", - "integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==", + "@babel/code-frame": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz", + "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==", + "dev": true, + "requires": { + "@babel/highlight": "^7.18.6" + } + }, + "@babel/helper-validator-identifier": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.18.6.tgz", + "integrity": "sha512-MmetCkz9ej86nJQV+sFCxoGGrUbU3q02kgLciwkrt9QqEB7cP39oKEY0PakknEO0Gu20SskMRi+AYZ3b1TpN9g==", + "dev": true + }, + "@babel/highlight": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", + "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", "dev": true, "requires": { - "minimist": "^1.2.5" + "@babel/helper-validator-identifier": "^7.18.6", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" } }, + "json5": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz", + "integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==", + "dev": true + }, "semver": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", "dev": true - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true } } }, "@babel/generator": { - "version": "7.16.5", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.16.5.tgz", - "integrity": "sha512-kIvCdjZqcdKqoDbVVdt5R99icaRtrtYhYK/xux5qiWCBmfdvEYMFZ68QCrpE5cbFM1JsuArUNs1ZkuKtTtUcZA==", + "version": "7.18.12", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.18.12.tgz", + "integrity": "sha512-dfQ8ebCN98SvyL7IxNMCUtZQSq5R7kxgN+r8qYTGDmmSion1hX2C0zq2yo1bsCDhXixokv1SAWTZUMYbO/V5zg==", "dev": true, "requires": { - "@babel/types": "^7.16.0", - "jsesc": "^2.5.1", - "source-map": "^0.5.0" + "@babel/types": "^7.18.10", + "@jridgewell/gen-mapping": "^0.3.2", + "jsesc": "^2.5.1" }, "dependencies": { - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true + "@jridgewell/gen-mapping": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", + "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", + "dev": true, + "requires": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + } } } }, "@babel/helper-compilation-targets": { - "version": "7.16.3", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.16.3.tgz", - "integrity": "sha512-vKsoSQAyBmxS35JUOOt+07cLc6Nk/2ljLIHwmq2/NM6hdioUaqEXq/S+nXvbvXbZkNDlWOymPanJGOc4CBjSJA==", + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.18.9.tgz", + "integrity": "sha512-tzLCyVmqUiFlcFoAPLA/gL9TeYrF61VLNtb+hvkuVaB5SUjW7jcfrglBIX1vUIoT7CLP3bBlIMeyEsIl2eFQNg==", "dev": true, "requires": { - "@babel/compat-data": "^7.16.0", - "@babel/helper-validator-option": "^7.14.5", - "browserslist": "^4.17.5", + "@babel/compat-data": "^7.18.8", + "@babel/helper-validator-option": "^7.18.6", + "browserslist": "^4.20.2", "semver": "^6.3.0" }, "dependencies": { @@ -105,86 +137,87 @@ } }, "@babel/helper-environment-visitor": { - "version": "7.16.5", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.16.5.tgz", - "integrity": "sha512-ODQyc5AnxmZWm/R2W7fzhamOk1ey8gSguo5SGvF0zcB3uUzRpTRmM/jmLSm9bDMyPlvbyJ+PwPEK0BWIoZ9wjg==", - "dev": true, - "requires": { - "@babel/types": "^7.16.0" - } + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz", + "integrity": "sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==", + "dev": true }, "@babel/helper-function-name": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.16.0.tgz", - "integrity": "sha512-BZh4mEk1xi2h4HFjWUXRQX5AEx4rvaZxHgax9gcjdLWdkjsY7MKt5p0otjsg5noXw+pB+clMCjw+aEVYADMjog==", + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.18.9.tgz", + "integrity": "sha512-fJgWlZt7nxGksJS9a0XdSaI4XvpExnNIgRP+rVefWh5U7BL8pPuir6SJUmFKRfjWQ51OtWSzwOxhaH/EBWWc0A==", "dev": true, "requires": { - "@babel/helper-get-function-arity": "^7.16.0", - "@babel/template": "^7.16.0", - "@babel/types": "^7.16.0" - } - }, - "@babel/helper-get-function-arity": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.16.0.tgz", - "integrity": "sha512-ASCquNcywC1NkYh/z7Cgp3w31YW8aojjYIlNg4VeJiHkqyP4AzIvr4qx7pYDb4/s8YcsZWqqOSxgkvjUz1kpDQ==", - "dev": true, - "requires": { - "@babel/types": "^7.16.0" + "@babel/template": "^7.18.6", + "@babel/types": "^7.18.9" } }, "@babel/helper-hoist-variables": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.16.0.tgz", - "integrity": "sha512-1AZlpazjUR0EQZQv3sgRNfM9mEVWPK3M6vlalczA+EECcPz3XPh6VplbErL5UoMpChhSck5wAJHthlj1bYpcmg==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz", + "integrity": "sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==", "dev": true, "requires": { - "@babel/types": "^7.16.0" + "@babel/types": "^7.18.6" } }, "@babel/helper-module-imports": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.16.0.tgz", - "integrity": "sha512-kkH7sWzKPq0xt3H1n+ghb4xEMP8k0U7XV3kkB+ZGy69kDk2ySFW1qPi06sjKzFY3t1j6XbJSqr4mF9L7CYVyhg==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz", + "integrity": "sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==", "dev": true, "requires": { - "@babel/types": "^7.16.0" + "@babel/types": "^7.18.6" } }, "@babel/helper-module-transforms": { - "version": "7.16.5", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.16.5.tgz", - "integrity": "sha512-CkvMxgV4ZyyioElFwcuWnDCcNIeyqTkCm9BxXZi73RR1ozqlpboqsbGUNvRTflgZtFbbJ1v5Emvm+lkjMYY/LQ==", - "dev": true, - "requires": { - "@babel/helper-environment-visitor": "^7.16.5", - "@babel/helper-module-imports": "^7.16.0", - "@babel/helper-simple-access": "^7.16.0", - "@babel/helper-split-export-declaration": "^7.16.0", - "@babel/helper-validator-identifier": "^7.15.7", - "@babel/template": "^7.16.0", - "@babel/traverse": "^7.16.5", - "@babel/types": "^7.16.0" + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.18.9.tgz", + "integrity": "sha512-KYNqY0ICwfv19b31XzvmI/mfcylOzbLtowkw+mfvGPAQ3kfCnMLYbED3YecL5tPd8nAYFQFAd6JHp2LxZk/J1g==", + "dev": true, + "requires": { + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-module-imports": "^7.18.6", + "@babel/helper-simple-access": "^7.18.6", + "@babel/helper-split-export-declaration": "^7.18.6", + "@babel/helper-validator-identifier": "^7.18.6", + "@babel/template": "^7.18.6", + "@babel/traverse": "^7.18.9", + "@babel/types": "^7.18.9" + }, + "dependencies": { + "@babel/helper-validator-identifier": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.18.6.tgz", + "integrity": "sha512-MmetCkz9ej86nJQV+sFCxoGGrUbU3q02kgLciwkrt9QqEB7cP39oKEY0PakknEO0Gu20SskMRi+AYZ3b1TpN9g==", + "dev": true + } } }, "@babel/helper-simple-access": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.16.0.tgz", - "integrity": "sha512-o1rjBT/gppAqKsYfUdfHq5Rk03lMQrkPHG1OWzHWpLgVXRH4HnMM9Et9CVdIqwkCQlobnGHEJMsgWP/jE1zUiw==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.18.6.tgz", + "integrity": "sha512-iNpIgTgyAvDQpDj76POqg+YEt8fPxx3yaNBg3S30dxNKm2SWfYhD0TGrK/Eu9wHpUW63VQU894TsTg+GLbUa1g==", "dev": true, "requires": { - "@babel/types": "^7.16.0" + "@babel/types": "^7.18.6" } }, "@babel/helper-split-export-declaration": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.0.tgz", - "integrity": "sha512-0YMMRpuDFNGTHNRiiqJX19GjNXA4H0E8jZ2ibccfSxaCogbm3am5WN/2nQNj0YnQwGWM1J06GOcQ2qnh3+0paw==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz", + "integrity": "sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==", "dev": true, "requires": { - "@babel/types": "^7.16.0" + "@babel/types": "^7.18.6" } }, + "@babel/helper-string-parser": { + "version": "7.18.10", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.18.10.tgz", + "integrity": "sha512-XtIfWmeNY3i4t7t4D2t02q50HvqHybPqW2ki1kosnvWCwuCMeo81Jf0gwr85jy/neUdg5XDdeFE/80DXiO+njw==", + "dev": true + }, "@babel/helper-validator-identifier": { "version": "7.15.7", "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.15.7.tgz", @@ -192,20 +225,20 @@ "dev": true }, "@babel/helper-validator-option": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.14.5.tgz", - "integrity": "sha512-OX8D5eeX4XwcroVW45NMvoYaIuFI+GQpA2a8Gi+X/U/cDUIRsV37qQfF905F0htTRCREQIB4KqPeaveRJUl3Ow==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz", + "integrity": "sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw==", "dev": true }, "@babel/helpers": { - "version": "7.16.5", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.16.5.tgz", - "integrity": "sha512-TLgi6Lh71vvMZGEkFuIxzaPsyeYCHQ5jJOOX1f0xXn0uciFuE8cEk0wyBquMcCxBXZ5BJhE2aUB7pnWTD150Tw==", + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.18.9.tgz", + "integrity": "sha512-Jf5a+rbrLoR4eNdUmnFu8cN5eNJT6qdTdOg5IHIzq87WwyRw9PwguLFOWYgktN/60IP4fgDUawJvs7PjQIzELQ==", "dev": true, "requires": { - "@babel/template": "^7.16.0", - "@babel/traverse": "^7.16.5", - "@babel/types": "^7.16.0" + "@babel/template": "^7.18.6", + "@babel/traverse": "^7.18.9", + "@babel/types": "^7.18.9" } }, "@babel/highlight": { @@ -220,50 +253,121 @@ } }, "@babel/parser": { - "version": "7.16.6", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.16.6.tgz", - "integrity": "sha512-Gr86ujcNuPDnNOY8mi383Hvi8IYrJVJYuf3XcuBM/Dgd+bINn/7tHqsj+tKkoreMbmGsFLsltI/JJd8fOFWGDQ==", + "version": "7.18.11", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.18.11.tgz", + "integrity": "sha512-9JKn5vN+hDt0Hdqn1PiJ2guflwP+B6Ga8qbDuoF0PzzVhrzsKIJo8yGqVk6CmMHiMei9w1C1Bp9IMJSIK+HPIQ==", "dev": true }, "@babel/template": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.16.0.tgz", - "integrity": "sha512-MnZdpFD/ZdYhXwiunMqqgyZyucaYsbL0IrjoGjaVhGilz+x8YB++kRfygSOIj1yOtWKPlx7NBp+9I1RQSgsd5A==", + "version": "7.18.10", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.18.10.tgz", + "integrity": "sha512-TI+rCtooWHr3QJ27kJxfjutghu44DLnasDMwpDqCXVTal9RLp3RSYNh4NdBrRP2cQAoG9A8juOQl6P6oZG4JxA==", "dev": true, "requires": { - "@babel/code-frame": "^7.16.0", - "@babel/parser": "^7.16.0", - "@babel/types": "^7.16.0" + "@babel/code-frame": "^7.18.6", + "@babel/parser": "^7.18.10", + "@babel/types": "^7.18.10" + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz", + "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==", + "dev": true, + "requires": { + "@babel/highlight": "^7.18.6" + } + }, + "@babel/helper-validator-identifier": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.18.6.tgz", + "integrity": "sha512-MmetCkz9ej86nJQV+sFCxoGGrUbU3q02kgLciwkrt9QqEB7cP39oKEY0PakknEO0Gu20SskMRi+AYZ3b1TpN9g==", + "dev": true + }, + "@babel/highlight": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", + "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.18.6", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + } + } } }, "@babel/traverse": { - "version": "7.16.5", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.16.5.tgz", - "integrity": "sha512-FOCODAzqUMROikDYLYxl4nmwiLlu85rNqBML/A5hKRVXG2LV8d0iMqgPzdYTcIpjZEBB7D6UDU9vxRZiriASdQ==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.16.0", - "@babel/generator": "^7.16.5", - "@babel/helper-environment-visitor": "^7.16.5", - "@babel/helper-function-name": "^7.16.0", - "@babel/helper-hoist-variables": "^7.16.0", - "@babel/helper-split-export-declaration": "^7.16.0", - "@babel/parser": "^7.16.5", - "@babel/types": "^7.16.0", + "version": "7.18.11", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.18.11.tgz", + "integrity": "sha512-TG9PiM2R/cWCAy6BPJKeHzNbu4lPzOSZpeMfeNErskGpTJx6trEvFaVCbDvpcxwy49BKWmEPwiW8mrysNiDvIQ==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.18.6", + "@babel/generator": "^7.18.10", + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-function-name": "^7.18.9", + "@babel/helper-hoist-variables": "^7.18.6", + "@babel/helper-split-export-declaration": "^7.18.6", + "@babel/parser": "^7.18.11", + "@babel/types": "^7.18.10", "debug": "^4.1.0", "globals": "^11.1.0" + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz", + "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==", + "dev": true, + "requires": { + "@babel/highlight": "^7.18.6" + } + }, + "@babel/helper-validator-identifier": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.18.6.tgz", + "integrity": "sha512-MmetCkz9ej86nJQV+sFCxoGGrUbU3q02kgLciwkrt9QqEB7cP39oKEY0PakknEO0Gu20SskMRi+AYZ3b1TpN9g==", + "dev": true + }, + "@babel/highlight": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", + "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.18.6", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + } + } } }, "@babel/types": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.16.0.tgz", - "integrity": "sha512-PJgg/k3SdLsGb3hhisFvtLOw5ts113klrpLuIPtCJIU+BB24fqq6lf8RWqKJEjzqXR9AEH1rIb5XTqwBHB+kQg==", + "version": "7.18.10", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.18.10.tgz", + "integrity": "sha512-MJvnbEiiNkpjo+LknnmRrqbY1GPUUggjv+wQVjetM/AONoupqRALB7I6jGqNUAZsKcRIEu2J6FRFvsczljjsaQ==", "dev": true, "requires": { - "@babel/helper-validator-identifier": "^7.15.7", + "@babel/helper-string-parser": "^7.18.10", + "@babel/helper-validator-identifier": "^7.18.6", "to-fast-properties": "^2.0.0" + }, + "dependencies": { + "@babel/helper-validator-identifier": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.18.6.tgz", + "integrity": "sha512-MmetCkz9ej86nJQV+sFCxoGGrUbU3q02kgLciwkrt9QqEB7cP39oKEY0PakknEO0Gu20SskMRi+AYZ3b1TpN9g==", + "dev": true + } } }, + "@colors/colors": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", + "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", + "dev": true + }, "@fimbul/bifrost": { "version": "0.21.0", "resolved": "https://registry.npmjs.org/@fimbul/bifrost/-/bifrost-0.21.0.tgz", @@ -318,6 +422,44 @@ "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", "dev": true }, + "@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==", + "dev": true, + "requires": { + "@jridgewell/set-array": "^1.0.0", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "@jridgewell/resolve-uri": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", + "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", + "dev": true + }, + "@jridgewell/set-array": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", + "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "dev": true + }, + "@jridgewell/sourcemap-codec": { + "version": "1.4.14", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", + "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", + "dev": true + }, + "@jridgewell/trace-mapping": { + "version": "0.3.15", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.15.tgz", + "integrity": "sha512-oWZNOULl+UbhsgB51uuZzglikfIKSUBO/M9W2OfEjn7cmqoAiCgmv9lyACTUacZwBz0ITnJ2NqjU8Tx0DHL88g==", + "dev": true, + "requires": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, "@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -345,20 +487,19 @@ } }, "@rollup/pluginutils": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-3.1.0.tgz", - "integrity": "sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-4.2.1.tgz", + "integrity": "sha512-iKnFXr7NkdZAIHiIWE+BX5ULi/ucVFYWD6TbAV+rZctiRTY2PL6tsIKhoIOaoskiWAkgu+VsbXgUVDNLHf+InQ==", "dev": true, "requires": { - "@types/estree": "0.0.39", - "estree-walker": "^1.0.1", + "estree-walker": "^2.0.1", "picomatch": "^2.2.2" }, "dependencies": { "estree-walker": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-1.0.1.tgz", - "integrity": "sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", "dev": true } } @@ -428,12 +569,6 @@ "integrity": "sha512-vt+kDhq/M2ayberEtJcIN/hxXy1Pk+59g2FV/ZQceeaTyCtCucjL2Q7FXlFjtWn4n15KCr1NE2lNNFhp0lEThw==", "dev": true }, - "@types/estree": { - "version": "0.0.39", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz", - "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==", - "dev": true - }, "@types/fs-extra": { "version": "8.1.2", "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-8.1.2.tgz", @@ -454,13 +589,13 @@ } }, "@types/karma": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@types/karma/-/karma-5.0.1.tgz", - "integrity": "sha512-zSaPZ+ABVx/DQ5imAQZUITgLy19H0aAogknHU67JuDi2PvaXGjYBevFakkDtooBvr7dMsq/YD9vtOxMcSHWnxw==", + "version": "6.3.3", + "resolved": "https://registry.npmjs.org/@types/karma/-/karma-6.3.3.tgz", + "integrity": "sha512-nRMec4mTCt+tkpRqh5/pAxmnjzEgAaalIq7mdfLFH88gSRC8+bxejLiSjHMMT/vHIhJHqg4GPIGCnCFbwvDRww==", "dev": true, "requires": { "@types/node": "*", - "log4js": "^4.0.0" + "log4js": "^6.4.1" } }, "@types/minimatch": { @@ -700,9 +835,9 @@ } }, "acorn": { - "version": "8.6.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.6.0.tgz", - "integrity": "sha512-U1riIR+lBSNi3IbxtaHOIKdH8sLFv3NYfNv8sg7ZsNhcfl4HF2++BfqqrNAxoCLQW1iiylOj76ecnaUxz+z9yw==", + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.0.tgz", + "integrity": "sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w==", "dev": true }, "acorn-walk": { @@ -871,13 +1006,10 @@ "dev": true }, "async": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", - "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", - "dev": true, - "requires": { - "lodash": "^4.17.14" - } + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", + "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==", + "dev": true }, "async-each": { "version": "1.0.3", @@ -999,12 +1131,6 @@ } } }, - "base64-arraybuffer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-1.0.1.tgz", - "integrity": "sha512-vFIUq7FdLtjZMhATwDul5RZWv2jpXQ09Pd6jcVEOvIsqCWTRFD/ONHNfyOS8dA/Ippi5dsIgpyKWKZaAKZltbA==", - "dev": true - }, "base64-js": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", @@ -1063,21 +1189,23 @@ "dev": true }, "body-parser": { - "version": "1.19.1", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.1.tgz", - "integrity": "sha512-8ljfQi5eBk8EJfECMrgqNGWPEY5jWP+1IzkzkGdFFEwFQZZyaZ21UqdaHktgiMlH0xLHqIFtE/u2OYE5dOtViA==", + "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==", "dev": true, "requires": { - "bytes": "3.1.1", + "bytes": "3.1.2", "content-type": "~1.0.4", "debug": "2.6.9", - "depd": "~1.1.2", - "http-errors": "1.8.1", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", "iconv-lite": "0.4.24", - "on-finished": "~2.3.0", - "qs": "6.9.6", - "raw-body": "2.4.2", - "type-is": "~1.6.18" + "on-finished": "2.4.1", + "qs": "6.10.3", + "raw-body": "2.5.1", + "type-is": "~1.6.18", + "unpipe": "1.0.0" }, "dependencies": { "debug": { @@ -1089,17 +1217,41 @@ "ms": "2.0.0" } }, + "depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "dev": true + }, + "destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "dev": true + }, "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", "dev": true }, + "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==", + "dev": true, + "requires": { + "ee-first": "1.1.1" + } + }, "qs": { - "version": "6.9.6", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.6.tgz", - "integrity": "sha512-TIRk4aqYLNoJUbd+g2lEdz5kLWIuTMRagAXxl78Q0RiVjAOugHmeKNGdd3cwo/ktpf9aL9epCfFqWDEKysUlLQ==", - "dev": true + "version": "6.10.3", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.3.tgz", + "integrity": "sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ==", + "dev": true, + "requires": { + "side-channel": "^1.0.4" + } } } }, @@ -1217,16 +1369,15 @@ } }, "browserslist": { - "version": "4.19.1", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.19.1.tgz", - "integrity": "sha512-u2tbbG5PdKRTUoctO3NBD8FQ5HdPh1ZXPHzp1rwaa5jTc+RV9/+RlWiAIKmjRPQF+xbGM9Kklj5bZQFa2s/38A==", + "version": "4.21.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.3.tgz", + "integrity": "sha512-898rgRXLAyRkM1GryrrBHGkqA5hlpkV5MhtZwg9QXeiyLUYs2k00Un05aX5l2/yJIOObYKOpS2JNo8nJDE7fWQ==", "dev": true, "requires": { - "caniuse-lite": "^1.0.30001286", - "electron-to-chromium": "^1.4.17", - "escalade": "^3.1.1", - "node-releases": "^2.0.1", - "picocolors": "^1.0.0" + "caniuse-lite": "^1.0.30001370", + "electron-to-chromium": "^1.4.202", + "node-releases": "^2.0.6", + "update-browserslist-db": "^1.0.5" } }, "buffer": { @@ -1264,9 +1415,9 @@ "dev": true }, "bytes": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.1.tgz", - "integrity": "sha512-dWe4nWO/ruEOY7HkUJ5gFt1DCFV9zPRoJr8pV0/ASQermOZjtq8jMjOprC0Kd10GLN+l7xaUPvxzJFWtxGu8Fg==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", "dev": true }, "cacache": { @@ -1342,9 +1493,9 @@ "dev": true }, "caniuse-lite": { - "version": "1.0.30001287", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001287.tgz", - "integrity": "sha512-4udbs9bc0hfNrcje++AxBuc6PfLNHwh3PO9kbwnfCQWyqtlzg3py0YgFu8jyRTTo85VAz4U+VLxSlID09vNtWA==", + "version": "1.0.30001378", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001378.tgz", + "integrity": "sha512-JVQnfoO7FK7WvU4ZkBRbPjaot4+YqxogSDosHv0Hv5mWpUESmN+UubMU6L/hGz8QlQ2aY5U0vR6MOs6j/CXpNA==", "dev": true }, "chai": { @@ -1496,7 +1647,7 @@ "clone": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", - "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=", + "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", "dev": true }, "collection-visit": { @@ -1530,16 +1681,10 @@ "integrity": "sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g==", "dev": true }, - "colors": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", - "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==", - "dev": true - }, "combine-source-map": { "version": "0.8.0", "resolved": "https://registry.npmjs.org/combine-source-map/-/combine-source-map-0.8.0.tgz", - "integrity": "sha1-pY0N8ELBhvz4IqjoAV9UUNLXmos=", + "integrity": "sha512-UlxQ9Vw0b/Bt/KYwCFqdEwsQ1eL8d1gibiFb7lxQJFdvTgc2hIZi6ugsg+kyhzhPV+QEpUiEIwInIAIrgoEkrg==", "dev": true, "requires": { "convert-source-map": "~1.1.0", @@ -1551,13 +1696,13 @@ "convert-source-map": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.1.3.tgz", - "integrity": "sha1-SCnId+n+SbMWHzvzZziI4gRpmGA=", + "integrity": "sha512-Y8L5rp6jo+g9VEPgvqNfEopjTR4OTYct8lXlS8iVQdmnjDvbdbzYe9rjtFCB9egC86JoNCU61WRY+ScjkZpnIg==", "dev": true }, "source-map": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", "dev": true } } @@ -1661,7 +1806,7 @@ "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", "dev": true } } @@ -1719,9 +1864,9 @@ } }, "cookie": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz", - "integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==", + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", + "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==", "dev": true }, "cookie-signature": { @@ -1884,7 +2029,7 @@ "custom-event": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/custom-event/-/custom-event-1.0.1.tgz", - "integrity": "sha1-XQKkaFCt8bSjF5RqOSj8y1v9BCU=", + "integrity": "sha512-GAj5FOq0Hd+RsCGVJxZuKaIDXDf3h6GQoNEjFgbLLI/trgtavwUbSnZ5pVfg27DVCaWjIohryS0JFwIJyT2cMg==", "dev": true }, "cyclist": { @@ -1894,9 +2039,9 @@ "dev": true }, "date-format": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/date-format/-/date-format-2.1.0.tgz", - "integrity": "sha512-bYQuGLeFxhkxNOF3rcMtiZxvCBAquGzZm6oWA1oZ0g2THUzivaRhv8uOhdr19LmoobSOLoIAxeUK2RdbM8IFTA==", + "version": "4.0.13", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-4.0.13.tgz", + "integrity": "sha512-bnYCwf8Emc3pTD8pXnre+wfnjGtfi5ncMDKy7+cWZXbmRAsdWkOQHrfC1yz/KiwP5thDp2kCHWYWKBX4HP1hoQ==", "dev": true }, "debug": { @@ -1931,7 +2076,7 @@ "defaults": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", - "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", + "integrity": "sha512-s82itHOnYrN0Ib8r+z7laQz3sdE+4FP3d9Q7VLO7U+KRT+CR0GsWuyHxzdAY82I7cXv0G/twrqomTJLOssO5HA==", "dev": true, "requires": { "clone": "^1.0.2" @@ -2023,7 +2168,7 @@ "di": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/di/-/di-0.0.1.tgz", - "integrity": "sha1-gGZJMmzqp8qjMG112YXqJ0i6kTw=", + "integrity": "sha512-uJaamHkagcZtHPqCIHZxnFrXlunQXgBOsZSUOWwFw31QJCAbyTBoHMW75YOTur5ZNx8pIeAKgf6GWIgaqqiLhA==", "dev": true }, "diff": { @@ -2081,7 +2226,7 @@ "dom-serialize": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/dom-serialize/-/dom-serialize-2.2.1.tgz", - "integrity": "sha1-ViromZ9Evl6jB29UGdzVnrQ6yVs=", + "integrity": "sha512-Yra4DbvoW7/Z6LBN560ZwXMjoNOSAN2wRsKFGc4iBeso+mpIA6qj1vfdf9HpMaKAqG6wXTy+1SYEzmNpKXOSsQ==", "dev": true, "requires": { "custom-event": "~1.0.0", @@ -2165,9 +2310,9 @@ "dev": true }, "electron-to-chromium": { - "version": "1.4.21", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.21.tgz", - "integrity": "sha512-T04U2ciApGbm+dESFEBbewi2Xt0Dgyww8M4n4sOt9lnmFuYbaHEDWCROkx4jvAZDUWWry9YOdnAs+7468q80Qg==", + "version": "1.4.225", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.225.tgz", + "integrity": "sha512-ICHvGaCIQR3P88uK8aRtx8gmejbVJyC6bB4LEC3anzBrIzdzC7aiZHY4iFfXhN4st6I7lMO0x4sgBHf/7kBvRw==", "dev": true }, "elliptic": { @@ -2221,9 +2366,9 @@ } }, "engine.io": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.1.0.tgz", - "integrity": "sha512-ErhZOVu2xweCjEfYcTdkCnEYUiZgkAcBBAhW4jbIvNG8SLU3orAqoJCiytZjYF7eTpVmmCrLDjLIEaPlUAs1uw==", + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.2.0.tgz", + "integrity": "sha512-4KzwW3F3bk+KlzSOY57fj/Jx6LyRQ1nbcyIadehl+AnXjKT7gDO0ORdRi/84ixvMKTym6ZKuxvbzN62HDDU1Lg==", "dev": true, "requires": { "@types/cookie": "^0.4.1", @@ -2234,18 +2379,15 @@ "cookie": "~0.4.1", "cors": "~2.8.5", "debug": "~4.3.1", - "engine.io-parser": "~5.0.0", + "engine.io-parser": "~5.0.3", "ws": "~8.2.3" } }, "engine.io-parser": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.0.2.tgz", - "integrity": "sha512-wuiO7qO/OEkPJSFueuATIXtrxF7/6GTbAO9QLv7nnbjwZ5tYhLm9zxvLwxstRs0dcT0KUlWTjtIOs1T86jt12g==", - "dev": true, - "requires": { - "base64-arraybuffer": "~1.0.1" - } + "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==", + "dev": true }, "enhanced-resolve": { "version": "4.5.0", @@ -2261,7 +2403,7 @@ "ent": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/ent/-/ent-2.2.0.tgz", - "integrity": "sha1-6WQhkyWiHQX0RGai9obtbOX13R0=", + "integrity": "sha512-GHrMyVZQWvTIdDtpiEXdHZnFQKzeO09apj8Cbl4pKWy4i0Oprcq17usfDt5aO63swf0JOeMWjWQE/LzgSRuWpA==", "dev": true }, "errno": { @@ -2315,7 +2457,7 @@ "es6-object-assign": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/es6-object-assign/-/es6-object-assign-1.1.0.tgz", - "integrity": "sha1-wsNYJlYkfDnqEHyx5mUrb58kUjw=", + "integrity": "sha512-MEl9uirslVwqQU369iHNWZXsI8yaZYGg/D65aOgZkeyFJwHYSxilf7rQzXKI7DdDuBPrBXbfk3sl9hJhmd5AUw==", "dev": true }, "es6-promise": { @@ -2988,12 +3130,6 @@ "is-buffer": "~2.0.3" } }, - "flatted": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.2.tgz", - "integrity": "sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA==", - "dev": true - }, "flush-write-stream": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz", @@ -3041,18 +3177,21 @@ "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.6.tgz", "integrity": "sha512-fhUl5EwSJbbl8AR+uYL2KQDxLkdSjZGR36xy46AO7cOMTrCMON6Sa28FmAnC2tRTDbd/Uuzz3aJBv7EBN7JH8A==" }, + "for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "dev": true, + "requires": { + "is-callable": "^1.1.3" + } + }, "for-in": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", "dev": true }, - "foreach": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz", - "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=", - "dev": true - }, "form-data": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz", @@ -3132,12 +3271,12 @@ } }, "fs-extra": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", - "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", "dev": true, "requires": { - "graceful-fs": "^4.1.2", + "graceful-fs": "^4.2.0", "jsonfile": "^4.0.0", "universalify": "^0.1.0" } @@ -3204,6 +3343,24 @@ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" }, + "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==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.0", + "functions-have-names": "^1.2.2" + } + }, + "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==", + "dev": true + }, "gensync": { "version": "1.0.0-beta.2", "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", @@ -3398,6 +3555,15 @@ "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", "dev": true }, + "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==", + "dev": true, + "requires": { + "get-intrinsic": "^1.1.1" + } + }, "has-symbols": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", @@ -3530,16 +3696,30 @@ "dev": true }, "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==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", "dev": true, "requires": { - "depd": "~1.1.2", + "depd": "2.0.0", "inherits": "2.0.4", "setprototypeof": "1.2.0", - "statuses": ">= 1.5.0 < 2", + "statuses": "2.0.1", "toidentifier": "1.0.1" + }, + "dependencies": { + "depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "dev": true + }, + "statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "dev": true + } } }, "http-proxy": { @@ -3652,7 +3832,7 @@ "inline-source-map": { "version": "0.6.2", "resolved": "https://registry.npmjs.org/inline-source-map/-/inline-source-map-0.6.2.tgz", - "integrity": "sha1-+Tk0ccGKedFyT4Y/o4tYY3Ct4qU=", + "integrity": "sha512-0mVWSSbNDvedDWIN4wxLsdPM4a7cIPcpyMxj3QZ406QRwQ6ePGB1YIHxVPjqpcUGbWQ5C+nHTwGNWAGvt7ggVA==", "dev": true, "requires": { "source-map": "~0.5.3" @@ -3661,7 +3841,7 @@ "source-map": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", "dev": true } } @@ -3942,16 +4122,120 @@ } }, "is-typed-array": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.8.tgz", - "integrity": "sha512-HqH41TNZq2fgtGT8WHVFVJhBVGuY3AnP3Q36K8JKXUxSxRgk/d+7NjmwG2vo2mYmXK8UYZKu0qH8bVP5gEisjA==", + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.9.tgz", + "integrity": "sha512-kfrlnTTn8pZkfpJMUgYD7YZ3qzeJgWUn8XfVYBARc4wnmNOmLbmuuaAs3q5fvB0UJOn6yHAKaGTPM7d6ezoD/A==", "dev": true, "requires": { "available-typed-arrays": "^1.0.5", "call-bind": "^1.0.2", - "es-abstract": "^1.18.5", - "foreach": "^2.0.5", + "es-abstract": "^1.20.0", + "for-each": "^0.3.3", "has-tostringtag": "^1.0.0" + }, + "dependencies": { + "define-properties": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.4.tgz", + "integrity": "sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==", + "dev": true, + "requires": { + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + } + }, + "es-abstract": { + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.20.1.tgz", + "integrity": "sha512-WEm2oBhfoI2sImeM4OF2zE2V3BYdSF+KnSi9Sidz51fQHd7+JuF8Xgcj9/0o+OWeIeIS/MiuNnlruQrJf16GQA==", + "dev": true, + "requires": { + "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.3", + "string.prototype.trimend": "^1.0.5", + "string.prototype.trimstart": "^1.0.5", + "unbox-primitive": "^1.0.2" + } + }, + "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==", + "dev": true + }, + "has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "dev": true + }, + "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==", + "dev": true, + "requires": { + "call-bind": "^1.0.2" + } + }, + "object-inspect": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz", + "integrity": "sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==", + "dev": true + }, + "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==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.19.5" + } + }, + "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==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.19.5" + } + }, + "unbox-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", + "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "has-bigints": "^1.0.2", + "has-symbols": "^1.0.3", + "which-boxed-primitive": "^1.0.2" + } + } } }, "is-weakref": { @@ -3982,9 +4266,9 @@ "dev": true }, "isbinaryfile": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-4.0.8.tgz", - "integrity": "sha512-53h6XFniq77YdW+spoRrebh0mnmTxRPTlcuIArO57lmMdq4uBKFKaeTjnb92oYWrSn/LVL+LT+Hap2tFQj8V+w==", + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-4.0.10.tgz", + "integrity": "sha512-iHrqe5shvBUcFbmZq9zOQHBoeOhZJu6RQGrDpBgenUm/Am+F3JM2MgQj+rK3Z601fzrL5gLZWtAPH2OBaSVcyw==", "dev": true }, "isexe": { @@ -4080,9 +4364,9 @@ } }, "istanbul-reports": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.1.tgz", - "integrity": "sha512-q1kvhAXWSsXfMjCdNHNPKZZv94OlspKnoGv+R9RGbnqOOQ0VbNfLFgQDVgi7hHenKsndGq3/o0OBdzDXthWcNw==", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.5.tgz", + "integrity": "sha512-nUsEMa9pBt/NOHqbcbeJEgqIlY/K7rVWUX6Lql2orY5e9roQOthbR3vtY4zzf2orPELg80fnxxk9zUyPlgwD1w==", "dev": true, "requires": { "html-escaper": "^2.0.0", @@ -4157,7 +4441,7 @@ "json-stringify-safe": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", + "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", "dev": true }, "json5": { @@ -4185,15 +4469,15 @@ "dev": true }, "karma": { - "version": "6.3.9", - "resolved": "https://registry.npmjs.org/karma/-/karma-6.3.9.tgz", - "integrity": "sha512-E/MqdLM9uVIhfuyVnrhlGBu4miafBdXEAEqCmwdEMh3n17C7UWC/8Kvm3AYKr91gc7scutekZ0xv6rxRaUCtnw==", + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/karma/-/karma-6.4.0.tgz", + "integrity": "sha512-s8m7z0IF5g/bS5ONT7wsOavhW4i4aFkzD4u4wgzAQWT4HGUeWI3i21cK2Yz6jndMAeHETp5XuNsRoyGJZXVd4w==", "dev": true, "requires": { + "@colors/colors": "1.5.0", "body-parser": "^1.19.0", "braces": "^3.0.2", "chokidar": "^3.5.1", - "colors": "^1.4.0", "connect": "^3.7.0", "di": "^0.0.1", "dom-serialize": "^2.2.1", @@ -4202,49 +4486,20 @@ "http-proxy": "^1.18.1", "isbinaryfile": "^4.0.8", "lodash": "^4.17.21", - "log4js": "^6.3.0", + "log4js": "^6.4.1", "mime": "^2.5.2", "minimatch": "^3.0.4", + "mkdirp": "^0.5.5", "qjobs": "^1.2.0", "range-parser": "^1.2.1", "rimraf": "^3.0.2", - "socket.io": "^4.2.0", + "socket.io": "^4.4.1", "source-map": "^0.6.1", "tmp": "^0.2.1", "ua-parser-js": "^0.7.30", "yargs": "^16.1.1" }, "dependencies": { - "date-format": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/date-format/-/date-format-3.0.0.tgz", - "integrity": "sha512-eyTcpKOcamdhWJXj56DpQMo1ylSQpcGtGKXcU0Tb97+K56/CF5amAqqqNj0+KvA0iw2ynxtHWFsPDSClCxe48w==", - "dev": true - }, - "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==", - "dev": true, - "requires": { - "graceful-fs": "^4.2.0", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - } - }, - "log4js": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.3.0.tgz", - "integrity": "sha512-Mc8jNuSFImQUIateBFwdOQcmC6Q5maU0VVvdC2R6XMb66/VnT+7WS4D/0EeNMZu1YODmJe5NIn2XftCzEocUgw==", - "dev": true, - "requires": { - "date-format": "^3.0.0", - "debug": "^4.1.1", - "flatted": "^2.0.1", - "rfdc": "^1.1.4", - "streamroller": "^2.2.4" - } - }, "rimraf": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", @@ -4253,32 +4508,13 @@ "requires": { "glob": "^7.1.3" } - }, - "streamroller": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-2.2.4.tgz", - "integrity": "sha512-OG79qm3AujAM9ImoqgWEY1xG4HX+Lw+yY6qZj9R1K2mhF5bEmQ849wvrb+4vt4jLMLzwXttJlQbOdPOQVRv7DQ==", - "dev": true, - "requires": { - "date-format": "^2.1.0", - "debug": "^4.1.1", - "fs-extra": "^8.1.0" - }, - "dependencies": { - "date-format": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/date-format/-/date-format-2.1.0.tgz", - "integrity": "sha512-bYQuGLeFxhkxNOF3rcMtiZxvCBAquGzZm6oWA1oZ0g2THUzivaRhv8uOhdr19LmoobSOLoIAxeUK2RdbM8IFTA==", - "dev": true - } - } } } }, "karma-chrome-launcher": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/karma-chrome-launcher/-/karma-chrome-launcher-3.1.0.tgz", - "integrity": "sha512-3dPs/n7vgz1rxxtynpzZTvb9y/GIaW8xjAwcIGttLbycqoFtI7yo1NGnQi6oFTherRE+GIhCAHZC4vEqWGhNvg==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/karma-chrome-launcher/-/karma-chrome-launcher-3.1.1.tgz", + "integrity": "sha512-hsIglcq1vtboGPAN+DGCISCFOxW+ZVnIqhDQcCMqqCp+4dmJ0Qpq5QAjkbA0X2L9Mi6OBkHi2Srrbmm7pUKkzQ==", "dev": true, "requires": { "which": "^1.2.1" @@ -4294,26 +4530,18 @@ } }, "karma-mocha": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/karma-mocha/-/karma-mocha-1.3.0.tgz", - "integrity": "sha1-7qrH/8DiAetjxGdEDStpx883eL8=", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/karma-mocha/-/karma-mocha-2.0.1.tgz", + "integrity": "sha512-Tzd5HBjm8his2OA4bouAsATYEpZrp9vC7z5E5j4C5Of5Rrs1jY67RAwXNcVmd/Bnk1wgvQRou0zGVLey44G4tQ==", "dev": true, "requires": { - "minimist": "1.2.0" - }, - "dependencies": { - "minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true - } + "minimist": "^1.2.3" } }, "karma-typescript": { - "version": "5.5.2", - "resolved": "https://registry.npmjs.org/karma-typescript/-/karma-typescript-5.5.2.tgz", - "integrity": "sha512-2rNhiCMrIF+VR8jMuovOLSRjNkjdoE/kQ4XYZU94lMkHNQtnqCaToAnztMj4fuOPRErL7VIkwvJEO7jBd47Q6A==", + "version": "5.5.3", + "resolved": "https://registry.npmjs.org/karma-typescript/-/karma-typescript-5.5.3.tgz", + "integrity": "sha512-l1FHurolXEBIzRa9ExpNtjzysAhsi/vLpTazpwLHWWK86mknvVpqor6pRZ5Nid7jvOPrTBqAq0JRuLgiCdRkFw==", "dev": true, "requires": { "acorn": "^8.1.0", @@ -4361,66 +4589,11 @@ "vm-browserify": "^1.1.2" }, "dependencies": { - "async": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.2.tgz", - "integrity": "sha512-H0E+qZaDEfx/FY4t7iLRv1W2fFI6+pyCeTw1uN20AQPiwqwM6ojPxHxdLv4z8hi2DtnW9BOckSspLucW7pIE5g==", - "dev": true - }, - "date-format": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/date-format/-/date-format-3.0.0.tgz", - "integrity": "sha512-eyTcpKOcamdhWJXj56DpQMo1ylSQpcGtGKXcU0Tb97+K56/CF5amAqqqNj0+KvA0iw2ynxtHWFsPDSClCxe48w==", - "dev": true - }, - "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==", - "dev": true, - "requires": { - "graceful-fs": "^4.2.0", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - } - }, - "log4js": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.3.0.tgz", - "integrity": "sha512-Mc8jNuSFImQUIateBFwdOQcmC6Q5maU0VVvdC2R6XMb66/VnT+7WS4D/0EeNMZu1YODmJe5NIn2XftCzEocUgw==", - "dev": true, - "requires": { - "date-format": "^3.0.0", - "debug": "^4.1.1", - "flatted": "^2.0.1", - "rfdc": "^1.1.4", - "streamroller": "^2.2.4" - } - }, "source-map": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", - "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", + "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", "dev": true - }, - "streamroller": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-2.2.4.tgz", - "integrity": "sha512-OG79qm3AujAM9ImoqgWEY1xG4HX+Lw+yY6qZj9R1K2mhF5bEmQ849wvrb+4vt4jLMLzwXttJlQbOdPOQVRv7DQ==", - "dev": true, - "requires": { - "date-format": "^2.1.0", - "debug": "^4.1.1", - "fs-extra": "^8.1.0" - }, - "dependencies": { - "date-format": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/date-format/-/date-format-2.1.0.tgz", - "integrity": "sha512-bYQuGLeFxhkxNOF3rcMtiZxvCBAquGzZm6oWA1oZ0g2THUzivaRhv8uOhdr19LmoobSOLoIAxeUK2RdbM8IFTA==", - "dev": true - } - } } } }, @@ -4472,7 +4645,7 @@ "lodash.memoize": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-3.0.4.tgz", - "integrity": "sha1-LcvSwofLwKVcxCMovQxzYVDVPj8=", + "integrity": "sha512-eDn9kqrAmVUC1wmZvlQ6Uhde44n+tXpqPrN8olQJbttgh0oKclk+SF54P47VEGE9CEiMeRwAP8BaM7UHvBkz2A==", "dev": true }, "log-symbols": { @@ -4485,16 +4658,33 @@ } }, "log4js": { - "version": "4.5.1", - "resolved": "https://registry.npmjs.org/log4js/-/log4js-4.5.1.tgz", - "integrity": "sha512-EEEgFcE9bLgaYUKuozyFfytQM2wDHtXn4tAN41pkaxpNjAykv11GVdeI4tHtmPWW4Xrgh9R/2d7XYghDVjbKKw==", + "version": "6.6.1", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.6.1.tgz", + "integrity": "sha512-J8VYFH2UQq/xucdNu71io4Fo+purYYudyErgBbswWKO0MC6QVOERRomt5su/z6d3RJSmLyTGmXl3Q/XjKCf+/A==", "dev": true, "requires": { - "date-format": "^2.0.0", - "debug": "^4.1.1", - "flatted": "^2.0.0", - "rfdc": "^1.1.4", - "streamroller": "^1.0.6" + "date-format": "^4.0.13", + "debug": "^4.3.4", + "flatted": "^3.2.6", + "rfdc": "^1.3.0", + "streamroller": "^3.1.2" + }, + "dependencies": { + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "flatted": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", + "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", + "dev": true + } } }, "lru-cache": { @@ -5291,9 +5481,9 @@ } }, "node-releases": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.1.tgz", - "integrity": "sha512-CqyzN6z7Q6aMeF/ktcMVTzhAHCEpf8SOarwpzpf8pNBY2k5/oM34UHldUwp8VKI7uxct2HxSRdJjBaZeESzcxA==", + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.6.tgz", + "integrity": "sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg==", "dev": true }, "normalize-path": { @@ -5831,13 +6021,13 @@ "dev": true }, "raw-body": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.2.tgz", - "integrity": "sha512-RPMAFUJP19WIet/99ngh6Iv8fzAbqum4Li7AD6DtGaW2RpMB/11xDoalPiJMTbu6I3hkbMVkATvZrqb9EEqeeQ==", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", + "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", "dev": true, "requires": { - "bytes": "3.1.1", - "http-errors": "1.8.1", + "bytes": "3.1.2", + "http-errors": "2.0.0", "iconv-lite": "0.4.24", "unpipe": "1.0.0" } @@ -5877,6 +6067,17 @@ "safe-regex": "^1.1.0" } }, + "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==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "functions-have-names": "^1.2.2" + } + }, "remove-trailing-separator": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", @@ -5911,7 +6112,7 @@ "requires-port": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", - "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=", + "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", "dev": true }, "resolve": { @@ -6103,16 +6304,16 @@ } }, "rollup-plugin-typescript2": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/rollup-plugin-typescript2/-/rollup-plugin-typescript2-0.27.3.tgz", - "integrity": "sha512-gmYPIFmALj9D3Ga1ZbTZAKTXq1JKlTQBtj299DXhqYz9cL3g/AQfUvbb2UhH+Nf++cCq941W2Mv7UcrcgLzJJg==", + "version": "0.32.1", + "resolved": "https://registry.npmjs.org/rollup-plugin-typescript2/-/rollup-plugin-typescript2-0.32.1.tgz", + "integrity": "sha512-RanO8bp1WbeMv0bVlgcbsFNCn+Y3rX7wF97SQLDxf0fMLsg0B/QFF005t4AsGUcDgF3aKJHoqt4JF2xVaABeKw==", "dev": true, "requires": { - "@rollup/pluginutils": "^3.1.0", - "find-cache-dir": "^3.3.1", - "fs-extra": "8.1.0", - "resolve": "1.17.0", - "tslib": "2.0.1" + "@rollup/pluginutils": "^4.1.2", + "find-cache-dir": "^3.3.2", + "fs-extra": "^10.0.0", + "resolve": "^1.20.0", + "tslib": "^2.4.0" }, "dependencies": { "find-cache-dir": { @@ -6137,14 +6338,24 @@ } }, "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==", + "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, "requires": { "graceful-fs": "^4.2.0", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" } }, "locate-path": { @@ -6189,20 +6400,17 @@ "find-up": "^4.0.0" } }, - "resolve": { - "version": "1.17.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz", - "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==", - "dev": true, - "requires": { - "path-parse": "^1.0.6" - } - }, "semver": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", "dev": true + }, + "universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "dev": true } } }, @@ -6627,29 +6835,29 @@ } }, "socket.io": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.4.0.tgz", - "integrity": "sha512-bnpJxswR9ov0Bw6ilhCvO38/1WPtE3eA2dtxi2Iq4/sFebiDJQzgKNYA7AuVVdGW09nrESXd90NbZqtDd9dzRQ==", + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.5.1.tgz", + "integrity": "sha512-0y9pnIso5a9i+lJmsCdtmTTgJFFSvNQKDnPQRz28mGNnxbmqYg2QPtJTLFxhymFZhAIn50eHAKzJeiNaKr+yUQ==", "dev": true, "requires": { "accepts": "~1.3.4", "base64id": "~2.0.0", "debug": "~4.3.2", - "engine.io": "~6.1.0", - "socket.io-adapter": "~2.3.3", + "engine.io": "~6.2.0", + "socket.io-adapter": "~2.4.0", "socket.io-parser": "~4.0.4" } }, "socket.io-adapter": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.3.3.tgz", - "integrity": "sha512-Qd/iwn3VskrpNO60BeRyCyr8ZWw9CPZyitW4AQwmRZ8zCiyDiL+znRnWX6tDHXnWn1sJrM1+b6Mn6wEDJJ4aYQ==", + "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==", "dev": true }, "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==", + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.0.5.tgz", + "integrity": "sha512-sNjbT9dX63nqUFIOv95tTVm6elyIU4RvB1m8dOeZt+IgWwcWklFDOdmGcfo3zSiRsnR/3pJkjY5lfoGqEe4Eig==", "dev": true, "requires": { "@types/component-emitter": "^1.2.10", @@ -6788,25 +6996,23 @@ "dev": true }, "streamroller": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-1.0.6.tgz", - "integrity": "sha512-3QC47Mhv3/aZNFpDDVO44qQb9gwB9QggMEE0sQmkTAwBVYdBRWISdsywlkfm5II1Q5y/pmrHflti/IgmIzdDBg==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-3.1.2.tgz", + "integrity": "sha512-wZswqzbgGGsXYIrBYhOE0yP+nQ6XRk7xDcYwuQAGTYXdyAUmvgVFE0YU1g5pvQT0m7GBaQfYcSnlHbapuK0H0A==", "dev": true, "requires": { - "async": "^2.6.2", - "date-format": "^2.0.0", - "debug": "^3.2.6", - "fs-extra": "^7.0.1", - "lodash": "^4.17.14" + "date-format": "^4.0.13", + "debug": "^4.3.4", + "fs-extra": "^8.1.0" }, "dependencies": { "debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "dev": true, "requires": { - "ms": "^2.1.1" + "ms": "2.1.2" } } } @@ -7006,7 +7212,7 @@ "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=", + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", "dev": true }, "to-object-path": { @@ -7090,9 +7296,9 @@ } }, "tslib": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.1.tgz", - "integrity": "sha512-SgIkNheinmEBgx1IUNirK0TUD4X9yjjBRTqqjggWCU3pUEqIk3/Uwl3yRixYKT6WjQuGiwDv4NomL3wqRCj+CQ==", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==", "dev": true }, "tslint": { @@ -7265,9 +7471,9 @@ "dev": true }, "typescript": { - "version": "3.9.10", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.10.tgz", - "integrity": "sha512-w6fIxVE/H1PkLKcCPsFqKE7Kv7QUwhU8qQY2MueZXWx5cPZdwFupLgKK3vntcK98BtNHZtAF4LA/yl2a7k8R6Q==", + "version": "4.7.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.4.tgz", + "integrity": "sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==", "dev": true }, "ua-parser-js": { @@ -7382,6 +7588,16 @@ "dev": true, "optional": true }, + "update-browserslist-db": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.5.tgz", + "integrity": "sha512-dteFFpCyvuDdr9S/ff1ISkKt/9YZxKjI9WlRR99c180GaztJtRa/fn18FdxGVKVsnPY7/a/FDN68mcvUmP4U7Q==", + "dev": true, + "requires": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0" + } + }, "uri-js": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", @@ -7478,7 +7694,7 @@ "void-elements": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-2.0.1.tgz", - "integrity": "sha1-wGavtYK7HLQSjWDqkjkulNXp2+w=", + "integrity": "sha512-qZKX4RnBzH2ugr8Lxa7x+0V6XD9Sb/ouARtiasEQCHB1EVU4NXtmHsDDrx1dO4ne5fc3J6EW05BP1Dl0z0iung==", "dev": true }, "watchpack": { @@ -7743,7 +7959,7 @@ "wcwidth": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", - "integrity": "sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g=", + "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", "dev": true, "requires": { "defaults": "^1.0.3" @@ -8178,17 +8394,121 @@ "dev": true }, "which-typed-array": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.7.tgz", - "integrity": "sha512-vjxaB4nfDqwKI0ws7wZpxIlde1XrLX5uB0ZjpfshgmapJMD7jJWhZI+yToJTqaFByF0eNBcYxbjmCzoRP7CfEw==", + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.8.tgz", + "integrity": "sha512-Jn4e5PItbcAHyLoRDwvPj1ypu27DJbtdYXUa5zsinrUx77Uvfb0cXwwnGMTn7cjUfhhqgVQnVJCwF+7cgU7tpw==", "dev": true, "requires": { "available-typed-arrays": "^1.0.5", "call-bind": "^1.0.2", - "es-abstract": "^1.18.5", - "foreach": "^2.0.5", + "es-abstract": "^1.20.0", + "for-each": "^0.3.3", "has-tostringtag": "^1.0.0", - "is-typed-array": "^1.1.7" + "is-typed-array": "^1.1.9" + }, + "dependencies": { + "define-properties": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.4.tgz", + "integrity": "sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==", + "dev": true, + "requires": { + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + } + }, + "es-abstract": { + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.20.1.tgz", + "integrity": "sha512-WEm2oBhfoI2sImeM4OF2zE2V3BYdSF+KnSi9Sidz51fQHd7+JuF8Xgcj9/0o+OWeIeIS/MiuNnlruQrJf16GQA==", + "dev": true, + "requires": { + "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.3", + "string.prototype.trimend": "^1.0.5", + "string.prototype.trimstart": "^1.0.5", + "unbox-primitive": "^1.0.2" + } + }, + "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==", + "dev": true + }, + "has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "dev": true + }, + "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==", + "dev": true, + "requires": { + "call-bind": "^1.0.2" + } + }, + "object-inspect": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz", + "integrity": "sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==", + "dev": true + }, + "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==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.19.5" + } + }, + "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==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.19.5" + } + }, + "unbox-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", + "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "has-bigints": "^1.0.2", + "has-symbols": "^1.0.3", + "which-boxed-primitive": "^1.0.2" + } + } } }, "wide-align": { diff --git a/package.json b/package.json index 378f5cc0..ad05f42a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@al/core", - "version": "1.0.190", + "version": "2.0.0", "description": "Node Enterprise Packages for Alert Logic (NEPAL) Core Library", "main": "./dist/index.cjs.js", "types": "./dist/index.d.ts", @@ -41,28 +41,29 @@ "devDependencies": { "@types/auth0-js": "^9.14.5", "@types/chai": "^4.2.21", - "@types/karma": "^5.0.0", + "@types/karma": "^6.3.3", "@types/mocha": "^7.0.2", "@types/qs": "^6.9.7", "@types/sinon": "^9.0.0", "chai": "^4.2.0", "copy-webpack-plugin": "^5.0.5", - "karma": "^6.3.4", - "karma-chrome-launcher": "^3.1.0", + "karma": "^6.4.0", + "karma-chrome-launcher": "^3.1.1", "karma-cli": "^2.0.0", - "karma-mocha": "^1.3.0", - "karma-typescript": "^5.0.2", + "karma-mocha": "^2.0.1", + "karma-typescript": "^5.5.3", "mocha": "~7.0.1", "peer-deps-externals-webpack-plugin": "^1.0.4", "rollup": "^2.56.2", "rollup-plugin-copy": "^3.3.0", "rollup-plugin-terser": "^5.3.0", - "rollup-plugin-typescript2": "^0.27.0", + "rollup-plugin-typescript2": "^0.32.1", "sinon": "^9.0.2", "ts-loader": "^6.2.2", + "tslib": "^2.4.0", "tslint": "^5.12.1", "tslint-config-airbnb": "^5.11.1", - "typescript": "^3.9.10", + "typescript": "^4.7.4", "webpack": "^4.41.2", "webpack-bundle-analyzer": "^3.6.0", "webpack-cli": "^3.2.1", diff --git a/src/aims-client/aims-client.ts b/src/aims-client/aims-client.ts deleted file mode 100644 index 47971c03..00000000 --- a/src/aims-client/aims-client.ts +++ /dev/null @@ -1,878 +0,0 @@ -/** - * Module to deal with available AIMS Public API endpoints - */ - -import { - AlApiClient, - AlDefaultClient, -} from "../client"; -import { AlValidationSchemaProvider } from '../common/utility'; -import { - AlLocation, - AlLocatorService, -} from "../common/navigation"; -import { - AIMSAccessKey, - AIMSAccount, - AIMSAuthenticationTokenInfo, - AIMSOrganization, - AIMSRole, - AIMSSessionDescriptor, - AIMSTopology, - AIMSUser, - AIMSUserDetails, - AIMSEnrollURI, -} from './types'; -import { aimsTypeSchematics } from './aims.schematics'; - -export class AIMSClientInstance implements AlValidationSchemaProvider { - - private client:AlApiClient; - private serviceName = 'aims'; - private serviceVersion:string = "v1"; - - constructor( client:AlApiClient = null ) { - this.client = client || AlDefaultClient; - } - - /** - * Create a user - * POST - * /aims/v1/:account_id/users?one_time_password=:one_time_password - * "https://api.cloudinsight.alertlogic.com/aims/v1/12345678/users" - * -d '{ "name": "Bob Dobalina", "email": "admin@company.com", "mobile_phone": "123-555-0123" }' - */ - async createUser(accountId: string, name: string, email: string, mobilePhone: string) { - const user = await this.client.post({ - service_stack: AlLocation.InsightAPI, - service_name: this.serviceName, - version: this.serviceVersion, - account_id: accountId, - path: '/users', - data: { name, email, mobile_phone: mobilePhone } - }); - return user as AIMSUser; - } - - /** - * Create a user with details - * POST - * /aims/v1/:account_id/users - * "https://api.cloudinsight.alertlogic.com/aims/v1/12345678/users" - * -d '{ "name": "Bob Dobalina", "email": "admin@company.com", "phone": "12321312", "mobile_phone": "123-555-0123" }' - */ - async createUserWithDetails(accountId: string, userDetails:AIMSUserDetails) { - return this.client.post({ - service_stack: AlLocation.InsightAPI, - service_name: this.serviceName, - version: this.serviceVersion, - account_id: accountId, - path: '/users', - data: userDetails - }); - } - - /** - * Update user details - * POST - * /aims/v1/:account_id/users/:user_id - * -d '{"name": "Bob Odenkirk", "email": "bodenkirk@company.com", "mobile_phone": "123-555-0124"}' "https://api.product.dev.alertlogic.com/aims/v1/12345678/users/715A4EC0-9833-4D6E-9C03-A537E3F98D23" - */ - async updateUserDetails(accountId: string, userId: string, data:AIMSUserDetails):Promise { - const userDetailsUpdate = await this.client.post({ - service_stack: AlLocation.InsightAPI, - service_name: this.serviceName, - version: this.serviceVersion, - account_id: accountId, - path: `/users/${userId}`, - data: data - }); - return userDetailsUpdate; - } - - /** - * Delete a user - * DELETE - * /aims/v1/:account_id/users/:user_id - * "https://api.cloudinsight.alertlogic.com/aims/v1/12345678/users/715A4EC0-9833-4D6E-9C03-A537E3F98D23" - */ - async deleteUser(accountId: string, userId: string) { - const userDelete = await this.client.delete({ - service_stack: AlLocation.InsightAPI, - service_name: this.serviceName, - version: this.serviceVersion, - account_id: accountId, - path: `/users/${userId}`, - }); - return userDelete; - } - - /** - * Get user details - * GET - * /aims/v1/:account_id/users/:user_id - * "https://api.cloudinsight.alertlogic.com/aims/v1/12345678/users/715A4EC0-9833-4D6E-9C03-A537E3F98D23" - */ - async getUserDetailsById(accountId: string, userId: string) { - const userDetails = await this.client.get({ - service_stack: AlLocation.InsightAPI, - service_name: this.serviceName, - version: this.serviceVersion, - account_id: accountId, - path: `/users/${userId}`, - ttl: 2 * 60 * 1000 - }); - return userDetails as AIMSUser; - } - - async getUserDetailsByUserId(userId: string) { - const userDetails = await this.client.get({ - service_stack: AlLocation.InsightAPI, - service_name: this.serviceName, - version: this.serviceVersion, - path: `/user/${userId}` - }); - return userDetails as AIMSUser; - } - - /** - * Get user permissions - * GET - * /aims/v1/:account_id/users/:user_id/permissions - * "https://api.cloudinsight.alertlogic.com/aims/v1/12345678/users/715A4EC0-9833-4D6E-9C03-A537E3F98D23/permissions" - */ - async getUserPermissions(accountId: string, userId: string) { - const userPermissions = await this.client.get({ - service_stack: AlLocation.InsightAPI, - service_name: this.serviceName, - version: this.serviceVersion, - account_id: accountId, - path: `/users/${userId}/permissions`, - ttl: 2 * 60 * 1000 - }); - return userPermissions; - } - - /** - * Get Account Details - * GET - * /aims/v1/:account_id/account - * "https://api.cloudinsight.alertlogic.com/aims/v1/12345678/account" - */ - async getAccountDetails(accountId: string) { - const accountDetails = await this.client.get({ - service_stack: AlLocation.InsightAPI, - service_name: this.serviceName, - version: this.serviceVersion, - account_id: accountId, - path: '/account', - ttl: 2 * 60 * 1000 - }); - return accountDetails as AIMSAccount; - } - - /** - * @deprecated use getAccountsByRelationship - * List managed accounts - * GET - * /aims/v1/:account_id/accounts/:relationship - * "https://api.cloudinsight.alertlogic.com/aims/v1/12345678/accounts/managed" - */ - async getManagedAccounts(accountId: string, queryParams?):Promise { - return this.getAccountsByRelationship(accountId, 'managed', queryParams ); - } - - /** - * @deprecated use getAccountIdsByRelationship - * List managed account IDs - * GET - * /aims/v1/:account_id/account_ids/:relationship - * "https://api.cloudinsight.alertlogic.com/aims/v1/12345678/account_ids/managed" - */ - async getManagedAccountIds(accountId: string, queryParams?):Promise { - return this.getAccountIdsByRelationship(accountId, 'managed', queryParams ); - } - - /** - * List account IDs, by relationship can be managing, managed and bills_to - * GET - * /aims/v1/:account_id/account_ids/:relationship - * "https://api.cloudinsight.alertlogic.com/aims/v1/12345678/account_ids/managing" - * "https://api.cloudinsight.alertlogic.com/aims/v1/12345678/account_ids/managed" - * "https://api.cloudinsight.alertlogic.com/aims/v1/12345678/account_ids/bills_to" - */ - async getAccountIdsByRelationship(accountId: string, relationship: string, queryParams?):Promise { - const accountIds = await this.client.get({ - service_stack: AlLocation.InsightAPI, - service_name: this.serviceName, - version: this.serviceVersion, - account_id: accountId, - path: `/account_ids/${relationship}`, - params: queryParams, - ttl: 2 * 60 * 1000 - }); - return accountIds.account_ids as string[]; - } - - /** - * List accounts, by relationship can be managing, managed and bills_to - * GET - * /aims/v1/:account_id/accounts/:relationship - * "https://api.cloudinsight.alertlogic.com/aims/v1/12345678/accounts/managing" - * "https://api.cloudinsight.alertlogic.com/aims/v1/12345678/accounts/managed" - * "https://api.cloudinsight.alertlogic.com/aims/v1/12345678/accounts/bills_to" - */ - async getAccountsByRelationship(accountId: string, relationship: string, queryParams?):Promise { - const managedAccounts = await this.client.get({ - service_stack: AlLocation.InsightAPI, - service_name: this.serviceName, - version: this.serviceVersion, - account_id: accountId, - path: `/accounts/${relationship}`, - params: queryParams, - ttl: 2 * 60 * 1000 - }); - return managedAccounts.accounts as AIMSAccount[]; - } - - /** - * Retrieve a union of user records corresponding to a managed relationship hierarchy between two accounts. - * This is a placeholder for a better implementation based on a relationship topology endpoint from AIMS.0 - * @deprecated use getAccountsIdsByRelationship in conjunction with getUsersFromAccounts - */ - async getUsersFromManagedRelationship( leafAccountId:string, terminalAccountId?:string, failOnError:boolean = true ):Promise { - let users = await this.getUsers( leafAccountId, { include_role_ids: false, include_user_credential: false } ); - try { - let managing = await this.getAccountsByRelationship( leafAccountId, "managing" ); - if ( managing.length > 0 ) { - managing.sort( ( a, b ) => parseInt( b.id, 10 ) - parseInt( a.id, 10 ) ); // this is gross hackery. Kevin did not implement this. Tell no-one of what you've seen! - let parentUsers = await this.getUsersFromManagedRelationship( managing[0].id, terminalAccountId ); - if ( Array.isArray( parentUsers ) ) { - users = users.concat( parentUsers ); - } - } - } catch( e ) { - if ( failOnError ) { - throw e; - } - } - return users; - } - - /** - * Update account MFA requirements - * POST - * /aims/v1/:account_id/account - * -d '{"mfa_required": true}' "https://api.cloudinsight.alertlogic.com/aims/v1/12345678/account" - */ - async requireMFA(accountId: string, mfaRequired: boolean):Promise { - const account = await this.client.post({ - service_stack: AlLocation.InsightAPI, - service_name: this.serviceName, - version: this.serviceVersion, - account_id: accountId, - path: '/account', - data: { mfa_required: mfaRequired } - }); - return account as AIMSAccount; - } - - /** - * Update account session idle expiration - * POST - * This updates a single property of an AIMS account record, affecting how long users of that account - * can be idle before their sessions will be terminated due to inactivity. - */ - async setAccountIdleThreshold( accountId:string, seconds:number|null ) { - await this.client.post( { - service_stack: AlLocation.GlobalAPI, - service_name: this.serviceName, - version: this.serviceVersion, - account_id: accountId, - path: '/account', - data: { - idle_session_timeout: seconds - } - } ); - } - - /** - * Authenticate a user's identity - * POST - * /aims/v1/authenticate - * -u username:password "https://api.cloudinsight.alertlogic.com/aims/v1/authenticate" - */ - async authenticate( user:string, pass:string, mfa?:string ): Promise { - return this.client.authenticate( user, pass, mfa, true ); - } - - /** - * Authenticate a user's identity with an mfa code and session token - */ - async authenticateWithMFASessionToken(token: string, mfa: string): Promise { - return this.client.authenticateWithMFASessionToken(token, mfa, true ); - } - - /** - * Change a user's password - * POST - * /aims/v1/change_password - * -d '{"email": "admin@company.com", "current_password": "hunter2", "new_password": "Fraudulent$Foes"}' "https://api.cloudinsight.alertlogic.com/aims/v1/change_password" - */ - async changePassword(email: string, password: string, newPassword: string) { - const changePass = await this.client.post({ - service_stack: AlLocation.InsightAPI, - service_name: this.serviceName, - version: this.serviceVersion, - path: '/change_password', - data: { email, current_password: password, new_password: newPassword } - }); - return changePass; - } - - /** - * Obtain Authentication Token Information (Account, User, Roles, etc.) - * - * @deprecated - * - * GET - * /aims/v1/token_info - * "https://api.cloudinsight.alertlogic.com/aims/v1/token_info" - */ - async tokenInfo() { - const tokenData = await this.client.get({ - service_stack: AlLocation.InsightAPI, - service_name: this.serviceName, - version: this.serviceVersion, - path: '/token_info', - }); - return tokenData as AIMSAuthenticationTokenInfo; - } - - /** - * Obtain Authentication Token Information for a specific access token - */ - public async getTokenInfo( accessToken:string ):Promise { - return this.client.get( { - service_stack: AlLocation.GlobalAPI, - service_name: this.serviceName, - version: 1, - path: '/token_info', - headers: { - 'X-AIMS-Auth-Token': accessToken - }, - ttl: 10 * 60 * 1000, - cacheKey: AlLocatorService.resolveURL( AlLocation.GlobalAPI, `/aims/v1/token_info/${accessToken}` ) // custom cacheKey to avoid cache pollution - } ); - } - - /** - * Initiate the password reset process for a user - * POST - * /aims/v1/reset_password - * -d '{"email": "admin@company.com", "return_to": "https://console.alertlogic.net"}' "https://api.cloudinsight.alertlogic.com/aims/v1/reset_password" - */ - async initiateReset(email: string, returnTo: string) { - const reset = await this.client.post({ - service_stack: AlLocation.InsightAPI, - service_name: this.serviceName, - version: this.serviceVersion, - path: '/reset_password', - data: { email, return_to: returnTo }, - }); - return reset; - } - - /** - * Reset a user's password using a token - * PUT - * /aims/v1/reset_password/:token - * -d '{"password": "hunter2"}' "https://api.cloudinsight.alertlogic.com/aims/v1/reset_password/69EtspCz3c4" - */ - async resetWithToken(token: string, password: string) { - const reset = await this.client.put({ - service_stack: AlLocation.InsightAPI, - service_name: this.serviceName, - version: this.serviceVersion, - path: `/reset_password/${token}`, - data: { password }, - }); - return reset; - } - - /** - * Create a role - * POST - * /aims/v1/:account_id/roles - * -d '{"name": "Super Mega Power User", "permissions": {"*:own:*:*": "allowed", "aims:own:grant:*":"allowed"}}' "https://api.cloudinsight.alertlogic.com/aims/v1/12345678/roles" - */ - async createRole(accountId: string, name: string, permissions) { - const createRole = await this.client.post({ - service_stack: AlLocation.InsightAPI, - service_name: this.serviceName, - version: this.serviceVersion, - account_id: accountId, - path: '/roles', - data: { name, permissions } - }); - return createRole as AIMSRole; - } - - /** - * Delete a role - * DELETE - * /aims/v1/:account_id/roles/:role_id - * "https://api.cloudinsight.alertlogic.com/aims/v1/12345678/roles/C7C5BE57-F199-4F14-BCB5-43E31CA02842" - */ - async deleteRole(accountId: string, roleId: string) { - const roleDelete = await this.client.delete({ - service_stack: AlLocation.InsightAPI, - service_name: this.serviceName, - version: this.serviceVersion, - account_id: accountId, - path: `/roles/${roleId}` - }); - return roleDelete; - } - - /** - * Grant a role - * PUT - * /aims/v1/:account_id/users/:user_id/roles/:role_id - * "https://api.product.dev.alertlogic.com/aims/v1/12345678/users/715A4EC0-9833-4D6E-9C03-A537E3F98D23/roles/2A33175D-86EF-44B5-AA39-C9549F6306DF" - */ - async grantRole(accountId:string, userId:string, roleId:string) { - return this.client.put({ - service_stack: AlLocation.InsightAPI, - service_name: this.serviceName, - version: this.serviceVersion, - account_id: accountId, - path: `/users/${userId}/roles/${roleId}` - }); - } - - /** - * Revoke a role - * DELETE - * /aims/v1/:account_id/users/:user_id/roles/:role_id - * "https://api.product.dev.alertlogic.com/aims/v1/12345678/users/715A4EC0-9833-4D6E-9C03-A537E3F98D23/roles/2A33175D-86EF-44B5-AA39-C9549F6306DF" - */ - async revokeRole(accountId:string, userId:string, roleId:string) { - return this.client.delete({ - service_stack: AlLocation.InsightAPI, - service_name: this.serviceName, - version: this.serviceVersion, - account_id: accountId, - path: `/users/${userId}/roles/${roleId}` - }); - } - - /** - * Get global role, a role that is shared among accounts. - * GET - * /aims/v1/roles/:role_id - * "https://api.cloudinsight.alertlogic.com/aims/v1/roles/2A33175D-86EF-44B5-AA39-C9549F6306DF" - */ - async getGlobalRole(roleId: string) { - const role = await this.client.get({ - service_stack: AlLocation.InsightAPI, - service_name: this.serviceName, - version: this.serviceVersion, - path: `/roles/${roleId}` - }); - return role as AIMSRole; - } - - /** - * Get role - * GET - * /aims/v1/:account_id/roles/:role_id - * "https://api.cloudinsight.alertlogic.com/aims/v1/12345678/roles/2A33175D-86EF-44B5-AA39-C9549F6306DF" - */ - async getAccountRole(accountId: string, roleId: string) { - const role = await this.client.get({ - service_stack: AlLocation.InsightAPI, - service_name: this.serviceName, - version: this.serviceVersion, - account_id: accountId, - path: `/roles/${roleId}` - }); - return role as AIMSRole; - } - - /** - * Get assigned roles - * GET - * /aims/v1/:account_id/users/:user_id/roles - * "https://api.cloudinsight.alertlogic.com/aims/v1/12345678/users/715A4EC0-9833-4D6E-9C03-A537E3F98D23/roles" - */ - async getAssignedRoles( accountId:string, userId:string ):Promise { - const roles = await this.client.get({ - service_stack: AlLocation.InsightAPI, - service_name: this.serviceName, - version: this.serviceVersion, - account_id: accountId, - path: `/users/${userId}/roles` - }); - return roles.roles; - } - - /** - * List global roles, roles that are shared among all accounts. - * GET - * /aims/v1/roles - * "https://api.cloudinsight.alertlogic.com/aims/v1/roles" - */ - async getGlobalRoles():Promise { - const roles = await this.client.get({ - service_stack: AlLocation.InsightAPI, - service_name: this.serviceName, - version: this.serviceVersion, - path: '/roles' - }); - return roles.roles; - } - - /** - * List roles for an account. Global roles are included in the list. - * GET - * /aims/v1/:account_id/roles - * "https://api.cloudinsight.alertlogic.com/aims/v1/12345678/roles" - */ - async getAccountRoles(accountId: string):Promise { - const roles = await this.client.get({ - service_stack: AlLocation.InsightAPI, - service_name: this.serviceName, - version: this.serviceVersion, - account_id: accountId, - path: '/roles' - }); - return roles.roles as AIMSRole[]; - } - - /** - * Update Role Name and Permissions - * POST - * /aims/v1/:account_id/roles/:role_id - * -d '{"name": "Mega Power User", "permissions": {"*:own:*:*": "allowed", "aims:own:grant:*":"allowed"}}' "https://api.cloudinsight.alertlogic.com/aims/v1/12345678/roles/2A33175D-86EF-44B5-AA39-C9549F6306DF" - */ - async updateRole(accountId: string, name: string, permissions) { - const roleUpdate = await this.client.post({ - service_stack: AlLocation.InsightAPI, - service_name: this.serviceName, - version: this.serviceVersion, - account_id: accountId, - path: '/roles', - data: { name, permissions } - }); - return roleUpdate; - } - /** - * Update Role Name - * POST - * /aims/v1/:account_id/roles/:role_id - * -d '{"name": "Mega Power User"}' "https://api.cloudinsight.alertlogic.com/aims/v1/12345678/roles/2A33175D-86EF-44B5-AA39-C9549F6306DF" - */ - async updateRoleName(accountId: string, name: string) { - const updateRole = await this.client.post({ - service_stack: AlLocation.InsightAPI, - service_name: this.serviceName, - version: this.serviceVersion, - account_id: accountId, - path: '/roles', - data: { name } - }); - return updateRole as AIMSRole; - } - /** - * Update Role Permissions - * POST - * /aims/v1/:account_id/roles/:role_id - * -d '{"permissions": {"*:own:*:*": "allowed", "aims:own:grant:*":"allowed"}}' "https://api.cloudinsight.alertlogic.com/aims/v1/12345678/roles/2A33175D-86EF-44B5-AA39-C9549F6306DF" - */ - async updateRolePermissions(accountId: string, permissions) { - const updateRole = await this.client.post({ - service_stack: AlLocation.InsightAPI, - service_name: this.serviceName, - version: this.serviceVersion, - account_id: accountId, - path: '/roles', - data: { permissions } - }); - return updateRole as AIMSRole as AIMSRole; - } - - /** - * Enroll an MFA device for a user - * POST - * /aims/v1/user/mfa/enroll - * "https://api.cloudinsight.alertlogic.com/aims/v1/user/mfa/enroll" \ - * -H "Content-Type: application/json" \ - * -H "X-Aims-Session-Token: a3e12fwafge1g9" \ - * -d @- << EOF - * { - * "mfa_uri": "otpauth://totp/Alert%20Logic:admin@company.com?secret=GFZSA5CINFJSA4ZTNNZDG5BAKM2EMMZ7&issuer=Alert%20Logic&algorithm=SHA1" - * "mfa_codes": ["123456", "456789"] - * } - * EOF - */ - async enrollMFA( uri: string, sessionToken:string, codes:string[] ) { - const mfa = await this.client.post({ - service_stack: AlLocation.InsightAPI, - service_name: this.serviceName, - version: this.serviceVersion, - path: '/user/mfa/enroll', - data: { mfa_uri: uri, mfa_codes: codes }, - headers: { - 'X-AIMS-Session-Token': sessionToken - } - }); - return mfa; - } - - /** - * Enroll an MFA device for a user (when no AIMS token available). - * POST - * /aims/v1/user/mfa/enroll - * "https://api.cloudinsight.alertlogic.com/aims/v1/user/mfa/enroll" \ - * -H "Content-Type: application/json" \ - * -d @- << EOF - * { - * "mfa_uri": "otpauth://totp/Alert%20Logic:admin@company.com?secret=GFZSA5CINFJSA4ZTNNZDG5BAKM2EMMZ7&issuer=Alert%20Logic&algorithm=SHA1" - * "mfa_codes": ["123456", "456789"], - * "password" : "password", - * "email" : "user@email.com" - * } - * EOF - */ - async enrollMFAWithoutAIMSToken(uri:AIMSEnrollURI, codes:string[], email:string, password:string ) { - return this.client.post({ - service_stack: AlLocation.InsightAPI, - service_name: this.serviceName, - version: this.serviceVersion, - path: '/user/mfa/enroll', - data: { - mfa_uri: uri.toString(), - email: email, - password: password, - mfa_codes: codes - } - }); - } - - /** - * Remove a user's MFA device - * DELETE - * /aims/v1/user/mfa/:email - * "https://api.cloudinsight.alertlogic.com/aims/v1/user/mfa/admin@company.com" - */ - async deleteMFA(email: string) { - const mfa = await this.client.delete({ - service_stack: AlLocation.InsightAPI, - service_name: this.serviceName, - version: this.serviceVersion, - path: `/user/mfa/${email}`, - }); - return mfa; - } - - async getUserDetails(accountId: string, userId: string, queryParams?: {include_role_ids?: boolean, include_user_credential?: boolean}) { - const user = await this.client.get({ - service_stack: AlLocation.InsightAPI, - service_name: this.serviceName, - version: this.serviceVersion, - account_id: accountId, - path: `/users/${userId}`, - params: queryParams, - }); - return user as AIMSUser; - } - - /** - * List Users - * GET - * /aims/v1/:account_id/users - * "https://api.cloudinsight.alertlogic.com/aims/v1/12345678/users" - */ - async getUsers( accountId: string, - queryParams?: {include_role_ids?: boolean, include_user_credential?: boolean} ):Promise { - const users = await this.client.get({ - service_stack: AlLocation.InsightAPI, - service_name: this.serviceName, - version: this.serviceVersion, - account_id: accountId, - path: '/users', - params: queryParams, - }); - return users.users as AIMSUser[]; - } - - /** - * Create Access Key - * POST - * /aims/v1/:account_id/users/:user_id/access_keys - * "https://api.cloudinsight.alertlogic.com/aims/v1/12345678/users/715A4EC0-9833-4D6E-9C03-A537E3F98D23/access_keys" - * -d '{"label": "api access"}' - */ - async createAccessKey(accountId: string, userId: string, label: string) { - const key = await this.client.post({ - service_stack: AlLocation.InsightAPI, - service_name: this.serviceName, - version: this.serviceVersion, - account_id: accountId, - path: `/users/${userId}/access_keys`, - data: { label } - }); - return key as AIMSAccessKey; - } - - /** - * Update Access Key - * POST - * /aims/v1/access_keys/:access_key_id - * "https://api.cloudinsight.alertlogic.com/aims/v1/access_keys/61fb235617960503" - * -d '{"label": "api access"}' - */ - async updateAccessKey(accessKeyId: string, label: string) { - const key = await this.client.post({ - service_stack: AlLocation.InsightAPI, - service_name: this.serviceName, - version: this.serviceVersion, - path: `/access_keys/${accessKeyId}`, - data: { label } - }); - return key as AIMSAccessKey; - } - - /** - * Get Access Key - * GET - * /aims/v1/access_keys/:access_key_id - * "https://api.cloudinsight.alertlogic.com/aims/v1/access_keys/61fb235617960503" - */ - async getAccessKey(accessKeyId: string) { - const key = await this.client.get({ - service_stack: AlLocation.InsightAPI, - service_name: this.serviceName, - version: this.serviceVersion, - path: `/access_keys/${accessKeyId}` - }); - return key as AIMSAccessKey; - } - - /** - * List Access Keys - * GET - * /aims/v1/:account_id/users/:user_id/access_keys?out=:out - * https://api.cloudinsight.alertlogic.com/aims/v1/12345678/users/715A4EC0-9833-4D6E-9C03-A537E3F98D23/access_keys?out=full" - */ - async getAccessKeys(accountId: string, userId: string, ttl: number = 60000) { - const keys = await this.client.get({ - service_stack: AlLocation.InsightAPI, - service_name: this.serviceName, - version: this.serviceVersion, - account_id: accountId, - ttl: ttl, - path: `/users/${userId}/access_keys?out=full` - }); - return keys.access_keys as AIMSAccessKey[]; - } - - /** - * Delete Access Key - * DELETE - * /aims/v1/:account_id/users/:user_id/access_keys/:access_key_id - * "https://api.cloudinsight.alertlogic.com/aims/v1/12345678/users/715A4EC0-9833-4D6E-9C03-A537E3F98D23/access_keys/61FB235617960503" - */ - async deleteAccessKey(accountId: string, userId: string, accessKeyId: string) { - const keyDelete = await this.client.delete({ - service_stack: AlLocation.InsightAPI, - service_name: this.serviceName, - version: this.serviceVersion, - account_id: accountId, - path: `/users/${userId}/access_keys/${accessKeyId}` - }); - return keyDelete; - } - - /** - * Retrieve linked organization - */ - async getAccountOrganization( accountId:string ):Promise { - const requestDescriptor = { - service_stack: AlLocation.InsightAPI, - service_name: this.serviceName, - version: 1, - account_id: accountId, - path: '/organization' - }; - return await this.client.get( requestDescriptor ) as AIMSOrganization; - } - - /** - * This endpoint render's an accounts related accounts topologically by adding a :relationship field to the account object, - * which contains an array of accounts that are directly related to it. - * GET - * /aims/v1/:account_id/accounts/:relationship/topology - * https://console.product.dev.alertlogic.com/api/aims/index.html#api-AIMS_Account_Resources-AccountRelationshipExists - * @param accountId {string} - * @param relationship {'managed' | 'managing'} - * @param queryParms {Object} - */ - async getAccountRelationshipTopology(accountId: string, relationship: 'managed' | 'managing', queryParams?): Promise { - const response = await this.client.get({ - service_stack: AlLocation.InsightAPI, - service_name: this.serviceName, - version: this.serviceVersion, - account_id: accountId, - path: `/accounts/${relationship}/topology`, - params: queryParams - }); - return response.topology as AIMSTopology; - } - - /** - * Returns the ids of the accounts to which an account is related. - * The related accounts that are returned depend oonf the :relationship param. - * If using a "managed" relationship, this returns all accounts that the current account manages. - * If using a "managing" relationship, this returns all accounts that managing the current account. - * @param accountId {string} - * @param relationship {'managed' | 'managing'} - * @param addCurrentId {boolean} [addCurrentId=true] true if wants add the current id to the return - */ - async getAccountsIdsByRelationship(accountId: string, relationship: 'managed' | 'managing', addCurrentId: boolean = true): Promise { - const topology = await this.getAccountRelationshipTopology(accountId, relationship); - - function getIds(accounts: AIMSTopology[]): string[] { - return accounts.flatMap(a => [a.id, ...getIds(Array.isArray(a[relationship]) ? a[relationship] : [])]); - } - const first = addCurrentId ? [accountId] : []; - return [...first, ...getIds(topology[relationship])]; - } - - /** - * Returns all users associated with a list of accounts - * @param accountList {string[]} - */ - async getUsersFromAccounts(accountList: string[]): Promise { - return (await Promise.all( - accountList.map(account => this.getUsers(account, { include_role_ids: false, include_user_credential: false })) - )).flat(); - } - - public hasSchema( schemaId:string ) { - return schemaId in aimsTypeSchematics; - } - - public async getSchema( schemaId:string ) { - return aimsTypeSchematics[schemaId]; - } - - public getProviders() { - return [ AlDefaultClient ]; - } - -} - -/* tslint:disable:variable-name */ -export const AIMSClient = new AIMSClientInstance(); diff --git a/src/aims-client/index.ts b/src/aims-client/index.ts deleted file mode 100644 index 940e1b20..00000000 --- a/src/aims-client/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from "./aims-client"; -export * from "./types/index"; diff --git a/src/aims-client/README.md b/src/client/aims/README.md similarity index 100% rename from src/aims-client/README.md rename to src/client/aims/README.md diff --git a/src/aims-client/aims.schematics.ts b/src/client/aims/aims.schematics.ts similarity index 100% rename from src/aims-client/aims.schematics.ts rename to src/client/aims/aims.schematics.ts diff --git a/src/client/aims/aims.service-client.ts b/src/client/aims/aims.service-client.ts new file mode 100644 index 00000000..ea57246f --- /dev/null +++ b/src/client/aims/aims.service-client.ts @@ -0,0 +1,702 @@ +/** + * Module to deal with available AIMS Public API endpoints + */ + +import { AlValidationSchemaProvider } from '../../common/utility'; +import { + AlLocation, + AlLocatorService, +} from "../../common/navigation"; +import { ServiceClient, AlBaseServiceClient } from '../types'; +import { + AIMSAccessKey, + AIMSAccount, + AIMSAuthenticationTokenInfo, + AIMSOrganization, + AIMSRole, + AIMSSessionDescriptor, + AIMSTopology, + AIMSUser, + AIMSUserDetails, + AIMSEnrollURI, +} from './types'; +import { aimsTypeSchematics } from './aims.schematics'; +import { AlXHRAdapter } from '../al-xhr-adapter'; + +@ServiceClient( { + service_stack: AlLocation.InsightAPI, + service_name: "aims", + version: "v1" +} ) +export class AlsAIMS + extends AlBaseServiceClient + implements AlValidationSchemaProvider { + + constructor() { + super(); + } + + /** + * Create a user + * POST + * /aims/v1/:account_id/users?one_time_password=:one_time_password + * "https://api.cloudinsight.alertlogic.com/aims/v1/12345678/users" + * -d '{ "name": "Bob Dobalina", "email": "admin@company.com", "mobile_phone": "123-555-0123" }' + */ + async createUser(accountId: string, name: string, email: string, mobilePhone: string) { + return this.post( { + account_id: accountId, + path: '/users', + data: { name, email, mobile_phone: mobilePhone } + } ); + } + + /** + * Create a user with details + * POST + * /aims/v1/:account_id/users + * "https://api.cloudinsight.alertlogic.com/aims/v1/12345678/users" + * -d '{ "name": "Bob Dobalina", "email": "admin@company.com", "phone": "12321312", "mobile_phone": "123-555-0123" }' + */ + async createUserWithDetails(accountId: string, userDetails:AIMSUserDetails) { + return this.post( { + account_id: accountId, + path: '/users', + data: userDetails + } ); + } + + /** + * Update user details + * POST + * /aims/v1/:account_id/users/:user_id + * -d '{"name": "Bob Odenkirk", "email": "bodenkirk@company.com", "mobile_phone": "123-555-0124"}' "https://api.product.dev.alertlogic.com/aims/v1/12345678/users/715A4EC0-9833-4D6E-9C03-A537E3F98D23" + */ + async updateUserDetails(accountId: string, userId: string, data:AIMSUserDetails):Promise { + return this.post( { + account_id: accountId, + path: `/users/${userId}`, + data: data + } ); + } + + /** + * Delete a user + * DELETE + * /aims/v1/:account_id/users/:user_id + * "https://api.cloudinsight.alertlogic.com/aims/v1/12345678/users/715A4EC0-9833-4D6E-9C03-A537E3F98D23" + */ + async deleteUser(accountId: string, userId: string) { + return this.delete( { + account_id: accountId, + path: `/users/${userId}`, + } ); + } + + /** + * Get user details + * GET + * /aims/v1/:account_id/users/:user_id + * "https://api.cloudinsight.alertlogic.com/aims/v1/12345678/users/715A4EC0-9833-4D6E-9C03-A537E3F98D23" + */ + async getUserDetailsById(accountId: string, userId: string) { + return this.get( { + account_id: accountId, + path: `/users/${userId}`, + ttl: 2 * 60 * 1000 + } ); + } + + async getUserDetailsByUserId(userId: string) { + return this.get( { + path: `/user/${userId}` + } ); + } + + /** + * Get user permissions + * GET + * /aims/v1/:account_id/users/:user_id/permissions + * "https://api.cloudinsight.alertlogic.com/aims/v1/12345678/users/715A4EC0-9833-4D6E-9C03-A537E3F98D23/permissions" + */ + async getUserPermissions(accountId: string, userId: string) { + return this.get( { + account_id: accountId, + path: `/users/${userId}/permissions`, + ttl: 2 * 60 * 1000 + }); + } + + /** + * Get Account Details + * GET + * /aims/v1/:account_id/account + * "https://api.cloudinsight.alertlogic.com/aims/v1/12345678/account" + */ + async getAccountDetails(accountId: string) { + return this.get({ + account_id: accountId, + path: '/account', + ttl: 2 * 60 * 1000 + }); + } + + /** + * @deprecated use getAccountsByRelationship + * List managed accounts + * GET + * /aims/v1/:account_id/accounts/:relationship + * "https://api.cloudinsight.alertlogic.com/aims/v1/12345678/accounts/managed" + */ + async getManagedAccounts(accountId: string, queryParams?):Promise { + return this.getAccountsByRelationship(accountId, 'managed', queryParams ); + } + + /** + * @deprecated use getAccountIdsByRelationship + * List managed account IDs + * GET + * /aims/v1/:account_id/account_ids/:relationship + * "https://api.cloudinsight.alertlogic.com/aims/v1/12345678/account_ids/managed" + */ + async getManagedAccountIds(accountId: string, queryParams?):Promise { + return this.getAccountIdsByRelationship(accountId, 'managed', queryParams ); + } + + /** + * List account IDs, by relationship can be managing, managed and bills_to + * GET + * /aims/v1/:account_id/account_ids/:relationship + * "https://api.cloudinsight.alertlogic.com/aims/v1/12345678/account_ids/managing" + * "https://api.cloudinsight.alertlogic.com/aims/v1/12345678/account_ids/managed" + * "https://api.cloudinsight.alertlogic.com/aims/v1/12345678/account_ids/bills_to" + */ + async getAccountIdsByRelationship(accountId: string, relationship: string, queryParams?):Promise { + return ( await this.get({ + account_id: accountId, + path: `/account_ids/${relationship}`, + params: queryParams, + ttl: 2 * 60 * 1000 + }) ).account_ids as string[]; + } + + /** + * List accounts, by relationship can be managing, managed and bills_to + * GET + * /aims/v1/:account_id/accounts/:relationship + * "https://api.cloudinsight.alertlogic.com/aims/v1/12345678/accounts/managing" + * "https://api.cloudinsight.alertlogic.com/aims/v1/12345678/accounts/managed" + * "https://api.cloudinsight.alertlogic.com/aims/v1/12345678/accounts/bills_to" + */ + async getAccountsByRelationship(accountId: string, relationship: string, queryParams?):Promise { + return ( await this.get({ + account_id: accountId, + path: `/accounts/${relationship}`, + params: queryParams, + ttl: 2 * 60 * 1000 + }) ).accounts as AIMSAccount[]; + } + + /** + * Retrieve a union of user records corresponding to a managed relationship hierarchy between two accounts. + * This is a placeholder for a better implementation based on a relationship topology endpoint from AIMS.0 + * @deprecated use getAccountsIdsByRelationship in conjunction with getUsersFromAccounts + */ + async getUsersFromManagedRelationship( leafAccountId:string, terminalAccountId?:string, failOnError:boolean = true ):Promise { + let users = await this.getUsers( leafAccountId, { include_role_ids: false, include_user_credential: false } ); + try { + let managing = await this.getAccountsByRelationship( leafAccountId, "managing" ); + if ( managing.length > 0 ) { + managing.sort( ( a, b ) => parseInt( b.id, 10 ) - parseInt( a.id, 10 ) ); // this is gross hackery. Kevin did not implement this. Tell no-one of what you've seen! + let parentUsers = await this.getUsersFromManagedRelationship( managing[0].id, terminalAccountId ); + if ( Array.isArray( parentUsers ) ) { + users = users.concat( parentUsers ); + } + } + } catch( e ) { + if ( failOnError ) { + throw e; + } + } + return users; + } + + /** + * Update account MFA requirements + * POST + * /aims/v1/:account_id/account + * -d '{"mfa_required": true}' "https://api.cloudinsight.alertlogic.com/aims/v1/12345678/account" + */ + async requireMFA(accountId: string, mfaRequired: boolean):Promise { + return this.post({ + account_id: accountId, + path: '/account', + data: { mfa_required: mfaRequired } + }); + } + + /** + * Update account session idle expiration + * POST + * This updates a single property of an AIMS account record, affecting how long users of that account + * can be idle before their sessions will be terminated due to inactivity. + */ + async setAccountIdleThreshold( accountId:string, seconds:number|null ) { + return this.post( { + account_id: accountId, + path: '/account', + data: { + idle_session_timeout: seconds + } + } ); + } + + /** + * Authenticate a user's identity + * POST + * /aims/v1/authenticate + * -u username:password "https://api.cloudinsight.alertlogic.com/aims/v1/authenticate" + */ + async authenticate( user:string, pass:string, mfa?:string ): Promise { + return this.adapter.authenticate( user, pass, mfa, true ); + } + + /** + * Authenticate a user's identity with an mfa code and session token + */ + async authenticateWithMFASessionToken(token: string, mfa: string): Promise { + return this.adapter.authenticateWithMFASessionToken(token, mfa, true ); + } + + /** + * Change a user's password + * POST + * /aims/v1/change_password + * -d '{"email": "admin@company.com", "current_password": "hunter2", "new_password": "Fraudulent$Foes"}' "https://api.cloudinsight.alertlogic.com/aims/v1/change_password" + */ + async changePassword(email: string, password: string, newPassword: string) { + return this.post({ + path: '/change_password', + data: { email, current_password: password, new_password: newPassword } + }); + } + + /** + * Obtain Authentication Token Information for a specific access token + */ + public async getTokenInfo( accessToken:string ):Promise { + return this.get( { + service_stack: AlLocation.GlobalAPI, + path: '/token_info', + headers: { + 'X-AIMS-Auth-Token': accessToken + }, + ttl: 10 * 60 * 1000, + cacheKey: AlLocatorService.resolveURL( AlLocation.GlobalAPI, `/aims/v1/token_info/${accessToken}` ) // custom cacheKey to avoid cache pollution + } ); + } + + /** + * Initiate the password reset process for a user + * POST + * /aims/v1/reset_password + * -d '{"email": "admin@company.com", "return_to": "https://console.alertlogic.net"}' "https://api.cloudinsight.alertlogic.com/aims/v1/reset_password" + */ + async initiateReset(email: string, returnTo: string) { + return this.post({ + path: '/reset_password', + data: { email, return_to: returnTo }, + }); + } + + /** + * Reset a user's password using a token + * PUT + * /aims/v1/reset_password/:token + * -d '{"password": "hunter2"}' "https://api.cloudinsight.alertlogic.com/aims/v1/reset_password/69EtspCz3c4" + */ + async resetWithToken(token: string, password: string) { + return this.put({ + path: `/reset_password/${token}`, + data: { password }, + }); + } + + /** + * Create a role + * POST + * /aims/v1/:account_id/roles + * -d '{"name": "Super Mega Power User", "permissions": {"*:own:*:*": "allowed", "aims:own:grant:*":"allowed"}}' "https://api.cloudinsight.alertlogic.com/aims/v1/12345678/roles" + */ + async createRole(accountId: string, name: string, permissions) { + return this.post({ + account_id: accountId, + path: '/roles', + data: { name, permissions } + }); + } + + /** + * Delete a role + * DELETE + * /aims/v1/:account_id/roles/:role_id + * "https://api.cloudinsight.alertlogic.com/aims/v1/12345678/roles/C7C5BE57-F199-4F14-BCB5-43E31CA02842" + */ + async deleteRole(accountId: string, roleId: string) { + return this.delete({ + account_id: accountId, + path: `/roles/${roleId}` + } ); + } + + /** + * Grant a role + * PUT + * /aims/v1/:account_id/users/:user_id/roles/:role_id + * "https://api.product.dev.alertlogic.com/aims/v1/12345678/users/715A4EC0-9833-4D6E-9C03-A537E3F98D23/roles/2A33175D-86EF-44B5-AA39-C9549F6306DF" + */ + async grantRole(accountId:string, userId:string, roleId:string) { + return this.put({ + account_id: accountId, + path: `/users/${userId}/roles/${roleId}` + }); + } + + /** + * Revoke a role + * DELETE + * /aims/v1/:account_id/users/:user_id/roles/:role_id + * "https://api.product.dev.alertlogic.com/aims/v1/12345678/users/715A4EC0-9833-4D6E-9C03-A537E3F98D23/roles/2A33175D-86EF-44B5-AA39-C9549F6306DF" + */ + async revokeRole(accountId:string, userId:string, roleId:string) { + return this.delete({ + account_id: accountId, + path: `/users/${userId}/roles/${roleId}` + }); + } + + /** + * Get global role, a role that is shared among accounts. + * GET + * /aims/v1/roles/:role_id + * "https://api.cloudinsight.alertlogic.com/aims/v1/roles/2A33175D-86EF-44B5-AA39-C9549F6306DF" + */ + async getGlobalRole(roleId: string) { + return this.get({ + path: `/roles/${roleId}` + }); + } + + /** + * Get role + * GET + * /aims/v1/:account_id/roles/:role_id + * "https://api.cloudinsight.alertlogic.com/aims/v1/12345678/roles/2A33175D-86EF-44B5-AA39-C9549F6306DF" + */ + async getAccountRole(accountId: string, roleId: string) { + return this.get({ + account_id: accountId, + path: `/roles/${roleId}` + }); + } + + /** + * Get assigned roles + * GET + * /aims/v1/:account_id/users/:user_id/roles + * "https://api.cloudinsight.alertlogic.com/aims/v1/12345678/users/715A4EC0-9833-4D6E-9C03-A537E3F98D23/roles" + */ + async getAssignedRoles( accountId:string, userId:string ):Promise { + return ( await this.get({ + account_id: accountId, + path: `/users/${userId}/roles` + }) ).roles as AIMSRole[]; + } + + /** + * List global roles, roles that are shared among all accounts. + * GET + * /aims/v1/roles + * "https://api.cloudinsight.alertlogic.com/aims/v1/roles" + */ + async getGlobalRoles():Promise { + return ( await this.get({ + path: '/roles' + }) ).roles as AIMSRole[]; + } + + /** + * List roles for an account. Global roles are included in the list. + * GET + * /aims/v1/:account_id/roles + * "https://api.cloudinsight.alertlogic.com/aims/v1/12345678/roles" + */ + async getAccountRoles(accountId: string):Promise { + return ( await this.get({ + account_id: accountId, + path: '/roles' + }) ).roles as AIMSRole[]; + } + + /** + * Update Role Name and Permissions + * POST + * /aims/v1/:account_id/roles/:role_id + * -d '{"name": "Mega Power User", "permissions": {"*:own:*:*": "allowed", "aims:own:grant:*":"allowed"}}' "https://api.cloudinsight.alertlogic.com/aims/v1/12345678/roles/2A33175D-86EF-44B5-AA39-C9549F6306DF" + */ + async updateRole(accountId: string, name: string, permissions) { + return this.post({ + account_id: accountId, + path: '/roles', + data: { name, permissions } + }); + } + + /** + * Update Role Name + * POST + * /aims/v1/:account_id/roles/:role_id + * -d '{"name": "Mega Power User"}' "https://api.cloudinsight.alertlogic.com/aims/v1/12345678/roles/2A33175D-86EF-44B5-AA39-C9549F6306DF" + */ + async updateRoleName(accountId: string, name: string) { + return this.post({ + account_id: accountId, + path: '/roles', + data: { name } + }); + } + + /** + * Update Role Permissions + * POST + * /aims/v1/:account_id/roles/:role_id + * -d '{"permissions": {"*:own:*:*": "allowed", "aims:own:grant:*":"allowed"}}' "https://api.cloudinsight.alertlogic.com/aims/v1/12345678/roles/2A33175D-86EF-44B5-AA39-C9549F6306DF" + */ + async updateRolePermissions(accountId: string, permissions:any ) { + return this.post({ + account_id: accountId, + path: '/roles', + data: { permissions } + }); + } + + /** + * Enroll an MFA device for a user + * POST + * /aims/v1/user/mfa/enroll + * "https://api.cloudinsight.alertlogic.com/aims/v1/user/mfa/enroll" \ + * -H "Content-Type: application/json" \ + * -H "X-Aims-Session-Token: a3e12fwafge1g9" \ + * -d @- << EOF + * { + * "mfa_uri": "otpauth://totp/Alert%20Logic:admin@company.com?secret=GFZSA5CINFJSA4ZTNNZDG5BAKM2EMMZ7&issuer=Alert%20Logic&algorithm=SHA1" + * "mfa_codes": ["123456", "456789"] + * } + * EOF + */ + async enrollMFA( uri: string, sessionToken:string, codes:string[] ) { + return this.post({ + path: '/user/mfa/enroll', + data: { mfa_uri: uri, mfa_codes: codes }, + headers: { + 'X-AIMS-Session-Token': sessionToken + } + }); + } + + /** + * Enroll an MFA device for a user (when no AIMS token available). + * POST + * /aims/v1/user/mfa/enroll + * "https://api.cloudinsight.alertlogic.com/aims/v1/user/mfa/enroll" \ + * -H "Content-Type: application/json" \ + * -d @- << EOF + * { + * "mfa_uri": "otpauth://totp/Alert%20Logic:admin@company.com?secret=GFZSA5CINFJSA4ZTNNZDG5BAKM2EMMZ7&issuer=Alert%20Logic&algorithm=SHA1" + * "mfa_codes": ["123456", "456789"], + * "password" : "password", + * "email" : "user@email.com" + * } + * EOF + */ + async enrollMFAWithoutAIMSToken(uri:AIMSEnrollURI, codes:string[], email:string, password:string ) { + return this.post({ + path: '/user/mfa/enroll', + data: { + mfa_uri: uri.toString(), + email: email, + password: password, + mfa_codes: codes + } + }); + } + + /** + * Remove a user's MFA device + * DELETE + * /aims/v1/user/mfa/:email + * "https://api.cloudinsight.alertlogic.com/aims/v1/user/mfa/admin@company.com" + */ + async deleteMFA(email: string) { + return this.delete({ path: `/user/mfa/${email}`}); + } + + async getUserDetails(accountId: string, userId: string, queryParams?: {include_role_ids?: boolean, include_user_credential?: boolean}) { + return this.get({ + account_id: accountId, + path: `/users/${userId}`, + params: queryParams, + }); + } + + /** + * List Users + * GET + * /aims/v1/:account_id/users + * "https://api.cloudinsight.alertlogic.com/aims/v1/12345678/users" + */ + async getUsers( accountId: string, queryParams?: {include_role_ids?: boolean, include_user_credential?: boolean} ):Promise { + return ( await this.get({ + account_id: accountId, + path: '/users', + params: queryParams, + }) ).users as AIMSUser[]; + } + + /** + * Create Access Key + * POST + * /aims/v1/:account_id/users/:user_id/access_keys + * "https://api.cloudinsight.alertlogic.com/aims/v1/12345678/users/715A4EC0-9833-4D6E-9C03-A537E3F98D23/access_keys" + * -d '{"label": "api access"}' + */ + async createAccessKey(accountId: string, userId: string, label: string) { + return this.post({ + account_id: accountId, + path: `/users/${userId}/access_keys`, + data: { label } + }); + } + + /** + * Update Access Key + * POST + * /aims/v1/access_keys/:access_key_id + * "https://api.cloudinsight.alertlogic.com/aims/v1/access_keys/61fb235617960503" + * -d '{"label": "api access"}' + */ + async updateAccessKey(accessKeyId: string, label: string) { + return this.post({ + path: `/access_keys/${accessKeyId}`, + data: { label } + }); + } + + /** + * Get Access Key + * GET + * /aims/v1/access_keys/:access_key_id + * "https://api.cloudinsight.alertlogic.com/aims/v1/access_keys/61fb235617960503" + */ + async getAccessKey(accessKeyId: string) { + return this.get( { + path: `/access_keys/${accessKeyId}` + } ); + } + + /** + * List Access Keys + * GET + * /aims/v1/:account_id/users/:user_id/access_keys?out=:out + * https://api.cloudinsight.alertlogic.com/aims/v1/12345678/users/715A4EC0-9833-4D6E-9C03-A537E3F98D23/access_keys?out=full" + */ + async getAccessKeys(accountId: string, userId: string, ttl: number = 60000) { + return ( await this.get({ + account_id: accountId, + ttl: ttl, + path: `/users/${userId}/access_keys?out=full` + } ) ).access_keys as AIMSAccessKey[]; + } + + /** + * Delete Access Key + * DELETE + * /aims/v1/:account_id/users/:user_id/access_keys/:access_key_id + * "https://api.cloudinsight.alertlogic.com/aims/v1/12345678/users/715A4EC0-9833-4D6E-9C03-A537E3F98D23/access_keys/61FB235617960503" + */ + async deleteAccessKey(accountId: string, userId: string, accessKeyId: string) { + return this.delete({ + account_id: accountId, + path: `/users/${userId}/access_keys/${accessKeyId}` + }); + } + + /** + * Retrieve linked organization + */ + async getAccountOrganization( accountId:string ):Promise { + return this.get( { + account_id: accountId, + path: '/organization' + } ); + } + + /** + * This endpoint render's an accounts related accounts topologically by adding a :relationship field to the account object, + * which contains an array of accounts that are directly related to it. + * GET + * /aims/v1/:account_id/accounts/:relationship/topology + * https://console.product.dev.alertlogic.com/api/aims/index.html#api-AIMS_Account_Resources-AccountRelationshipExists + * @param accountId {string} + * @param relationship {'managed' | 'managing'} + * @param queryParms {Object} + */ + async getAccountRelationshipTopology(accountId: string, relationship: 'managed' | 'managing', queryParams?): Promise { + return ( await this.get({ + account_id: accountId, + path: `/accounts/${relationship}/topology`, + params: queryParams + } ) ).topology as AIMSTopology; + } + + /** + * Returns the ids of the accounts to which an account is related. + * The related accounts that are returned depend oonf the :relationship param. + * If using a "managed" relationship, this returns all accounts that the current account manages. + * If using a "managing" relationship, this returns all accounts that managing the current account. + * @param accountId {string} + * @param relationship {'managed' | 'managing'} + * @param addCurrentId {boolean} [addCurrentId=true] true if wants add the current id to the return + */ + async getAccountsIdsByRelationship(accountId: string, relationship: 'managed' | 'managing', addCurrentId: boolean = true): Promise { + const topology = await this.getAccountRelationshipTopology(accountId, relationship); + + function getIds(accounts: AIMSTopology[]): string[] { + return accounts.flatMap(a => [a.id, ...getIds(Array.isArray(a[relationship]) ? a[relationship] : [])]); + } + const first = addCurrentId ? [accountId] : []; + return [...first, ...getIds(topology[relationship])]; + } + + /** + * Returns all users associated with a list of accounts + * @param accountList {string[]} + */ + async getUsersFromAccounts(accountList: string[]): Promise { + return (await Promise.all( + accountList.map(account => this.getUsers(account, { include_role_ids: false, include_user_credential: false })) + )).flat(); + } + + public hasSchema( schemaId:string ) { + return schemaId in aimsTypeSchematics; + } + + public async getSchema( schemaId:string ) { + return aimsTypeSchematics[schemaId]; + } + + public getProviders() { + return [ this.adapter ]; + } +} diff --git a/src/client/aims/index.ts b/src/client/aims/index.ts new file mode 100644 index 00000000..cbba2960 --- /dev/null +++ b/src/client/aims/index.ts @@ -0,0 +1,2 @@ +export * from "./aims.service-client"; +export * from "./types/index"; diff --git a/src/aims-client/types/index.ts b/src/client/aims/types/index.ts similarity index 100% rename from src/aims-client/types/index.ts rename to src/client/aims/types/index.ts diff --git a/src/aims-client/types/types.ts b/src/client/aims/types/types.ts similarity index 97% rename from src/aims-client/types/types.ts rename to src/client/aims/types/types.ts index 1ed39b95..c2ed4719 100644 --- a/src/aims-client/types/types.ts +++ b/src/client/aims/types/types.ts @@ -1,4 +1,4 @@ -import { AlChangeStamp } from '../../types/index'; +import { AlChangeStamp } from '../../../types/index'; export interface AIMSAuthentication { user: AIMSUser; @@ -49,6 +49,7 @@ export interface AIMSAuthenticationTokenInfo extends AIMSAuthentication { } export interface AIMSUserDetails { + id?:string; name?:string; password?:string; email?:string; diff --git a/src/client/al-api-client.ts b/src/client/al-xhr-adapter.ts similarity index 93% rename from src/client/al-api-client.ts rename to src/client/al-xhr-adapter.ts index c2abfbef..cd501178 100644 --- a/src/client/al-api-client.ts +++ b/src/client/al-xhr-adapter.ts @@ -1,7 +1,7 @@ /** * Alert Logic axios extension - an API Client with automatic service discovery, local caching, and retry functionality baked in. * - * An instance of the client can be constructed manually, but in general you should just use the global instance `AlDefaultClient`. + * An instance of the client can be constructed manually, but in general you should just use the global instance `AlRootClient`. * * Most use cases can be handled by using one of the client's convenience methods, which includes support for local caching and retries: * @@ -17,8 +17,8 @@ * Alternatively, a request can be normalized and dispatched without caching or retry logic using this method: * * ``` - * let normalizedRequest = AlDefaultClient.normalizeRequest( config ); - * let response = await AlDefaultClient.doRequest( method, normalizedRequest ); + * let normalizedRequest = AlRootClient.normalizeRequest( config ); + * let response = await AlRootClient.doRequest( method, normalizedRequest ); * ``` */ import axios, { @@ -28,7 +28,7 @@ import axios, { Method, } from 'axios'; import * as base64JS from 'base64-js'; -import { AlDataValidationError, AlGatewayTimeoutError } from '../common/errors'; +import { AlErrorHandler, AlDataValidationError, AlGatewayTimeoutError } from '../errors'; import { AlLocation, AlLocationContext, @@ -53,9 +53,12 @@ import { APIRequestParams, AlInterceptionRule, AlInterceptionRules, + AlServiceDescriptor, + AlBaseServiceClient, + serviceClientBlueprints } from './types'; import { AlClientBeforeRequestEvent, AlClientAPIErrorEvent } from './events'; -import { AIMSSessionDescriptor } from '../aims-client/types'; +import { AIMSSessionDescriptor } from './aims/types'; import { AlRuntimeConfiguration, ConfigOption } from '../configuration'; import { commonTypeSchematics } from './common.schematics'; @@ -73,7 +76,7 @@ type AlEndpointsDictionary = { } }; -export class AlApiClient implements AlValidationSchemaProvider +export class AlXHRAdapter implements AlValidationSchemaProvider { /** * The following list of services are the ones whose endpoints will be resolved by default. Added globally/commonly used services here for optimized API performance. @@ -82,8 +85,6 @@ export class AlApiClient implements AlValidationSchemaProvider /** * The following list of services are the ones whose endpoints will need to be determined for the current context active residency location. */ - protected static resolveByResidencyServiceList = [ "iris", "kalm", "ticketmaster", "tacoma", "responder", "responder-async", "cargo" ]; - protected static defaultServiceParams: APIRequestParams = { service_stack: AlLocation.InsightAPI, // May also be AlLocation.GlobalAPI, AlLocation.EndpointsAPI, or ALLocation.LegacyUI residency: 'default', // "us" or "emea" or "default" @@ -99,11 +100,13 @@ export class AlApiClient implements AlValidationSchemaProvider public mockMode:boolean = false; // If true, requests will be normalized but not actually dispatched. public defaultAccountId:string = null; // If specified, uses *this* account ID to resolve endpoints if no other account ID is explicitly specified + private resolveByResidencyServiceList = [ "iris", "kalm", "ticketmaster", "tacoma", "responder", "responder-async", "cargo" ]; private storage = AlCabinet.local( 'apiclient.cache' ); private instance:AxiosInstance = null; private lastError:AxiosResponse = null; private endpointsGuard = new AlMutex(); private endpointCache:AlEndpointsDictionary = {}; + private clientDictionary:{[clientName:string]:AlBaseServiceClient} = {}; /* List of stacks (service_stack property in APIRequestParams) that should have endpoints resolution enabled by default */ private endpointsStackWhitelist = [ @@ -124,18 +127,18 @@ export class AlApiClient implements AlValidationSchemaProvider constructor() { // temp to debug ie11 - this.globalServiceParams = this.merge( {}, AlApiClient.defaultServiceParams ); + this.globalServiceParams = this.merge( {}, AlXHRAdapter.defaultServiceParams ); } /** * Resets internal state back to its factory defaults. */ - public reset():AlApiClient { + public reset():AlXHRAdapter { this.endpointCache = {}; this.instance = null; this.executionRequestLog = []; this.storage.destroy(); - this.globalServiceParams = this.merge( {}, AlApiClient.defaultServiceParams ); + this.globalServiceParams = this.merge( {}, AlXHRAdapter.defaultServiceParams ); return this; } @@ -173,7 +176,7 @@ export class AlApiClient implements AlValidationSchemaProvider * This allows the host to set global parameters that will be used for every request, either for Axios or the @al/client service layer. * Most notably, setting `noEndpointsResolution` to true will suppress endpoints resolution for all requests, and cause default endpoint values to be used. */ - public setGlobalParameters( parameters:APIRequestParams ):AlApiClient { + public setGlobalParameters( parameters:APIRequestParams ):AlXHRAdapter { this.globalServiceParams = this.merge( this.globalServiceParams, parameters ); return this; } @@ -263,7 +266,7 @@ export class AlApiClient implements AlValidationSchemaProvider * Alias for GET utility method */ public async fetch(config: APIRequestParams):Promise { - console.warn("Deprecation warning: do not use AlApiClient.fetch; use `get` instead." ); + console.warn("Deprecation warning: do not use AlXHRAdapter.fetch; use `get` instead." ); return this.get( config ); } @@ -329,7 +332,7 @@ export class AlApiClient implements AlValidationSchemaProvider * Alias for PUT utility method */ public async set( config:APIRequestParams ) :Promise{ - console.warn("Deprecation warning: do not use AlApiClient.set; use `put` instead." ); + console.warn("Deprecation warning: do not use AlXHRAdapter.set; use `put` instead." ); return this.put( config ); } @@ -392,9 +395,15 @@ export class AlApiClient implements AlValidationSchemaProvider if (this.collectRequestLog) { const completed = Date.now(); const duration = completed - start; - logItem.responseCode = e.status; logItem.durationMs = duration; - logItem.errorMessage = e["message"]; + if ( this.isResponse( e ) ) { + logItem.responseCode = e.status; + logItem.errorMessage = e["message"]; + } else { + logItem.responseCode = 0; + logItem.durationMs = duration; + logItem.errorMessage = AlErrorHandler.normalize( e ).message; + } } this.log(`APIClient::XHR FAILED ${JSON.stringify(logItem)}`); throw e; @@ -735,12 +744,12 @@ export class AlApiClient implements AlValidationSchemaProvider host = `https://${host}`; // ensuring domains are prefixed with protocol } setJsonPath( this.endpointCache, - [ context.environment, accountId, serviceName, AlApiClient.defaultResidency ], + [ context.environment, accountId, serviceName, AlXHRAdapter.defaultResidency ], host ); } ); return this.endpointCache; } catch ( e ) { - this.fallbackResolveEndpoints( accountId, serviceList, AlApiClient.defaultResidency ); + this.fallbackResolveEndpoints( accountId, serviceList, AlXHRAdapter.defaultResidency ); } } @@ -780,7 +789,7 @@ export class AlApiClient implements AlValidationSchemaProvider public lookupDefaultServiceEndpoint(accountId: string, serviceName: string) { const context = AlLocatorService.getContext(); return getJsonPath( this.endpointCache, - [ context.environment, accountId, serviceName, AlApiClient.defaultResidency ], + [ context.environment, accountId, serviceName, AlXHRAdapter.defaultResidency ], null ); } @@ -796,6 +805,33 @@ export class AlApiClient implements AlValidationSchemaProvider } } + public getClient( clientType:{ new():ServiceClass } ):ServiceClass { + if ( ! ( 'clientId' in clientType.prototype ) || ! ( 'definition' in clientType.prototype ) ) { + throw new Error( `Could not find client!` ); + } + const clientId = clientType.prototype.clientId; + if ( ! ( clientId in serviceClientBlueprints ) ) { + throw new Error( `No registered client for service '${clientId}'` ); + } + if ( clientId in this.clientDictionary ) { + return this.clientDictionary[clientId] as ServiceClass; + } + const blueprint = serviceClientBlueprints[clientId]; + let instance = new clientType; + instance.adapter = this; + instance.defaultConfig.service_stack = blueprint.definition.service_stack; + instance.defaultConfig.service_name = blueprint.definition.service_name; + instance.defaultConfig.version = blueprint.definition.version; + if ( blueprint.definition.residencyAware ) { + if ( ! this.resolveByResidencyServiceList.includes( blueprint.definition.service_name ) ) { + this.resolveByResidencyServiceList.push( blueprint.definition.service_name ); + } + } + this.clientDictionary[clientId] = instance; + console.log("Constructed %s", clientId, instance ); + return instance; + } + protected getGestaltAuthenticationURL():string { let residency = 'US'; let environment = AlLocatorService.getCurrentEnvironment(); @@ -859,7 +895,7 @@ export class AlApiClient implements AlValidationSchemaProvider const environment = AlLocatorService.getCurrentEnvironment(); const accountId = requestParams.context_account_id || requestParams.account_id || this.defaultAccountId || "0"; const serviceEndpointId = requestParams.target_endpoint || requestParams.service_name; - const residencyAware = AlApiClient.resolveByResidencyServiceList.includes( serviceEndpointId ); + const residencyAware = this.resolveByResidencyServiceList.includes( serviceEndpointId ); const residency = residencyAware ? AlLocatorService.getCurrentResidency() : "default"; let baseURL = getJsonPath( this.endpointCache, @@ -869,7 +905,7 @@ export class AlApiClient implements AlValidationSchemaProvider return baseURL; } - let serviceList = residencyAware ? AlApiClient.resolveByResidencyServiceList : AlApiClient.defaultServiceList; + let serviceList = residencyAware ? this.resolveByResidencyServiceList : AlXHRAdapter.defaultServiceList; if ( ! serviceList.includes(serviceEndpointId)) { serviceList.push(serviceEndpointId); } @@ -1176,4 +1212,5 @@ export class AlApiClient implements AlValidationSchemaProvider } /* tslint:disable:variable-name */ -export const AlDefaultClient = AlGlobalizer.instantiate( 'AlDefaultClient', () => new AlApiClient() ); +export const AlRootClient = AlGlobalizer.instantiate( 'alsRoot', () => new AlXHRAdapter() ); +export const AlDefaultClient = AlRootClient; // @deprecated diff --git a/src/client/index.ts b/src/client/index.ts index 6789c84a..fae67c81 100644 --- a/src/client/index.ts +++ b/src/client/index.ts @@ -1,7 +1,10 @@ export * from './types'; export * from './events'; export { - AlApiClient, - AlDefaultClient, - AlDefaultClient as ALClient /* @deprecated */ -} from './al-api-client'; + AlXHRAdapter, + AlRootClient, + AlRootClient as AlDefaultClient, /* @deprecated */ + AlXHRAdapter as ALClient /* also @deprecated */ +} from './al-xhr-adapter'; +export * from './aims'; +export * from './subscriptions'; diff --git a/src/subscriptions-client/README.md b/src/client/subscriptions/README.md similarity index 100% rename from src/subscriptions-client/README.md rename to src/client/subscriptions/README.md diff --git a/src/client/subscriptions/index.ts b/src/client/subscriptions/index.ts new file mode 100644 index 00000000..a6ccd9aa --- /dev/null +++ b/src/client/subscriptions/index.ts @@ -0,0 +1,2 @@ +export * from "./subscriptions.service-client"; +export * from "./types/index"; diff --git a/src/subscriptions-client/subscriptions-client.ts b/src/client/subscriptions/subscriptions.service-client.ts similarity index 73% rename from src/subscriptions-client/subscriptions-client.ts rename to src/client/subscriptions/subscriptions.service-client.ts index 13742485..6f5eced8 100644 --- a/src/subscriptions-client/subscriptions-client.ts +++ b/src/client/subscriptions/subscriptions.service-client.ts @@ -1,18 +1,19 @@ -import { - AlApiClient, - AlDefaultClient, -} from "../client"; -import { AlLocation } from "../common/navigation"; +import { ServiceClient, AlBaseServiceClient } from "../types"; +import { AlLocation } from "../../common/navigation"; import { AlEntitlementCollection } from './types'; +import { AlRootClient } from '../al-xhr-adapter'; -export class AlSubscriptionsClient { +@ServiceClient( { + service_name: "subscriptions", + service_stack: AlLocation.GlobalAPI, + version: 1 +} ) +export class AlsSubscriptions extends AlBaseServiceClient { - private alClient; private internalUser:boolean = false; - private serviceVersion:string = "v1"; - constructor( client:AlApiClient = null ) { - this.alClient = client || AlDefaultClient; + constructor() { + super(); } /** @@ -32,16 +33,12 @@ export class AlSubscriptionsClient { * "https://api.global-integration.product.dev.alertlogic.com/subscriptions/v1/01000001/entitlements" */ async getRawEntitlements(accountId, queryParams?) { - const entitlements = await this.alClient.get({ - service_stack: AlLocation.GlobalAPI, - service_name: 'subscriptions', - version: this.serviceVersion, + return this.get({ account_id: accountId, path: '/entitlements', params: queryParams, ttl: 5 * 60 * 1000 /* 5 minute in-memory caching */ }); - return entitlements; } /** @@ -54,14 +51,10 @@ export class AlSubscriptionsClient { * "https://api.global-integration.product.dev.alertlogic.com/subscriptions/v1/account_ids/entitlement/log_manager" */ async getAccountsByEntitlement(accountId, productFamily) { - const accounts = await this.alClient.get({ - service_stack: AlLocation.GlobalAPI, - service_name: 'subscriptions', - version: this.serviceVersion, + return this.get({ account_id: accountId, path: `/entitlements/${productFamily}` }); - return accounts; } /** @@ -74,14 +67,12 @@ export class AlSubscriptionsClient { * "status":"subscribe-success"}' */ async createAWSSubscription(accountId, subscription) { - const added = await this.alClient.post({ - service_name: 'subscriptions', - version: this.serviceVersion, + return this.post( { + service_stack: AlLocation.InsightAPI, account_id: accountId, path: '/subscription/aws', data: subscription, }); - return added; } /** @@ -105,14 +96,11 @@ export class AlSubscriptionsClient { active: true, type: 'manual', }; - const added = await this.alClient.post({ - service_name: 'subscriptions', - version: this.serviceVersion, + return this.post( { account_id: accountId, path: '/subscription', data: subscription, }); - return added; } /** @@ -122,13 +110,10 @@ export class AlSubscriptionsClient { * "https://api.global-integration.product.dev.alertlogic.com/subscriptions/v1/01000001/subscription/sync/standard" */ async createStandardSubscription(accountId) { - const added = await this.alClient.post({ - service_name: 'subscriptions', - version: this.serviceVersion, + return this.post({ account_id: accountId, path: '/subscription/sync/standard', }); - return added; } /** @@ -138,13 +123,10 @@ export class AlSubscriptionsClient { * "https://api.global-integration.product.dev.alertlogic.com/subscriptions/v1/01000001/subscription/AAB2A94F-2A2F-474E-BEFD-C387E595F153" */ async getSubscription(accountId, subscriptionId) { - const subscription = await this.alClient.get({ - service_name: 'subscriptions', - version: this.serviceVersion, + return this.get( { account_id: accountId, path: `/subscription/${subscriptionId}`, }); - return subscription; } /** @@ -154,13 +136,10 @@ export class AlSubscriptionsClient { * "https://api.global-integration.product.dev.alertlogic.com/subscriptions/v1/01000001/subscriptions" */ async getSubscriptions(accountId) { - const subscriptions = await this.alClient.get({ - service_name: 'subscriptions', - version: this.serviceVersion, + return this.get( { account_id: accountId, path: '/subscriptions', }); - return subscriptions; } /** @@ -172,20 +151,14 @@ export class AlSubscriptionsClient { * "status":"unsubscribe-success"}' */ async updateAWSSubscription(accountId, subscription) { - const updated = await this.alClient.put({ - service_name: 'subscriptions', - version: this.serviceVersion, + return this.put( { account_id: accountId, path: '/subscription/aws', data: subscription, }); - return updated; } public setInternalUser( internal:boolean ) { this.internalUser = internal; } } - -/* tslint:disable:variable-name */ -export const SubscriptionsClient = new AlSubscriptionsClient(); diff --git a/src/subscriptions-client/types/al-subscription.types.ts b/src/client/subscriptions/types/al-subscription.types.ts similarity index 100% rename from src/subscriptions-client/types/al-subscription.types.ts rename to src/client/subscriptions/types/al-subscription.types.ts diff --git a/src/subscriptions-client/types/index.ts b/src/client/subscriptions/types/index.ts similarity index 100% rename from src/subscriptions-client/types/index.ts rename to src/client/subscriptions/types/index.ts diff --git a/src/client/types/al-base.service-client.ts b/src/client/types/al-base.service-client.ts new file mode 100644 index 00000000..cc6d31f7 --- /dev/null +++ b/src/client/types/al-base.service-client.ts @@ -0,0 +1,47 @@ +import { AxiosResponse } from 'axios'; +import { APIRequestParams } from './common.types'; +import { AlXHRAdapter } from '../al-xhr-adapter'; + +export class AlBaseServiceClient { + public defaultConfig:APIRequestParams = {}; + public adapter!:AlXHRAdapter; + + constructor() { + } + + public async get( config:APIRequestParams):Promise { + return this.adapter.get( Object.assign( {}, this.defaultConfig, config ) ); + } + + public async rawGet( config:APIRequestParams ):Promise> { + return this.adapter.rawGet( Object.assign( {}, this.defaultConfig, config ) ); + } + + public async post( config:APIRequestParams ):Promise { + return this.adapter.post( Object.assign( {}, this.defaultConfig, config ) ); + } + + public async rawPost( config:APIRequestParams ):Promise> { + return this.adapter.rawPost( Object.assign( {}, this.defaultConfig, config ) ); + } + + public async put( config:APIRequestParams ):Promise { + return this.adapter.put( Object.assign( {}, this.defaultConfig, config ) ); + } + + public async rawPut( config:APIRequestParams ):Promise> { + return this.adapter.rawPut( Object.assign( {}, this.defaultConfig, config ) ); + } + + public async delete( config:APIRequestParams ):Promise { + return this.adapter.delete( Object.assign( {}, this.defaultConfig, config ) ); + } + + public async rawDelete( config:APIRequestParams ):Promise> { + return this.adapter.rawDelete( Object.assign( {}, this.defaultConfig, config ) ); + } + + public async request( config:APIRequestParams ):Promise> { + return this.adapter.executeRequest( Object.assign( {}, this.defaultConfig, config ) ); + } +} diff --git a/src/client/types/api-definition.types.ts b/src/client/types/api-definition.types.ts index d33c4a0a..405d11fd 100644 --- a/src/client/types/api-definition.types.ts +++ b/src/client/types/api-definition.types.ts @@ -1,6 +1,6 @@ /** * Author: Kevin - * Copyright 2021 Alert Logic, Inc. + * Copyright 2022 Alert Logic, Inc. */ /** @@ -10,19 +10,21 @@ * and allows generic methods to be defined as data instead of as a literal method. */ +export interface AlServiceDescriptor { + service_stack?:string; + service_name?:string; + version?:string|number; + residencyAware?:boolean; +} + +export const serviceClientBlueprints:{[clientId:string]:{ctor:Function, definition: AlServiceDescriptor}} = {}; + /* tslint:disable:function-name */ -export function AlAPIClientDef( apiDefinition: { - stack:string, - name:string, - version:string|number, - methods:{ - methodName:string, - relativePath:string, - parameters?: string[] - }[] -} ) { +export function ServiceClient( definition: AlServiceDescriptor ) { return function( ctor:Function ) { - ctor.prototype.apiDefinition = apiDefinition; + ctor.prototype.clientId = definition.service_name; + ctor.prototype.definition = definition; + serviceClientBlueprints[definition.service_name] = { ctor, definition }; }; } diff --git a/src/client/types/index.ts b/src/client/types/index.ts index 30513c49..7a4afd4c 100644 --- a/src/client/types/index.ts +++ b/src/client/types/index.ts @@ -1,2 +1,3 @@ export * from './common.types'; export * from './api-definition.types'; +export * from './al-base.service-client'; diff --git a/src/common/cardstack/al-cardstack-view.ts b/src/common/cardstack/al-cardstack-view.ts index 0c30dd24..bb279b82 100644 --- a/src/common/cardstack/al-cardstack-view.ts +++ b/src/common/cardstack/al-cardstack-view.ts @@ -8,6 +8,7 @@ import { AlCardstackActiveFilter } from './types'; import { AlStopwatch } from '../utility/al-stopwatch'; +import { AlErrorHandler } from '../../errors'; /** * Manages a cardstack view state @@ -117,7 +118,7 @@ export abstract class AlCardstackView< EntityType=any, } } catch( error ) { console.error("A fatal error prevented this view from starting!", error ); - this.error = error; + this.error = error as Error; this.loading = false; } } @@ -167,7 +168,7 @@ export abstract class AlCardstackView< EntityType=any, } catch( e ) { console.error("A fatal error prevented this view from continuing!", e ); this.loading = false; - this.error = e; + this.error = e as Error; } } @@ -681,8 +682,7 @@ export abstract class AlCardstackView< EntityType=any, } ); } catch( e ) { - throw new Error(`Failed to normalize characteristics object: ${e.message}` ); - + AlErrorHandler.log( e, `Failed to normalize characteristics object` ); } } diff --git a/src/common/errors/al-error.types.ts.backup b/src/common/errors/al-error.types.ts.backup deleted file mode 100644 index efd1688e..00000000 --- a/src/common/errors/al-error.types.ts.backup +++ /dev/null @@ -1,180 +0,0 @@ -/** - * A collection of classed error types. - * Please note that the widespread use of istanbul ignore directives here is because of a known issue with istanbul coverage calculations for ES5 targets: - * see [this issue](https://github.com/gotwarlost/istanbul/issues/690) for reference. - * - * Author: Kevin Nielsen - * Copyright 2019 Alert Logic, Inc. - */ - -import { AxiosResponse } from 'axios'; - -/** - * @public - * - * A base error class used only to provide consistent prototype chaining. - */ -export class AlBaseError extends Error -{ - /* tslint:disable:variable-name */ - __proto__: Error; - - /** - * Optional reference to underlying Error, AxiosResponse, or thing that triggered - * this error. - */ - public origin?:any; - - constructor( message?:string, derivedFrom?:any ) { - const trueProto = new.target.prototype; - super(message); - this.origin = derivedFrom; - - this.__proto__ = trueProto; - } -} - -/** - * @public - * - * This error should be used when an HTTP 5xx response (or other general error) is received - * from an internal API. - */ - -export class AlAPIServerError extends AlBaseError -{ - constructor( message:string, - public serviceName:string, - public statusCode:number, - origin?:AxiosResponse|any ) { - /* istanbul ignore next */ - super( message, origin ); - } -} - -/** - * @public - * - * The AlResponseValidationError is intended to alert of unexpected responses from an internal API. - * These responses need to be identified separately from other errors so that the relevant - * system health checks or communication with an appropriate backend team can be organized in response. - * Please note that this should NOT be used to handler general server-side failures; please see AlAPIServerError - * for that error condition. - * - * @param message - Descriptive error text - * @param errors - Unstructured information about specific response validation issues - */ -export class AlResponseValidationError extends AlBaseError -{ - constructor( message:string, - public invalidResponse:AxiosResponse, - public validationErrors:any[] = [] ) { - /* istanbul ignore next */ - super( message ); - } -} - -/** - * @public - * - * Used to indicate an invalid request to a service or API. - * - * @param message - The description of the error - * @param inputType - Which type of input was malformed (e.g., query parameter, header, data) - * @param inputProperty - Which data element was malformed (e.g., "filter", "X-AIMS-Auth-Token", ".data.accounts.id") - * @param description - Additional descriptive content. - */ -export class AlBadRequestError extends AlBaseError -{ - public httpResponseCode:number = 400; - constructor( message:string, - public inputType?:string, - public inputProperty?:string, - public description?:string ) { - /* istanbul ignore next */ - super( message ); - } -} - -/** - * @public - * - * Used to indicate that the current actor is not authenticated. - * - * @param message - The description of the error - * @param authority - Which authentication authority made the authentication state claim. Typically, this will be AIMS. - */ -export class AlUnauthenticatedRequestError extends AlBaseError -{ - public httpResponseCode:number = 401; - constructor( message: string, - public authority:string ) { - /* istanbul ignore next */ - super( message ); - } -} - -/** - * @public - * - * Used to indicate that the current actor is not authorized to perform a given action. - * - * @param message - A general description of the error or error context. - * @param resource - The resource that the actor is not authorized to access, e.g., "endpoints" or "deployments" - */ -export class AlUnauthorizedRequestError extends AlBaseError -{ - public httpResponseCode:number = 403; - constructor( message: string, - public resource:string ) { - /* istanbul ignore next */ - super( message ); - } -} - -/** - * @public - * - * Used to indicate that the request cannot be completed because the underlying functionality is incomplete or unimplemented. - * - * @param message - A general description of the error or error context. - */ -export class AlUnimplementedMethodError extends AlBaseError -{ - public httpResponseCode:number = 501; - constructor( message:string ) { - /* istanbul ignore next */ - super( message ); - } -} - -/** - * @public - * - * Used to indicate that an upstream service has failed to complete a request in the expected fashion. - */ -export class AlBadGatewayError extends AlBaseError -{ - public httpResponseCode:number = 502; - /* tslint:disable:no-unused-variable */ - constructor( message:string, public upstreamService:string, public requestDescriptor:unknown ) { - /* istanbul ignore next */ - super(message); - } -} - -/** - * @public - * - * Used to indicate that a resource does not exist. - * - * @param message - A general description of the error and error context. - */ -export class AlNotFoundError extends AlBaseError -{ - public httpResponseCode:number = 404; - constructor( message:string ) { - /* istanbul ignore next */ - super( message ); - } -} diff --git a/src/common/index.ts b/src/common/index.ts index 877bb0e2..d7a9c173 100644 --- a/src/common/index.ts +++ b/src/common/index.ts @@ -1,5 +1,4 @@ export * from "./cardstack/index"; -export * from "./errors/index"; export * from "./forms/index"; export * from "./navigation/index"; export * from "./promises/index"; diff --git a/src/common/utility/al-merge-helper.ts b/src/common/utility/al-merge-helper.ts deleted file mode 100644 index 2f408996..00000000 --- a/src/common/utility/al-merge-helper.ts +++ /dev/null @@ -1,79 +0,0 @@ -/** - * A simple utility class for translating data between objects and intermediary representations. - * The most obvious use cases are unpacking a DTO into a class instance, or merging multiple DTOs into a complex model. - * Mostly this class is a structured way of avoiding the endless repetition of "if x.hasOwnProperty( x )". - */ - -export class AlMergeHelper { - - constructor( public source:any, public target:any ) { - } - - /** - * Copies one or more properties from the source into the target. - */ - public copy( ...sourceProperties:string[] ) { - sourceProperties.forEach( sourceProperty => { - if ( sourceProperty in this.source ) { - if ( typeof( this.source[sourceProperty] ) !== 'undefined' ) { - this.target[sourceProperty] = this.source[sourceProperty]; - } - } - } ); - } - - /** - * Copies a property from the source to a different property name in the target. - */ - public rename( sourceProperty:string, targetProperty:string ) { - if ( sourceProperty in this.source ) { - if ( typeof( this.source[sourceProperty] ) !== 'undefined' ) { - this.target[targetProperty] = this.source[sourceProperty]; - } - } - } - - /** - * Copies an array of properties from source to a different property name in the target. - */ - public renameAll( ...properties:[ string, string ][] ) { - properties.forEach( ( [ sourceProperty, targetProperty ] ) => this.rename( sourceProperty, targetProperty ) ); - } - - /** - * Transforms a property from the source into a new property in the target. - */ - public transform( sourceProperty:string, targetProperty:string, transformer:{(input:unknown):any} ) { - if ( sourceProperty in this.source ) { - if ( typeof( this.source[sourceProperty] ) !== 'undefined' ) { - this.target[targetProperty] = transformer( this.source[sourceProperty] ); - } - } - } - - /** - * Executes a callback against a property in the source object. - */ - public with( sourceProperty:string, action:{(value:PropertyType):void}) { - if ( sourceProperty in this.source ) { - if ( typeof( this.source[sourceProperty] ) !== 'undefined' ) { - action( this.source[sourceProperty] ); - } - } - } - - /** - * Creates a child merge helper that targets a child property. - */ - public descend( sourceProperty:string, targetProperty:string|null, action:{(merger:AlMergeHelper):void} ) { - if ( sourceProperty in this.source ) { - if ( typeof( this.source[sourceProperty] ) !== 'undefined' ) { - if ( targetProperty && ! ( targetProperty in this.target ) ) { - this.target[targetProperty] = {}; - } - const target = targetProperty ? this.target[targetProperty] : this.target; - action( new AlMergeHelper( this.source[sourceProperty], target ) ); - } - } - } -} diff --git a/src/common/utility/al-trigger.types.ts b/src/common/utility/al-trigger.types.ts index 11b8f808..35c3dbd1 100644 --- a/src/common/utility/al-trigger.types.ts +++ b/src/common/utility/al-trigger.types.ts @@ -3,6 +3,8 @@ * Copyright 2019 Alert Logic, Inc. */ +import { AlErrorHandler } from '../../errors'; + /** * @public * @@ -183,7 +185,7 @@ export class AlTriggerStream try { subscription.trigger( event ); } catch( e ) { - console.warn(`Trigger callback for event ${event.eventTypeName} threw exception: ${e.message}; ignoring.` ); + AlErrorHandler.log( e, `Trigger callback for event ${event.eventTypeName} threw exception, ignoring` ); } } ); diff --git a/src/common/utility/al-validation.types.ts b/src/common/utility/al-validation.types.ts index 6f8926cd..b4bfc456 100644 --- a/src/common/utility/al-validation.types.ts +++ b/src/common/utility/al-validation.types.ts @@ -1,5 +1,5 @@ import { getJsonPath } from './json-utilities'; -import { AlDataValidationError } from '../errors/al-error.types'; +import { AlDataValidationError } from '../../errors'; import * as tv4 from 'tv4'; /** diff --git a/src/common/utility/error-utilities.ts b/src/common/utility/error-utilities.ts deleted file mode 100644 index 4b53ca8e..00000000 --- a/src/common/utility/error-utilities.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { AlDefaultClient } from '../../client/al-api-client'; -import { AxiosResponse } from 'axios'; -import { AlBaseError } from '../errors'; - -export function normalizeError( error:AxiosResponse|AlBaseError|string|any ):AlBaseError { - if ( AlDefaultClient.isResponse( error ) ) { - return new AlBaseError( error.statusText ); - } else if ( error instanceof AlBaseError ) { - return error; - } else if ( typeof( error ) === 'string' ) { - return new AlBaseError( error ); - } else { - return new AlBaseError( "An internal error has occurred." ); - } -} diff --git a/src/common/utility/index.ts b/src/common/utility/index.ts index 76a8e720..f8c8550b 100644 --- a/src/common/utility/index.ts +++ b/src/common/utility/index.ts @@ -5,7 +5,6 @@ export * from "./al-trigger.types"; export * from './al-validation.types'; export * from "./is-promise-like"; export * from "./json-utilities"; -export * from './al-merge-helper'; export * from './timezone-utilities'; export * from './al-mutex'; export * from './al-frame-message-stream'; diff --git a/src/error-handler/al-error-handler.ts b/src/errors/al-error-handler.ts similarity index 81% rename from src/error-handler/al-error-handler.ts rename to src/errors/al-error-handler.ts index 8177d591..ee6af837 100644 --- a/src/error-handler/al-error-handler.ts +++ b/src/errors/al-error-handler.ts @@ -1,6 +1,5 @@ import { AxiosResponse } from 'axios'; -import { AlBaseError, AlAPIServerError, AlWrappedError } from '../common/errors'; -import { AlDefaultClient, APIRequestParams } from '../client'; +import { AlBaseError, AlAPIServerError, AlWrappedError } from './types'; /** * AlErrorHandler is a simple utility class for normalizing errors and exceptions into a known format. @@ -18,6 +17,17 @@ export class AlErrorHandler console.log( commentary ? `${commentary}: ${normalized.message}` : normalized.message ); } + /** + * Type guard: object is an AxiosResponse + */ + public static isResponse( instance:any ):instance is AxiosResponse { + if ( typeof( instance ) === 'object' && instance !== null + && 'status' in instance && 'statusText' in instance && 'headers' in instance && 'config' in instance ) { + return true; + } + return false; + } + /** * Normalizes an error into an AlBaseError. * @@ -28,8 +38,8 @@ export class AlErrorHandler public static normalize( error:AxiosResponse|AlBaseError|Error|string|any ):AlBaseError { if ( error instanceof AlBaseError ) { return error; - } else if ( AlDefaultClient.isResponse( error ) ) { - let config = error.config as APIRequestParams; + } else if ( AlErrorHandler.isResponse( error ) ) { + let config = error.config as any; let serviceName = `service_name` in config ? config.service_name : config.url; let statusCode = `status` in error ? error.status : 0; let errorText = `Received an unexpected ${statusCode} (${error.statusText}) response from '${serviceName}' at '${error.config.url}'.`; diff --git a/src/error-handler/index.ts b/src/errors/index.ts similarity index 67% rename from src/error-handler/index.ts rename to src/errors/index.ts index 26923cd2..a3ad8339 100644 --- a/src/error-handler/index.ts +++ b/src/errors/index.ts @@ -1 +1,2 @@ export { AlErrorHandler } from './al-error-handler'; +export * from './types'; diff --git a/src/common/errors/al-error.types.ts b/src/errors/types/al-error.types.ts similarity index 89% rename from src/common/errors/al-error.types.ts rename to src/errors/types/al-error.types.ts index 7bb438cb..78cee4b2 100644 --- a/src/common/errors/al-error.types.ts +++ b/src/errors/types/al-error.types.ts @@ -16,9 +16,6 @@ import { AxiosResponse, AxiosRequestConfig } from 'axios'; */ export class AlBaseError extends Error { - /* tslint:disable:variable-name */ - __proto__: Error; - /** * Optional reference to underlying Error, AxiosResponse, or thing that triggered * this error. @@ -27,12 +24,10 @@ export class AlBaseError extends Error public details?:any; constructor( message?:string, derivedFrom?:any, details?:any ) { - const trueProto = new.target.prototype; super(message); this.origin = derivedFrom; this.details = details; - - this.__proto__ = trueProto; + Object.setPrototypeOf( this, AlBaseError.prototype ); } } @@ -51,6 +46,7 @@ export class AlAPIServerError extends AlBaseError origin?:AxiosResponse|any ) { /* istanbul ignore next */ super( message, origin ); + Object.setPrototypeOf( this, AlAPIServerError.prototype ); } } @@ -71,6 +67,7 @@ export class AlResponseValidationError extends AlBaseError constructor( message:string, public errors:any[] = [] ) { /* istanbul ignore next */ super( message ); + Object.setPrototypeOf( this, AlResponseValidationError.prototype ); } } @@ -98,6 +95,7 @@ export class AlDataValidationError extends AlBaseError public request?:AxiosRequestConfig ) { /* istanbul ignore next */ super( message ); + Object.setPrototypeOf( this, AlDataValidationError.prototype ); } } @@ -120,6 +118,7 @@ export class AlBadRequestError extends AlBaseError public description?:string ) { /* istanbul ignore next */ super( message ); + Object.setPrototypeOf( this, AlBadRequestError.prototype ); } } @@ -138,6 +137,7 @@ export class AlUnauthenticatedRequestError extends AlBaseError public authority:string ) { /* istanbul ignore next */ super( message ); + Object.setPrototypeOf( this, AlUnauthenticatedRequestError.prototype ); } } @@ -156,6 +156,7 @@ export class AlUnauthorizedRequestError extends AlBaseError public resource:string ) { /* istanbul ignore next */ super( message ); + Object.setPrototypeOf( this, AlUnauthorizedRequestError.prototype ); } } @@ -172,6 +173,7 @@ export class AlUnimplementedMethodError extends AlBaseError constructor( message:string ) { /* istanbul ignore next */ super( message ); + Object.setPrototypeOf( this, AlUnimplementedMethodError.prototype ); } } @@ -187,6 +189,7 @@ export class AlBadGatewayError extends AlBaseError constructor( message:string, public upstreamService:string, public requestDescriptor:unknown ) { /* istanbul ignore next */ super(message); + Object.setPrototypeOf( this, AlBadGatewayError.prototype ); } } @@ -202,6 +205,7 @@ export class AlServiceUnavailableError extends AlBaseError constructor( message:string, public upstreamService:string, public requestDescription:unknown ) { /* istanbul ignore next */ super(message); + Object.setPrototypeOf( this, AlServiceUnavailableError.prototype ); } } @@ -217,6 +221,7 @@ export class AlGatewayTimeoutError extends AlBaseError constructor( message:string, public upstreamService:string, public requestDescription:unknown ) { /* istanbul ignore next */ super(message); + Object.setPrototypeOf( this, AlGatewayTimeoutError.prototype ); } } @@ -233,6 +238,7 @@ export class AlNotFoundError extends AlBaseError constructor( message:string ) { /* istanbul ignore next */ super( message ); + Object.setPrototypeOf( this, AlNotFoundError.prototype ); } } @@ -248,6 +254,7 @@ export class AlWrappedError extends AlBaseError { constructor( message:string, inner:any, details?:any ) { /* istanbul ignore next */ super( message, inner, details ); + Object.setPrototypeOf( this, AlWrappedError.prototype ); } public getInnerError():any { diff --git a/src/common/errors/index.ts b/src/errors/types/index.ts similarity index 100% rename from src/common/errors/index.ts rename to src/errors/types/index.ts diff --git a/src/index.ts b/src/index.ts index a89d81b9..c430d98c 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,8 +1,6 @@ +export * from "./errors/index"; export * from "./common/index"; export * from "./configuration/index"; export * from "./client/index"; export * from "./session/index"; -export * from "./aims-client/index"; -export * from "./subscriptions-client/index"; export * from "./types/index"; -export * from "./error-handler/index"; diff --git a/src/session/al-session.ts b/src/session/al-session.ts index 71967998..b6ece1f8 100644 --- a/src/session/al-session.ts +++ b/src/session/al-session.ts @@ -9,19 +9,17 @@ */ import { - AIMSClient, AIMSUser, AIMSAccount, AIMSAuthentication, AIMSSessionDescriptor, -} from "../aims-client"; -import { - AlApiClient, AlClientBeforeRequestEvent, - AlDefaultClient, + AlRootClient, + AlEntitlementCollection, + AlsAIMS, + AlsSubscriptions, } from "../client"; -import { AlDataValidationError } from "../common/errors"; -import { AlErrorHandler } from '../error-handler'; +import { AlErrorHandler, AlDataValidationError } from "../errors"; import { AlInsightLocations, AlLocation, @@ -36,8 +34,6 @@ import { AlTriggerStream, deepMerge } from "../common/utility"; -import { SubscriptionsClient } from "../subscriptions-client"; -import { AlEntitlementCollection } from "../subscriptions-client/types"; import { AlActingAccountChangedEvent, AlActingAccountResolvedEvent, @@ -71,7 +67,6 @@ export class AlSessionInstance * Protected state properties */ protected sessionIsActive = false; - protected client:AlApiClient = null; protected sessionData: AIMSSessionDescriptor = JSON.parse(JSON.stringify(AlNullSessionDescriptor)); /** @@ -115,9 +110,8 @@ export class AlSessionInstance ]; - constructor( client:AlApiClient = null ) { - this.client = client || AlDefaultClient; - this.notifyStream.siphon( this.client.events ); + constructor() { + this.notifyStream.siphon( AlRootClient.events ); this.notifyStream.attach( AlClientBeforeRequestEvent, this.onBeforeRequest ); /** * Attempt to recreate a persisted session. Note that the timeout below (really just an execution deferral, given the 0ms) prevents any @@ -170,26 +164,26 @@ export class AlSessionInstance } AlLocatorService.reset(); if ( flushClientCache ) { - AlDefaultClient.reset(); + AlRootClient.reset(); } } public async authenticate( username:string, passphrase:string, options:AuthenticationOptions = {} ):Promise { - let session = await this.client.authenticate( username, passphrase, undefined, true ); + let session = await AlRootClient.authenticate( username, passphrase, undefined, true ); this.mergeSessionOptions( session, options ); await this.setAuthentication( session ); return true; } public async authenticateWithSessionToken( sessionToken:string, mfaCode:string, options:AuthenticationOptions = {} ):Promise { - let session = await this.client.authenticateWithMFASessionToken( sessionToken, mfaCode, true ); + let session = await AlRootClient.authenticateWithMFASessionToken( sessionToken, mfaCode, true ); this.mergeSessionOptions( session, options ); await this.setAuthentication( session ); return true; } public async authenticateWithAccessToken( accessToken:string, options:AuthenticationOptions = {} ):Promise { - let tokenInfo = await AIMSClient.getTokenInfo( accessToken ); + let tokenInfo = await AlRootClient.getClient(AlsAIMS).getTokenInfo( accessToken ); tokenInfo.token = accessToken; // Annoyingly, AIMS does not include the `token` property in its response to this call, making the descriptor somewhat irregular let session:AIMSSessionDescriptor = { authentication: tokenInfo }; this.mergeSessionOptions( session, options ); @@ -207,7 +201,7 @@ export class AlSessionInstance try { this.startDetection(); let authenticationSchemaId = "https://alertlogic.com/schematics/aims#definitions/authentication"; - let validator = new AlJsonValidator( AIMSClient ); + let validator = new AlJsonValidator( AlRootClient.getClient(AlsAIMS) ); let test = await validator.test( proposal.authentication, authenticationSchemaId ); if ( ! test.valid ) { throw new AlDataValidationError( `The provided data is not a valid session descriptor.`, proposal, authenticationSchemaId, [ test.error ] ); @@ -260,7 +254,7 @@ export class AlSessionInstance throw new Error("Usage error: setActingAccount requires an account ID or account descriptor." ); } if ( typeof( account ) === 'string' ) { - const accountDetails = await AIMSClient.getAccountDetails( account ); + const accountDetails = await AlRootClient.getClient(AlsAIMS).getAccountDetails( account ); return await this.setActingAccount( accountDetails, profileId ); } const previousAccount = this.sessionData.acting; @@ -276,7 +270,7 @@ export class AlSessionInstance : account.default_location; this.setActiveDatacenter( targetLocationId ); - AlDefaultClient.defaultAccountId = account.id; + AlRootClient.defaultAccountId = account.id; let resolveMetadata = AlRuntimeConfiguration.getOption( ConfigOption.ResolveAccountMetadata, true ); let useConsolidatedResolver = AlRuntimeConfiguration.getOption( ConfigOption.ConsolidatedAccountResolver, false ); @@ -361,7 +355,7 @@ export class AlSessionInstance this.sessionIsActive = true; } if ( this.sessionIsActive ) { - SubscriptionsClient.setInternalUser( this.getPrimaryAccountId() === "2" ); + AlRootClient.getClient( AlsSubscriptions ).setInternalUser( this.getPrimaryAccountId() === "2" ); if ( ! wasActive ) { this.notifyStream.tap(); // *always* get notifyStream flowing at this point, so that we can intercept AlBeforeRequestEvents this.notifyStream.trigger( new AlSessionStartedEvent( this.sessionData.authentication.user, this.sessionData.authentication.account ) ); @@ -378,7 +372,7 @@ export class AlSessionInstance this.sessionIsActive = false; this.storage.destroy(); this.notifyStream.trigger( new AlSessionEndedEvent( ) ); - AlDefaultClient.defaultAccountId = null; + AlRootClient.defaultAccountId = null; return this.isActive(); } @@ -619,7 +613,7 @@ export class AlSessionInstance if ( ! accountId ) { accountId = this.getActingAccountId(); } - return this.resolutionGuard.then( () => AIMSClient.getManagedAccounts( accountId, { active: true } ) ); + return this.resolutionGuard.then( () => AlRootClient.getClient(AlsAIMS).getManagedAccounts( accountId, { active: true } ) ); } /** @@ -650,7 +644,7 @@ export class AlSessionInstance await this.setAuthentication(session); } catch( e ) { this.deactivateSession(); - console.warn(`Failed to reinstate session from localStorage: ${e.message}`, e ); + AlErrorHandler.log( e, "Failed to reinstate session from localStorage" ); } finally { this.endDetection(); } @@ -663,7 +657,7 @@ export class AlSessionInstance } try { if ( AlRuntimeConfiguration.getOption( ConfigOption.NavigationViaGestalt, true ) ) { - let profile = await AlDefaultClient.get( { + let profile = await AlRootClient.get( { service_stack: AlLocation.GestaltAPI, service_name: 'content', version: 1, @@ -672,7 +666,7 @@ export class AlSessionInstance } ); return profile; } else { - let profile = await AlDefaultClient.get( { + let profile = await AlRootClient.get( { url: `/assets/navigation/profiles/${profileId}.json` } ); return profile; @@ -687,7 +681,7 @@ export class AlSessionInstance options:AuthenticationOptions ) { if ( options.actingAccount ) { if ( typeof( options.actingAccount ) === 'string' ) { - session.acting = await AIMSClient.getAccountDetails( options.actingAccount ); + session.acting = await AlRootClient.getClient(AlsAIMS).getAccountDetails( options.actingAccount ); } else { session.acting = options.actingAccount; } @@ -729,13 +723,13 @@ export class AlSessionInstance protected async resolveActingAccount( account:AIMSAccount, profileId?:string ) { const resolved:AlActingAccountResolvedEvent = new AlActingAccountResolvedEvent( account, null, null ); let dataSources:Promise[] = [ - AIMSClient.getAccountDetails( account.id ), + AlRootClient.getClient(AlsAIMS).getAccountDetails( account.id ), this.getSessionProfile( profileId ), - SubscriptionsClient.getEntitlements( this.getPrimaryAccountId() ) + AlRootClient.getClient(AlsSubscriptions).getEntitlements( this.getPrimaryAccountId() ) ]; if ( account.id !== this.getPrimaryAccountId() ) { - dataSources.push( SubscriptionsClient.getEntitlements( account.id ) ); + dataSources.push( AlRootClient.getClient(AlsSubscriptions).getEntitlements( account.id ) ); } return Promise.all( dataSources ) @@ -779,7 +773,7 @@ export class AlSessionInstance }; try { let [ metadata, profile ] = await Promise.all( [ - AlDefaultClient.get( request ), + AlRootClient.get( request ), this.getSessionProfile( profileId ) ] ); let effectiveEntitlements = profile.entitlements diff --git a/src/session/events/events.ts b/src/session/events/events.ts index b54c64a8..0f375ad5 100644 --- a/src/session/events/events.ts +++ b/src/session/events/events.ts @@ -1,12 +1,12 @@ import { AIMSAccount, AIMSUser, -} from "../../aims-client"; +} from "../../client/aims"; import { AlTrigger, AlTriggeredEvent, } from "../../common/utility"; -import { AlEntitlementCollection } from "../../subscriptions-client/types"; +import { AlEntitlementCollection } from "../../client/subscriptions/types"; /** * AlSessionStartedEvent is broadcast by an AlSessionInstance whenever a new session is created by a successful authentication. diff --git a/src/session/null-session.ts b/src/session/null-session.ts index e0b1ec61..306745d2 100644 --- a/src/session/null-session.ts +++ b/src/session/null-session.ts @@ -3,7 +3,7 @@ * This session descriptor corresponds to an empty/unauthenticated session state. */ -import { AIMSSessionDescriptor } from "../aims-client"; +import { AIMSSessionDescriptor } from "../client/aims/types"; /* tslint:disable:variable-name */ export const AlNullSessionDescriptor: AIMSSessionDescriptor = { diff --git a/src/session/types/types.ts b/src/session/types/types.ts index 4d14be37..cb639ba5 100644 --- a/src/session/types/types.ts +++ b/src/session/types/types.ts @@ -1,8 +1,8 @@ import { AIMSAccount, AIMSUser, -} from '../../aims-client/types'; -import { AlEntitlementRecord } from "../../subscriptions-client/types"; +} from '../../client/aims/types'; +import { AlEntitlementRecord } from "../../client/subscriptions/types"; export interface AlConsolidatedAccountMetadata { user:AIMSUser; diff --git a/src/session/utilities/al-authentication.utility.ts b/src/session/utilities/al-authentication.utility.ts index f574f355..7ad23086 100644 --- a/src/session/utilities/al-authentication.utility.ts +++ b/src/session/utilities/al-authentication.utility.ts @@ -1,7 +1,7 @@ import { AlDefaultClient } from '../../client'; import { AlSession } from '../al-session'; import { AlLocatorService, AlLocation } from '../../common/navigation'; -import { AIMSSessionDescriptor } from '../../aims-client/types'; +import { AIMSSessionDescriptor } from '../../client/aims//types'; import { AlRuntimeConfiguration, ConfigOption } from '../../configuration'; import { AlConduitClient } from './al-conduit-client'; import { getJsonPath } from '../../common/utility'; diff --git a/src/session/utilities/al-conduit-client.ts b/src/session/utilities/al-conduit-client.ts index c62fb229..48a74287 100644 --- a/src/session/utilities/al-conduit-client.ts +++ b/src/session/utilities/al-conduit-client.ts @@ -1,4 +1,4 @@ -import { AIMSSessionDescriptor } from "../../aims-client/types"; +import { AIMSSessionDescriptor } from "../../client/aims/types"; import { AlLocation, AlLocatorService, diff --git a/src/session/utilities/al-session-detector.ts b/src/session/utilities/al-session-detector.ts index fcfe9639..1d305da2 100644 --- a/src/session/utilities/al-session-detector.ts +++ b/src/session/utilities/al-session-detector.ts @@ -6,9 +6,9 @@ */ import { WebAuth } from 'auth0-js'; -import { AIMSClient, AIMSSessionDescriptor } from "../../aims-client"; -import { AlDefaultClient } from "../../client"; -import { AlErrorHandler } from '../../error-handler'; +import { AlsAIMS, AIMSSessionDescriptor } from "../../client/aims"; +import { AlRootClient } from "../../client"; +import { AlErrorHandler } from '../../errors'; import { AlLocation, AlLocatorService, @@ -109,7 +109,7 @@ export class AlSessionDetector */ public forceAuthentication() { - const loginUri = AlDefaultClient.resolveLocation(AlLocation.AccountsUI, '/#/login'); + const loginUri = AlRootClient.resolveLocation(AlLocation.AccountsUI, '/#/login'); const returnUri = window.location.origin + ((window.location.pathname && window.location.pathname.length > 1) ? window.location.pathname : ""); this.redirect( `${loginUri}?return=${encodeURIComponent(returnUri)}&token=null`, "User is not authenticated; redirecting to login." ); } @@ -165,7 +165,7 @@ export class AlSessionDetector if ( authenticator ) { let config = this.getAuth0Config( { usePostMessage: true, prompt: 'none' } ); let accessToken = await this.getAuth0SessionToken( authenticator, config, 5000 ); - let tokenInfo = await AIMSClient.getTokenInfo( accessToken ); + let tokenInfo = await AlRootClient.getClient(AlsAIMS).getTokenInfo( accessToken ); /** * The following rather obscure assignment is necessary because aims' token_info endpoint responds with the complete token information *except* the token itself @@ -193,7 +193,7 @@ export class AlSessionDetector environment = 'integration'; } let sessionStatusURL = AlLocatorService.resolveURL( AlLocation.AccountsUI, `/session/v1/status`, { residency, environment } ); - let sessionStatus = await AlDefaultClient.get( { + let sessionStatus = await AlRootClient.get( { url: sessionStatusURL, withCredentials: true } ); @@ -286,7 +286,7 @@ export class AlSessionDetector if ( session.authentication.user && session.authentication.account ) { return resolve( session ); } - AIMSClient.getTokenInfo( session.authentication.token ) + AlRootClient.getClient(AlsAIMS).getTokenInfo( session.authentication.token ) .then( tokenInfo => { if ( typeof( tokenInfo.user ) === 'object' ) { session.authentication.user = tokenInfo.user; diff --git a/src/subscriptions-client/index.ts b/src/subscriptions-client/index.ts deleted file mode 100644 index affd9a7c..00000000 --- a/src/subscriptions-client/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from "./subscriptions-client"; -export * from "./types/index"; diff --git a/test/aims-client/aims-client.spec.ts b/test/aims-client/aims-client.spec.ts index 14dd9558..bcdd4ed6 100644 --- a/test/aims-client/aims-client.spec.ts +++ b/test/aims-client/aims-client.spec.ts @@ -2,16 +2,15 @@ import { expect } from 'chai'; import { describe } from 'mocha'; import * as sinon from 'sinon'; -import { AlDefaultClient } from "../../src/client"; +import { AlRootClient } from "../../src/client"; import { AlLocation, AlLocatorService, } from "../../src/common/navigation"; import { - AIMSClient, - AIMSClientInstance, + AlsAIMS, AIMSEnrollURI -} from '../../src/aims-client/index'; +} from '../../src/client/aims/index'; const accountId = '12345'; const userId = '4567'; @@ -22,27 +21,21 @@ describe('AIMS Client Test Suite:', () => { let apiBaseURL, globalBaseURL; beforeEach(() => { AlLocatorService.setContext( { environment: "integration" } ); - AlDefaultClient.reset() + AlRootClient.reset() .setGlobalParameters( { noEndpointsResolution: true } ); - stub = sinon.stub(AlDefaultClient as any, "axiosRequest").returns( Promise.resolve( { status: 200, data: 'Some result', config: {} } ) ); + stub = sinon.stub(AlRootClient as any, "axiosRequest").returns( Promise.resolve( { status: 200, data: 'Some result', config: {} } ) ); apiBaseURL = AlLocatorService.resolveURL( AlLocation.InsightAPI ); globalBaseURL = AlLocatorService.resolveURL( AlLocation.GlobalAPI ); }); afterEach(() => { stub.restore(); }); - describe("when instantiating a client", () => { - it("should capture the specified client", () => { - let clientInstance = new AIMSClientInstance( AlDefaultClient ); - expect( clientInstance['client'] ).to.equal( AlDefaultClient ); - } ); - } ); describe('when performing a create user operation', () => { - it('should call post() on the AlDefaultClient instance with a correctly constructed payload', async() => { + it('should call post() on the AlRootClient instance with a correctly constructed payload', async() => { const name = 'someone.somewhere'; const email = 'someone@somwehere.com'; const mobilePhone = '123-456-789-000'; - await AIMSClient.createUser(accountId, name, email, mobilePhone); + await AlRootClient.getClient(AlsAIMS).createUser(accountId, name, email, mobilePhone); expect(stub.callCount).to.equal(1); const payload = stub.args[0][0]; expect( payload.method ).to.equal( "POST" ); @@ -51,8 +44,8 @@ describe('AIMS Client Test Suite:', () => { }); }); describe('when performing a delete user operation', () => { - it('should call delete() on the AlDefaultClient instance with a correctly constructed payload', async() => { - await AIMSClient.deleteUser(accountId, userId); + it('should call delete() on the AlRootClient instance with a correctly constructed payload', async() => { + await AlRootClient.getClient(AlsAIMS).deleteUser(accountId, userId); expect(stub.callCount).to.equal(1); const payload = stub.args[0][0]; expect( payload.method ).to.equal( "DELETE" ); @@ -60,8 +53,8 @@ describe('AIMS Client Test Suite:', () => { }); }); describe('when retrieving a user record', () => { - it('should call fetch() on the AlDefaultClient instance with a correctly constructed payload', async() => { - await AIMSClient.getUserDetailsById(accountId, userId); + it('should call fetch() on the AlRootClient instance with a correctly constructed payload', async() => { + await AlRootClient.getClient(AlsAIMS).getUserDetailsById(accountId, userId); expect(stub.callCount).to.equal(1); const payload = stub.args[0][0]; expect( payload.method ).to.equal( "GET" ); @@ -69,8 +62,8 @@ describe('AIMS Client Test Suite:', () => { }); }); describe('when retrieving permissions for a user', () => { - it('should call fetch() on the AlDefaultClient instance with a correctly constructed payload', async() => { - await AIMSClient.getUserPermissions(accountId, userId); + it('should call fetch() on the AlRootClient instance with a correctly constructed payload', async() => { + await AlRootClient.getClient(AlsAIMS).getUserPermissions(accountId, userId); expect(stub.callCount).to.equal(1); const payload = stub.args[0][0]; expect( payload.method ).to.equal( "GET" ); @@ -78,8 +71,8 @@ describe('AIMS Client Test Suite:', () => { }); }); describe('when retrieving account details', () => { - it('should call fetch() on the AlDefaultClient instance with a correctly constructed payload', async() => { - await AIMSClient.getAccountDetails(accountId); + it('should call fetch() on the AlRootClient instance with a correctly constructed payload', async() => { + await AlRootClient.getClient(AlsAIMS).getAccountDetails(accountId); expect(stub.callCount).to.equal(1); const payload = stub.args[0][0]; expect( payload.method ).to.equal( "GET" ); @@ -87,8 +80,8 @@ describe('AIMS Client Test Suite:', () => { }); }); describe('when retrieving managed account details', () => { - it('should call fetch() on the AlDefaultClient instance with a correctly constructed payload', async() => { - await AIMSClient.getManagedAccounts(accountId, queryParams); + it('should call fetch() on the AlRootClient instance with a correctly constructed payload', async() => { + await AlRootClient.getClient(AlsAIMS).getManagedAccounts(accountId, queryParams); expect(stub.callCount).to.equal(1); const payload = stub.args[0][0]; expect( payload.method ).to.equal( "GET" ); @@ -96,8 +89,8 @@ describe('AIMS Client Test Suite:', () => { }); }); describe('when retrieving managed account Ids', () => { - it('should call fetch() on the AlDefaultClient instance with a correctly constructed payload', async() => { - await AIMSClient.getManagedAccountIds(accountId, queryParams); + it('should call fetch() on the AlRootClient instance with a correctly constructed payload', async() => { + await AlRootClient.getClient(AlsAIMS).getManagedAccountIds(accountId, queryParams); expect(stub.callCount).to.equal(1); const payload = stub.args[0][0]; expect( payload.method ).to.equal( "GET" ); @@ -105,8 +98,8 @@ describe('AIMS Client Test Suite:', () => { }); }); describe('when retrieving managing account Id', () => { - it('should call fetch() on the AlDefaultClient instance with a correctly constructed payload', async() => { - await AIMSClient.getAccountIdsByRelationship(accountId,'managing', queryParams); + it('should call fetch() on the AlRootClient instance with a correctly constructed payload', async() => { + await AlRootClient.getClient(AlsAIMS).getAccountIdsByRelationship(accountId,'managing', queryParams); expect(stub.callCount).to.equal(1); const payload = stub.args[0][0]; expect( payload.method ).to.equal( "GET" ); @@ -114,8 +107,8 @@ describe('AIMS Client Test Suite:', () => { }); }); describe('when retrieving managing accounts', () => { - it('should call fetch() on the AlDefaultClient instance with a correctly constructed payload', async() => { - await AIMSClient.getAccountsByRelationship(accountId,'managing', queryParams); + it('should call fetch() on the AlRootClient instance with a correctly constructed payload', async() => { + await AlRootClient.getClient(AlsAIMS).getAccountsByRelationship(accountId,'managing', queryParams); expect(stub.callCount).to.equal(1); const payload = stub.args[0][0]; expect( payload.method ).to.equal( "GET" ); @@ -123,8 +116,8 @@ describe('AIMS Client Test Suite:', () => { }); }); describe('when enabling MFA for a user account', () => { - it('should call post() on the AlDefaultClient instance with a correctly constructed payload', async() => { - await AIMSClient.requireMFA(accountId, true); + it('should call post() on the AlRootClient instance with a correctly constructed payload', async() => { + await AlRootClient.getClient(AlsAIMS).requireMFA(accountId, true); expect(stub.callCount).to.equal(1); const payload = stub.args[0][0]; expect( payload.method ).to.equal( "POST" ); @@ -133,10 +126,10 @@ describe('AIMS Client Test Suite:', () => { }); }); describe('when authenticating a user', () => { - it('should call authenticate() on the AlDefaultClient instance with the supplied params, username and password', async() => { + it('should call authenticate() on the AlRootClient instance with the supplied params, username and password', async() => { const username = 'someone.somewhere'; const password = 'LetMeIn!'; - await AIMSClient.authenticate(username, password, null ); + await AlRootClient.getClient(AlsAIMS).authenticate(username, password, null ); expect(stub.callCount).to.equal(1); const payload = stub.args[0][0]; expect( payload.method ).to.equal( 'POST' ); @@ -144,10 +137,10 @@ describe('AIMS Client Test Suite:', () => { }); }); describe('when authenticating with an MFA session token', () => { - it('should call authenticateWithMFASessionToken() on the AlDefaultClient instance with the supplied param, token and mfa values', async() => { + it('should call authenticateWithMFASessionToken() on the AlRootClient instance with the supplied param, token and mfa values', async() => { const token = 'abc-123-xYz=-'; const mfa = '123001'; - await AIMSClient.authenticateWithMFASessionToken(token, mfa ); + await AlRootClient.getClient(AlsAIMS).authenticateWithMFASessionToken(token, mfa ); expect(stub.callCount).to.equal(1); const payload = stub.args[0][0]; expect( payload.method ).to.equal( "POST" ); @@ -155,11 +148,11 @@ describe('AIMS Client Test Suite:', () => { }); }); describe('when changing a user password', () => { - it('should call post() on the AlDefaultClient instance with a correctly constructed payload', async() => { + it('should call post() on the AlRootClient instance with a correctly constructed payload', async() => { const email = 'someone@somewhere.com'; const password = 'xyz123'; const newPassword = 'ABC007'; - await AIMSClient.changePassword(email, password, newPassword); + await AlRootClient.getClient(AlsAIMS).changePassword(email, password, newPassword); expect(stub.callCount).to.equal(1); const payload = stub.args[0][0]; expect( payload.method ).to.equal( "POST" ); @@ -167,18 +160,9 @@ describe('AIMS Client Test Suite:', () => { expect( payload.data ).to.deep.equal( { email, current_password: password, new_password: newPassword } ); }); }); - describe('when retrieving tokenInfo', () => { - it('should call fetch() on the AlDefaultClient instance with a correctly constructed payload', async() => { - await AIMSClient.tokenInfo(); - expect(stub.callCount).to.equal(1); - const payload = stub.args[0][0]; - expect( payload.method ).to.equal( "GET" ); - expect( payload.url ).to.equal( `${apiBaseURL}/aims/v1/token_info` ); - }); - }); describe("when retrieving token info for a specific token", () => { it("should call the correct URL", async() => { - await AIMSClient.getTokenInfo( "ABCDEFGHIJKLMNOPQRSTUVWXYZ" ); + await AlRootClient.getClient(AlsAIMS).getTokenInfo( "ABCDEFGHIJKLMNOPQRSTUVWXYZ" ); expect( stub.callCount ).to.equal( 1 ); const payload = stub.args[0][0]; expect( payload.method ).to.equal( "GET" ); @@ -187,10 +171,10 @@ describe('AIMS Client Test Suite:', () => { } ); } ); describe('when initiating a password reset', () => { - it('should call post() on the AlDefaultClient instance with a correctly constructed payload', async() => { + it('should call post() on the AlRootClient instance with a correctly constructed payload', async() => { const returnTo = 'https://console.alertlogic.net'; const email = 'someone@somewhere.com'; - await AIMSClient.initiateReset(email, returnTo); + await AlRootClient.getClient(AlsAIMS).initiateReset(email, returnTo); expect(stub.callCount).to.equal(1); const payload = stub.args[0][0]; expect( payload.method ).to.equal( "POST" ); @@ -199,10 +183,10 @@ describe('AIMS Client Test Suite:', () => { }); }); describe('when initiating a password reset with a token', () => { - it('should call set() on the AlDefaultClient instance with a correctly constructed payload', async() => { + it('should call set() on the AlRootClient instance with a correctly constructed payload', async() => { const token = 'xyz-123'; const password = 'P@ssw0rd'; - await AIMSClient.resetWithToken(token, password); + await AlRootClient.getClient(AlsAIMS).resetWithToken(token, password); expect(stub.callCount).to.equal(1); const payload = stub.args[0][0]; expect( payload.method ).to.equal( "PUT" ); @@ -211,10 +195,10 @@ describe('AIMS Client Test Suite:', () => { }); }); describe('when creating a new role', () => { - it('should call post() on the AlDefaultClient instance with a correctly constructed payload', async() => { + it('should call post() on the AlRootClient instance with a correctly constructed payload', async() => { const name = 'RoleA'; const permissions = { foo: 'bar' }; - await AIMSClient.createRole(accountId, name, permissions); + await AlRootClient.getClient(AlsAIMS).createRole(accountId, name, permissions); expect(stub.callCount).to.equal(1); const payload = stub.args[0][0]; expect( payload.method ).to.equal( "POST" ); @@ -223,9 +207,9 @@ describe('AIMS Client Test Suite:', () => { }); }); describe('when deleting a role', () => { - it('should call delete() on the AlDefaultClient instance with a correctly constructed payload', async() => { + it('should call delete() on the AlRootClient instance with a correctly constructed payload', async() => { const roleId = '00-22-xx-zz'; - await AIMSClient.deleteRole(accountId, roleId); + await AlRootClient.getClient(AlsAIMS).deleteRole(accountId, roleId); expect(stub.callCount).to.equal(1); const payload = stub.args[0][0]; expect( payload.method ).to.equal( "DELETE" ); @@ -233,9 +217,9 @@ describe('AIMS Client Test Suite:', () => { }); }); describe('when retrieving a global role', () => { - it('should call fetch() on the AlDefaultClient instance with a correctly constructed payload', async() => { + it('should call fetch() on the AlRootClient instance with a correctly constructed payload', async() => { const roleId = '00-22-xx-zz'; - await AIMSClient.getGlobalRole(roleId); + await AlRootClient.getClient(AlsAIMS).getGlobalRole(roleId); expect(stub.callCount).to.equal(1); const payload = stub.args[0][0]; expect( payload.method ).to.equal( "GET" ); @@ -243,9 +227,9 @@ describe('AIMS Client Test Suite:', () => { }); }); describe('when retrieving an account role', () => { - it('should call fetch() on the AlDefaultClient instance with a correctly constructed payload', async() => { + it('should call fetch() on the AlRootClient instance with a correctly constructed payload', async() => { const roleId = '00-22-xx-zz'; - await AIMSClient.getAccountRole(accountId, roleId); + await AlRootClient.getClient(AlsAIMS).getAccountRole(accountId, roleId); expect(stub.callCount).to.equal(1); const payload = stub.args[0][0]; expect( payload.method ).to.equal( "GET" ); @@ -253,8 +237,8 @@ describe('AIMS Client Test Suite:', () => { }); }); describe('when retrieving all global roles', () => { - it('should call fetch() on the AlDefaultClient instance to the roles endpoint', async() => { - await AIMSClient.getGlobalRoles(); + it('should call fetch() on the AlRootClient instance to the roles endpoint', async() => { + await AlRootClient.getClient(AlsAIMS).getGlobalRoles(); expect(stub.callCount).to.equal(1); const payload = stub.args[0][0]; expect( payload.method ).to.equal( "GET" ); @@ -262,8 +246,8 @@ describe('AIMS Client Test Suite:', () => { }); }); describe('when retrieving all account roles', () => { - it('should call fetch() on the AlDefaultClient instance to the roles endpoint', async() => { - await AIMSClient.getAccountRoles(accountId); + it('should call fetch() on the AlRootClient instance to the roles endpoint', async() => { + await AlRootClient.getClient(AlsAIMS).getAccountRoles(accountId); expect(stub.callCount).to.equal(1); const payload = stub.args[0][0]; expect( payload.method ).to.equal( "GET" ); @@ -271,10 +255,10 @@ describe('AIMS Client Test Suite:', () => { }); }); describe('when updating the name and permissions of a role', () => { - it('should call post() on the AlDefaultClient instance to the roles endpoint with a payload containing the name and permissions', async() => { + it('should call post() on the AlRootClient instance to the roles endpoint with a payload containing the name and permissions', async() => { const name = 'Mega Power User'; const permissions = { '*:own:*:*': 'allowed', 'aims:own:grant:*':'allowed' }; - await AIMSClient.updateRole(accountId, name, permissions); + await AlRootClient.getClient(AlsAIMS).updateRole(accountId, name, permissions); expect(stub.callCount).to.equal(1); const payload = stub.args[0][0]; expect( payload.method ).to.equal( "POST" ); @@ -282,9 +266,9 @@ describe('AIMS Client Test Suite:', () => { }); }); describe('when updating the name of a role', () => { - it('should call post() on the AlDefaultClient instance to the roles endpoint with a payload containing the name', async() => { + it('should call post() on the AlRootClient instance to the roles endpoint with a payload containing the name', async() => { const name = 'Mega Power User'; - await AIMSClient.updateRoleName(accountId, name); + await AlRootClient.getClient(AlsAIMS).updateRoleName(accountId, name); expect(stub.callCount).to.equal(1); const payload = stub.args[0][0]; expect( payload.method ).to.equal( "POST" ); @@ -293,9 +277,9 @@ describe('AIMS Client Test Suite:', () => { }); }); describe('when updating the permissions of a role', () => { - it('should call post() on the AlDefaultClient instance to the roles endpoint with a payload containing the name', async() => { + it('should call post() on the AlRootClient instance to the roles endpoint with a payload containing the name', async() => { const permissions = { '*:own:*:*': 'allowed', 'aims:own:grant:*':'allowed' }; - await AIMSClient.updateRolePermissions(accountId, permissions); + await AlRootClient.getClient(AlsAIMS).updateRolePermissions(accountId, permissions); expect(stub.callCount).to.equal(1); const payload = stub.args[0][0]; expect( payload.method ).to.equal( "POST" ); @@ -304,10 +288,10 @@ describe('AIMS Client Test Suite:', () => { }); }); describe('when enrolling a users MFA device', () => { - it('should call post() on the AlDefaultClient instance to the mfa endpoint with the supplied uri and codes', async() => { + it('should call post() on the AlRootClient instance to the mfa endpoint with the supplied uri and codes', async() => { const uri = 'otpauth://totp/Alert%20Logic:admin@company.com?secret=GFZSA5CINFJSA4ZTNNZDG5BAKM2EMMZ7&issuer=Alert%20Logic&algorithm=SHA1'; const codes = ['123456', '456789']; - await AIMSClient.enrollMFA(uri, "Some Token", codes); + await AlRootClient.getClient(AlsAIMS).enrollMFA(uri, "Some Token", codes); expect(stub.callCount).to.equal(1); const payload = stub.args[0][0]; expect( payload.method ).to.equal( "POST" ); @@ -316,9 +300,9 @@ describe('AIMS Client Test Suite:', () => { }); }); describe('when removing a users MFA device', () => { - it('should call delete() on the AlDefaultClient instance to the mfa endpoint with the supplied email', async() => { + it('should call delete() on the AlRootClient instance to the mfa endpoint with the supplied email', async() => { const email = 'admin@company.com'; - await AIMSClient.deleteMFA(email); + await AlRootClient.getClient(AlsAIMS).deleteMFA(email); expect(stub.callCount).to.equal(1); const payload = stub.args[0][0]; expect( payload.method ).to.equal( "DELETE" ); @@ -326,9 +310,9 @@ describe('AIMS Client Test Suite:', () => { }); }); describe('when retrieving user details', () => { - it('should call fetch() on the AlDefaultClient instance to the users endpoint with any extra params supplied', async() => { + it('should call fetch() on the AlRootClient instance to the users endpoint with any extra params supplied', async() => { const reqParams = { include_role_ids: true, include_user_credential: true }; - await AIMSClient.getUserDetails(accountId, userId, reqParams); + await AlRootClient.getClient(AlsAIMS).getUserDetails(accountId, userId, reqParams); expect(stub.callCount).to.equal(1); const payload = stub.args[0][0]; expect( payload.method ).to.equal( "GET" ); @@ -336,9 +320,9 @@ describe('AIMS Client Test Suite:', () => { }); }); describe('when retrieving users', () => { - it('should call fetch() on the AlDefaultClient instance to the users endpoint with any extra params supplied', async() => { + it('should call fetch() on the AlRootClient instance to the users endpoint with any extra params supplied', async() => { const reqParams = { include_role_ids: true, include_user_credential: true }; - await AIMSClient.getUsers(accountId, reqParams); + await AlRootClient.getClient(AlsAIMS).getUsers(accountId, reqParams); expect(stub.callCount).to.equal(1); const payload = stub.args[0][0]; expect( payload.method ).to.equal( "GET" ); @@ -346,9 +330,9 @@ describe('AIMS Client Test Suite:', () => { }); }); describe('when creating an access key', () => { - it('should call post() on the AlDefaultClient instance to the access_keys endpoint with the label value supplied', async() => { + it('should call post() on the AlRootClient instance to the access_keys endpoint with the label value supplied', async() => { const label = 'my-key'; - await AIMSClient.createAccessKey(accountId, userId, label); + await AlRootClient.getClient(AlsAIMS).createAccessKey(accountId, userId, label); expect(stub.callCount).to.equal(1); const payload = stub.args[0][0]; expect( payload.method ).to.equal( "POST" ); @@ -357,10 +341,10 @@ describe('AIMS Client Test Suite:', () => { }); }); describe('when updating an access key', () => { - it('should call post() on the AlDefaultClient instance to the access_keys endpoint with the label value supplied', async() => { + it('should call post() on the AlRootClient instance to the access_keys endpoint with the label value supplied', async() => { const label = 'my-key'; const accessKeyId = '002211-22dddc'; - await AIMSClient.updateAccessKey(accessKeyId, label); + await AlRootClient.getClient(AlsAIMS).updateAccessKey(accessKeyId, label); expect(stub.callCount).to.equal(1); const payload = stub.args[0][0]; expect( payload.method ).to.equal( "POST" ); @@ -369,9 +353,9 @@ describe('AIMS Client Test Suite:', () => { }); }); describe('when retrieving an access key', () => { - it('should call fetch() on the AlDefaultClient instance to the access_keys endpoint for the supplied access key id value', async() => { + it('should call fetch() on the AlRootClient instance to the access_keys endpoint for the supplied access key id value', async() => { const accessKeyId = '002211-22dddc'; - await AIMSClient.getAccessKey(accessKeyId); + await AlRootClient.getClient(AlsAIMS).getAccessKey(accessKeyId); expect(stub.callCount).to.equal(1); const payload = stub.args[0][0]; expect( payload.method ).to.equal( "GET" ); @@ -379,8 +363,8 @@ describe('AIMS Client Test Suite:', () => { }); }); describe('when retrieving all access keys for a user', () => { - it('should call fetch() on the AlDefaultClient instance to the access_keys endpoint for the supplied user id value', async() => { - await AIMSClient.getAccessKeys(accountId, userId ); + it('should call fetch() on the AlRootClient instance to the access_keys endpoint for the supplied user id value', async() => { + await AlRootClient.getClient(AlsAIMS).getAccessKeys(accountId, userId ); expect(stub.callCount).to.equal(1); const payload = stub.args[0][0]; expect( payload.method ).to.equal( "GET" ); @@ -388,9 +372,9 @@ describe('AIMS Client Test Suite:', () => { }); }); describe('when deleting an access key for a user', () => { - it('should call delete() on the AlDefaultClient instance to the access_keys endpoint for the supplied user and access key id values', async() => { + it('should call delete() on the AlRootClient instance to the access_keys endpoint for the supplied user and access key id values', async() => { const accessKeyId = '002211-22dddc'; - await AIMSClient.deleteAccessKey(accountId, userId, accessKeyId); + await AlRootClient.getClient(AlsAIMS).deleteAccessKey(accountId, userId, accessKeyId); expect(stub.callCount).to.equal(1); const payload = stub.args[0][0]; expect( payload.method ).to.equal( "DELETE" ); diff --git a/test/client/al-api-client.spec.ts b/test/client/al-api-client.spec.ts index 66cf3291..f3703a1b 100644 --- a/test/client/al-api-client.spec.ts +++ b/test/client/al-api-client.spec.ts @@ -6,7 +6,7 @@ import { AlLocation, AlLocatorService, AlCabinet, - AlDefaultClient, + AlRootClient, APIRequestParams } from "@al/core"; @@ -91,16 +91,16 @@ function configureCache( client:any ) { }; } -describe("AlDefaultClient", () => { +describe("AlRootClient", () => { beforeEach(() => { xhrMock.setup(); AlLocatorService.setContext( { environment: "integration", residency: 'EMEA', insightLocationId: 'defender-uk-newport' } ); // for unit tests, assume integration environment - configureCache( AlDefaultClient ); + configureCache( AlRootClient ); } ); afterEach(() => { xhrMock.teardown(); - AlDefaultClient.reset(); + AlRootClient.reset(); }); describe('merge function', () => { @@ -120,13 +120,13 @@ describe("AlDefaultClient", () => { c: "miss piggy" }; - let target = AlDefaultClient['merge']( {}, source1 ); + let target = AlRootClient['merge']( {}, source1 ); expect( target ).to.deep.equal( source1 ); - target = AlDefaultClient['merge']( {}, source1, source2 ); + target = AlRootClient['merge']( {}, source1, source2 ); expect( target ).to.deep.equal( source2 ); - target = AlDefaultClient['merge']( {}, source1, source3, source2 ); + target = AlRootClient['merge']( {}, source1, source3, source2 ); expect( target.a ).to.equal( false ); expect( target.b ).to.equal( 4 ); expect( target.c ).to.equal( "kermit" ); @@ -136,7 +136,7 @@ describe("AlDefaultClient", () => { describe('when calculating request URLs', () => { describe('with no params supplied', () => { it('should throw an error', async () => { - let result = await AlDefaultClient['calculateRequestURL']( {} ) + let result = await AlRootClient['calculateRequestURL']( {} ) .then( r => { expect( false ).to.equal( true ); // this should never occur } ).catch( e => { @@ -147,49 +147,49 @@ describe("AlDefaultClient", () => { describe('with parameters', () => { it('should return targets with correct hosts and paths', async () => { - let endpointURL = await AlDefaultClient['calculateRequestURL']({ service_name: 'cargo', service_stack: AlLocation.InsightAPI }); + let endpointURL = await AlRootClient['calculateRequestURL']({ service_name: 'cargo', service_stack: AlLocation.InsightAPI }); // path should default to /:service_name/v1, no trailing slash expect(endpointURL).to.equal( "https://api.product.dev.alertlogic.com/cargo" ); - endpointURL = await AlDefaultClient['calculateRequestURL']( { service_name: 'aims', version: null, service_stack: AlLocation.InsightAPI } ); + endpointURL = await AlRootClient['calculateRequestURL']( { service_name: 'aims', version: null, service_stack: AlLocation.InsightAPI } ); expect(endpointURL).to.equal( "https://api.global-integration.product.dev.alertlogic.com/aims" ); - endpointURL = await AlDefaultClient['calculateRequestURL']( { service_name: 'aims', version: 'v4', service_stack: AlLocation.InsightAPI } ); + endpointURL = await AlRootClient['calculateRequestURL']( { service_name: 'aims', version: 'v4', service_stack: AlLocation.InsightAPI } ); // path should be /:service_name/:version, no trailing slash expect(endpointURL).to.equal( "https://api.global-integration.product.dev.alertlogic.com/aims/v4" ); - endpointURL = await AlDefaultClient['calculateRequestURL']( { service_name: 'cargo', version: 'v2', account_id: '67108880', service_stack: AlLocation.InsightAPI } ); + endpointURL = await AlRootClient['calculateRequestURL']( { service_name: 'cargo', version: 'v2', account_id: '67108880', service_stack: AlLocation.InsightAPI } ); // path should be /:service_name/:version/:accountId, no trailing slash expect( endpointURL ).to.equal( `https://api.product.dev.alertlogic.com/cargo/v2/67108880` ); - endpointURL = await AlDefaultClient['calculateRequestURL']( { service_name: 'search', version: 'v1', path: 'global-capabilities', service_stack: AlLocation.InsightAPI } ); + endpointURL = await AlRootClient['calculateRequestURL']( { service_name: 'search', version: 'v1', path: 'global-capabilities', service_stack: AlLocation.InsightAPI } ); // domain should be non-default; path should be /:service_name/:version/:path expect( endpointURL ).to.equal( `https://api.global-fake-integration.product.dev.alertlogic.com/search/v1/global-capabilities` ); - endpointURL = await AlDefaultClient['calculateRequestURL']( { service_name: 'aims', version: 'v100', account_id: '67108880', path: '/some/arbitrary/path/', service_stack: AlLocation.InsightAPI } ); + endpointURL = await AlRootClient['calculateRequestURL']( { service_name: 'aims', version: 'v100', account_id: '67108880', path: '/some/arbitrary/path/', service_stack: AlLocation.InsightAPI } ); // path should be /:service_name/:version/:accountId, trailing slash ONLY because it is included in path, but no double slash from the slash at the beginning of `path` expect( endpointURL ).to.equal( "https://api.global-integration.product.dev.alertlogic.com/aims/v100/67108880/some/arbitrary/path/" ); - endpointURL = await AlDefaultClient['calculateRequestURL']( { service_name: 'search', version: 2, account_id: '2', path: '/some/endpoint', params: { a: 1, b: 2, c: 3 }, service_stack: AlLocation.InsightAPI } ); + endpointURL = await AlRootClient['calculateRequestURL']( { service_name: 'search', version: 2, account_id: '2', path: '/some/endpoint', params: { a: 1, b: 2, c: 3 }, service_stack: AlLocation.InsightAPI } ); // query params should not be applied by this stage -- axios serializes them and dispatches them during the actual request execution expect( endpointURL ).to.equal( "https://api.global-fake-integration.product.dev.alertlogic.com/search/v2/2/some/endpoint" ); - endpointURL = await AlDefaultClient['calculateRequestURL']( { service_name: 'kevin', version: 1, account_id: '67108880', path: '/some/endpoint', context_account_id: '3', service_stack: AlLocation.InsightAPI } ); + endpointURL = await AlRootClient['calculateRequestURL']( { service_name: 'kevin', version: 1, account_id: '67108880', path: '/some/endpoint', context_account_id: '3', service_stack: AlLocation.InsightAPI } ); // expect the endpoints response for the context_account_id to be used instead of the dominant account_id's expect( endpointURL ).to.equal( `https://kevin.product.dev.alertlogic.co.uk/kevin/v1/67108880/some/endpoint` ); - endpointURL = await AlDefaultClient['calculateRequestURL']( { service_name: 'cargo', target_endpoint: 'kevin', path: '/some/endpoint' } ); + endpointURL = await AlRootClient['calculateRequestURL']( { service_name: 'cargo', target_endpoint: 'kevin', path: '/some/endpoint' } ); // expect target endpoint ID to be honored expect( endpointURL ).to.equal( `https://kevin.product.dev.alertlogic.com/cargo/some/endpoint` ); - endpointURL = await AlDefaultClient['calculateRequestURL']( { service_name: 'iris', version: 1, account_id: '12345678', path: '/some/endpoint', service_stack: AlLocation.InsightAPI } ); + endpointURL = await AlRootClient['calculateRequestURL']( { service_name: 'iris', version: 1, account_id: '12345678', path: '/some/endpoint', service_stack: AlLocation.InsightAPI } ); // expect target endpoint to be referenced from residency based lookup expect( endpointURL ).to.equal( `https://rob.product.dev.alertlogic.co.uk/iris/v1/12345678/some/endpoint` ); - AlDefaultClient.defaultAccountId = "67108880"; - endpointURL = await AlDefaultClient['calculateRequestURL']( { service_name: 'kevin', version: 16, path: 'some/arbitrary/endpoint', service_stack: AlLocation.InsightAPI } ); + AlRootClient.defaultAccountId = "67108880"; + endpointURL = await AlRootClient['calculateRequestURL']( { service_name: 'kevin', version: 16, path: 'some/arbitrary/endpoint', service_stack: AlLocation.InsightAPI } ); expect( endpointURL ).to.equal( `https://kevin.product.dev.alertlogic.com/kevin/v16/some/arbitrary/endpoint` ); - AlDefaultClient.defaultAccountId = null; + AlRootClient.defaultAccountId = null; }); @@ -200,7 +200,7 @@ describe("AlDefaultClient", () => { status: 200, body: {"bryan": "api.bryan.alertlogic.com"} }) ); - let url = await AlDefaultClient['calculateRequestURL']( { target_endpoint: 'bryan', path: 'playbooks', version: 1, account_id: "10101010" } ); + let url = await AlRootClient['calculateRequestURL']( { target_endpoint: 'bryan', path: 'playbooks', version: 1, account_id: "10101010" } ); expect( url ).to.equal( 'https://api.bryan.alertlogic.com/v1/10101010/playbooks' ); } ); it("should set wss protocol for async endpoints", async () => { @@ -208,7 +208,7 @@ describe("AlDefaultClient", () => { status: 200, body: {"bryan": "async.bryan.alertlogic.com"} }) ); - let url = await AlDefaultClient['calculateRequestURL']( { target_endpoint: 'bryan', path: 'playbooks', version: 1, account_id: "10101010" } ); + let url = await AlRootClient['calculateRequestURL']( { target_endpoint: 'bryan', path: 'playbooks', version: 1, account_id: "10101010" } ); expect( url ).to.equal( 'wss://async.bryan.alertlogic.com/v1/10101010/playbooks' ); } ); } ); @@ -219,7 +219,7 @@ describe("AlDefaultClient", () => { body: 'Internal Error Or Something' }) ); - let url = await AlDefaultClient['calculateRequestURL']( { service_name: 'aims', version: 1, path: '/something', account_id: "10101010", service_stack: AlLocation.InsightAPI } ); + let url = await AlRootClient['calculateRequestURL']( { service_name: 'aims', version: 1, path: '/something', account_id: "10101010", service_stack: AlLocation.InsightAPI } ); expect( url ).to.equal( 'https://api.product.dev.alertlogic.com/aims/v1/10101010/something' ); } ); } ); @@ -233,12 +233,12 @@ describe("AlDefaultClient", () => { status: 200, body: 'first response', })); - await AlDefaultClient.get({ service_name: 'aims', version: 'v1', account_id: '2', path: 'users' }); // fetch once + await AlRootClient.get({ service_name: 'aims', version: 'v1', account_id: '2', path: 'users' }); // fetch once xhrMock.get('https://api.global-integration.product.dev.alertlogic.com/aims/v1/2/users', once({ status: 200, body: 'second response', })); - let response = await AlDefaultClient.get({ service_name: 'aims', version: 'v1', account_id: '2', path: 'users'}); // fetch again, TTL 0 to disable caching + let response = await AlRootClient.get({ service_name: 'aims', version: 'v1', account_id: '2', path: 'users'}); // fetch again, TTL 0 to disable caching expect(response).to.equal('second response'); }); }); @@ -248,12 +248,12 @@ describe("AlDefaultClient", () => { status: 200, body: 'first response', })); - await AlDefaultClient.get({ service_name: 'aims', version: 'v1', account_id: '2', path: 'users', ttl: true }); + await AlRootClient.get({ service_name: 'aims', version: 'v1', account_id: '2', path: 'users', ttl: true }); xhrMock.get('https://api.global-integration.product.dev.alertlogic.com/aims/v1/2/users', once({ status: 200, body: 'second response', })); - let response = await AlDefaultClient.get({ service_name: 'aims', version: 'v1', account_id: '2', path: 'users', ttl: true }); + let response = await AlRootClient.get({ service_name: 'aims', version: 'v1', account_id: '2', path: 'users', ttl: true }); expect(response).to.equal('first response'); }); }); @@ -263,12 +263,12 @@ describe("AlDefaultClient", () => { status: 200, body: 'first response', })); - await AlDefaultClient.get({ service_name: 'aims', version: 'v1', account_id: '2', path: 'users', params: {foo: 'bar'}, ttl: true }); + await AlRootClient.get({ service_name: 'aims', version: 'v1', account_id: '2', path: 'users', params: {foo: 'bar'}, ttl: true }); xhrMock.get('https://api.global-integration.product.dev.alertlogic.com/aims/v1/2/users?foo=bar', once({ status: 200, body: 'second response', })); - let response = await AlDefaultClient.get({ service_name: 'aims', version: 'v1', account_id: '2', path: 'users' , params: {foo: 'bar'}, ttl: true }); + let response = await AlRootClient.get({ service_name: 'aims', version: 'v1', account_id: '2', path: 'users' , params: {foo: 'bar'}, ttl: true }); expect(response).to.equal('first response'); }); describe('which contain an array of values', () => { @@ -277,12 +277,12 @@ describe("AlDefaultClient", () => { status: 200, body: 'first response', })); - await AlDefaultClient.get({ service_name: 'aims', version: 'v1', account_id: '2', path: 'users', params: {foo: ['bar', 'meow']}, ttl: true }); + await AlRootClient.get({ service_name: 'aims', version: 'v1', account_id: '2', path: 'users', params: {foo: ['bar', 'meow']}, ttl: true }); xhrMock.get('https://api.global-integration.product.dev.alertlogic.com/aims/v1/2/users?foo=bar&foo=meow', once({ status: 200, body: 'second response', })); - let response = await AlDefaultClient.get({ service_name: 'aims', version: 'v1', account_id: '2', path: 'users' , params: {foo: ['bar', 'meow']}, ttl: true }); + let response = await AlRootClient.get({ service_name: 'aims', version: 'v1', account_id: '2', path: 'users' , params: {foo: ['bar', 'meow']}, ttl: true }); expect(response).to.equal('first response'); }); }); @@ -293,12 +293,12 @@ describe("AlDefaultClient", () => { status: 200, body: 'first response', })); - await AlDefaultClient.get({ service_name: 'aims', version: 'v1', account_id: '2', path: 'users', params: {foo: 'bar'}, ttl: true }); + await AlRootClient.get({ service_name: 'aims', version: 'v1', account_id: '2', path: 'users', params: {foo: 'bar'}, ttl: true }); xhrMock.get('https://api.global-integration.product.dev.alertlogic.com/aims/v1/2/users?foo=baz', once({ status: 200, body: 'second response', })); - let response = await AlDefaultClient.get({ service_name: 'aims', version: 'v1', account_id: '2', path: 'users' , params: {foo: 'baz'}, ttl: true }); + let response = await AlRootClient.get({ service_name: 'aims', version: 'v1', account_id: '2', path: 'users' , params: {foo: 'baz'}, ttl: true }); expect(response).to.equal('second response'); }); }); @@ -315,7 +315,7 @@ describe("AlDefaultClient", () => { expect(req.body()).to.equal('{}'); return res.status(200).body(defaultAuthResponse); }); - const sessionDescriptor = await AlDefaultClient.authenticate(username, password, undefined, true ); + const sessionDescriptor = await AlRootClient.authenticate(username, password, undefined, true ); expect( sessionDescriptor ).to.deep.equals( defaultAuthResponse ); }); }); @@ -327,7 +327,7 @@ describe("AlDefaultClient", () => { return res.status(200).body(defaultAuthResponse); }); try { - const sessionDescriptor = await AlDefaultClient.authenticate(username, password, mfaCode, true ); + const sessionDescriptor = await AlRootClient.authenticate(username, password, mfaCode, true ); expect( sessionDescriptor ).to.deep.equals( defaultAuthResponse ); } catch( e ) { console.error("Got error...", e ); @@ -345,7 +345,7 @@ describe("AlDefaultClient", () => { expect(JSON.parse(req.body())).to.deep.equals({ mfa_code: mfaCode }); return res.status(200).body(defaultAuthResponse); }); - await AlDefaultClient.authenticateWithMFASessionToken(sessionToken, mfaCode, true ); + await AlRootClient.authenticateWithMFASessionToken(sessionToken, mfaCode, true ); }); }); @@ -353,7 +353,7 @@ describe("AlDefaultClient", () => { it( 'should generate random cache breakers for every retry call', () => { let previousValues = []; for ( let i = 0; i < 100; i++ ) { - let breaker = AlDefaultClient['generateCacheBuster']( Math.floor( Math.random() * 5 ) ); // cache busters should be suitably random to avoid overlaps + let breaker = AlRootClient['generateCacheBuster']( Math.floor( Math.random() * 5 ) ); // cache busters should be suitably random to avoid overlaps expect( previousValues.indexOf( breaker ) ).to.equal( -1 ); previousValues.push( breaker ); } @@ -363,14 +363,14 @@ describe("AlDefaultClient", () => { retry_count: 10, url: "https://some.com/made/up/url" }; - expect( AlDefaultClient['isRetryableError']( { data: {}, status: 500, statusText: "Something", config: {}, headers: {} }, config, 0 ) ).to.equal( true ); - expect( AlDefaultClient['isRetryableError']( { data: {}, status: 503, statusText: "Something", config: {}, headers: {} }, config, 0 ) ).to.equal( true ); - expect( AlDefaultClient['isRetryableError']( { data: {}, status: 302, statusText: "Something", config: {}, headers: {} }, config, 0 ) ).to.equal( true ); - expect( AlDefaultClient['isRetryableError']( { data: {}, status: 0, statusText: "Something", config: {}, headers: {} }, config, 0 ) ).to.equal( true ); - expect( AlDefaultClient['isRetryableError']( { data: {}, status: 0, statusText: "Something", config: {}, headers: {} }, config, 10 ) ).to.equal( false ); - expect( AlDefaultClient['isRetryableError']( { data: {}, status: 204, statusText: "Something", config: {}, headers: {} }, config, 0 ) ).to.equal( false ); - expect( AlDefaultClient['isRetryableError']( { data: {}, status: 404, statusText: "Something", config: {}, headers: {} }, config, 0 ) ).to.equal( false ); - expect( AlDefaultClient['isRetryableError']( { data: {}, status: 403, statusText: "Something", config: {}, headers: {} }, config, 0 ) ).to.equal( false ); + expect( AlRootClient['isRetryableError']( { data: {}, status: 500, statusText: "Something", config: {}, headers: {} }, config, 0 ) ).to.equal( true ); + expect( AlRootClient['isRetryableError']( { data: {}, status: 503, statusText: "Something", config: {}, headers: {} }, config, 0 ) ).to.equal( true ); + expect( AlRootClient['isRetryableError']( { data: {}, status: 302, statusText: "Something", config: {}, headers: {} }, config, 0 ) ).to.equal( true ); + expect( AlRootClient['isRetryableError']( { data: {}, status: 0, statusText: "Something", config: {}, headers: {} }, config, 0 ) ).to.equal( true ); + expect( AlRootClient['isRetryableError']( { data: {}, status: 0, statusText: "Something", config: {}, headers: {} }, config, 10 ) ).to.equal( false ); + expect( AlRootClient['isRetryableError']( { data: {}, status: 204, statusText: "Something", config: {}, headers: {} }, config, 0 ) ).to.equal( false ); + expect( AlRootClient['isRetryableError']( { data: {}, status: 404, statusText: "Something", config: {}, headers: {} }, config, 0 ) ).to.equal( false ); + expect( AlRootClient['isRetryableError']( { data: {}, status: 403, statusText: "Something", config: {}, headers: {} }, config, 0 ) ).to.equal( false ); } ); it('should retry if retry_count is specified', async () => { xhrMock.reset(); @@ -387,7 +387,7 @@ describe("AlDefaultClient", () => { status: 200, body: 'Final result', })); - const result = await AlDefaultClient.get({ service_name: 'aims', version: 'v1', account_id: '2', path: 'users', retry_count: 3, retry_interval: 10 }); // fetch once + const result = await AlRootClient.get({ service_name: 'aims', version: 'v1', account_id: '2', path: 'users', retry_count: 3, retry_interval: 10 }); // fetch once expect( result ).to.equal( "Final result" ); }); } ); @@ -401,7 +401,7 @@ describe("AlDefaultClient", () => { expect(req.method()).to.equal('POST'); return res.status(200).body({}); }); - await AlDefaultClient.form(apiRequestParams).then((r) => { + await AlRootClient.form(apiRequestParams).then((r) => { expect(apiRequestParams.headers['Content-Type']).to.equal('multipart/form-data'); expect(apiRequestParams.method).to.equal('POST'); }); @@ -414,7 +414,7 @@ describe("AlDefaultClient", () => { expect(req.method()).to.equal('PUT'); return res.status(200).body({}); }); - await AlDefaultClient.put(apiRequestParams).then((r) => { + await AlRootClient.put(apiRequestParams).then((r) => { expect(apiRequestParams.method).to.equal('PUT'); }); }); @@ -426,7 +426,7 @@ describe("AlDefaultClient", () => { expect(req.method()).to.equal('PUT'); return res.status(200).body({}); }); - await AlDefaultClient.put(apiRequestParams).then((r) => { + await AlRootClient.put(apiRequestParams).then((r) => { expect(apiRequestParams.method).to.equal('PUT'); }); }); @@ -438,7 +438,7 @@ describe("AlDefaultClient", () => { expect(req.method()).to.equal('DELETE'); return res.status(200).body({}); }); - await AlDefaultClient.delete(apiRequestParams).then((r) => { + await AlRootClient.delete(apiRequestParams).then((r) => { expect(apiRequestParams.method).to.equal('DELETE'); }); }); @@ -448,7 +448,7 @@ describe("AlDefaultClient", () => { describe('with an accept_header property', () => { it('set a headers object on the config object with an Accept prop set to the value of the original accept_header value', async() => { const config: APIRequestParams = { accept_header: 'foo/bar'}; - await AlDefaultClient.normalizeRequest(config).then((c) => { + await AlRootClient.normalizeRequest(config).then((c) => { expect(c.headers).to.deep.equals({ Accept: 'foo/bar' }); @@ -458,7 +458,7 @@ describe("AlDefaultClient", () => { describe('with a response_type property', () => { it('set a responseType prop on the config object set to the original response_type value', async() => { const config: APIRequestParams = { response_type: 'something'}; - await AlDefaultClient.normalizeRequest(config).then((c) => { + await AlRootClient.normalizeRequest(config).then((c) => { expect(c.responseType).to.equal('something'); }); }); @@ -470,7 +470,7 @@ describe("AlDefaultClient", () => { it('should return the full url', async() => { const config: APIRequestParams = { service_name: 'aims', version: 'v1', account_id: '2', path: 'users', params: {foo: 'bar', bar: 'foo'}, ttl: true }; config.method = 'GET'; - let fullURL = await AlDefaultClient.fromConfigToFullUrl(config); + let fullURL = await AlRootClient.fromConfigToFullUrl(config); expect(fullURL).equals("https://api.global-integration.product.dev.alertlogic.com/aims/v1/2/users?foo=bar&bar=foo"); }); }); @@ -478,7 +478,7 @@ describe("AlDefaultClient", () => { it('should return the full url', async() => { const config: APIRequestParams = { service_name: 'aims', version: 'v1', account_id: '2', path: 'postme', ttl: true }; config.method = 'POST'; - let fullURL = await AlDefaultClient.fromConfigToFullUrl(config); + let fullURL = await AlRootClient.fromConfigToFullUrl(config); expect(fullURL).equals("https://api.global-integration.product.dev.alertlogic.com/aims/v1/2/postme"); }); }); @@ -486,7 +486,7 @@ describe("AlDefaultClient", () => { it('should return the full url', async() => { const config: APIRequestParams = { service_name: 'aims', version: 'v1', account_id: '2', path: 'putme', ttl: true }; config.method = 'PUT'; - let fullURL = await AlDefaultClient.fromConfigToFullUrl(config); + let fullURL = await AlRootClient.fromConfigToFullUrl(config); expect(fullURL).equals("https://api.global-integration.product.dev.alertlogic.com/aims/v1/2/putme"); }); }); @@ -494,7 +494,7 @@ describe("AlDefaultClient", () => { it('should return the full url', async() => { const config: APIRequestParams = { service_name: 'aims', version: 'v1', account_id: '2', path: 'deleteme', ttl: true }; config.method = 'DELETE'; - let fullURL = await AlDefaultClient.fromConfigToFullUrl(config); + let fullURL = await AlRootClient.fromConfigToFullUrl(config); expect(fullURL).equals("https://api.global-integration.product.dev.alertlogic.com/aims/v1/2/deleteme"); }); }); @@ -515,7 +515,7 @@ describe("AlDefaultClient", () => { * First test covers URL calculation for MDR APIs without endpoints resolution. Important feature: service_name should be * substituted into the domain name, and not the path, and the domain should be well formed. */ - let fullURL = await AlDefaultClient.fromConfigToFullUrl( config ); + let fullURL = await AlRootClient.fromConfigToFullUrl( config ); expect( fullURL ).to.equal( "https://responder.mdr.product.dev.alertlogic.com/v1/12345678/something/wicked?this-way=comes" ); /** @@ -523,7 +523,7 @@ describe("AlDefaultClient", () => { * introduced the service_name into the path. */ config.noEndpointsResolution = false; - fullURL = await AlDefaultClient.fromConfigToFullUrl( config ); + fullURL = await AlRootClient.fromConfigToFullUrl( config ); expect( fullURL ).to.equal( "https://responder.mdr.product.dev.something.alertlogic.com/v1/12345678/something/wicked?this-way=comes" ); } ); @@ -541,7 +541,7 @@ describe("AlDefaultClient", () => { cabinetStorage.synchronize(); // Testing storage. expect(cabinetStorage.get('otherkey')).equal('value3'); - flushSpy = sinon.spy(AlDefaultClient,"flushCacheKeysFromConfig"); + flushSpy = sinon.spy(AlRootClient,"flushCacheKeysFromConfig"); xhrMock.post('https://api.product.dev.alertlogic.com/cargo/v1/2', (req, res) => { expect(req.method()).to.equal('POST'); return res.status(200).body({}); @@ -551,7 +551,7 @@ describe("AlDefaultClient", () => { const config: APIRequestParams = { flushCacheKeys:['key1','/url/with/data','otherkey'], service_name: 'cargo', version: 'v1', account_id: '2', ttl: true }; config.method = 'POST'; - await AlDefaultClient.post(config).then(() => { + await AlRootClient.post(config).then(() => { expect(cabinetStorage.get('key1')).equal(null); expect(cabinetStorage.get('/url/with/data')).equal(null); expect(cabinetStorage.get('otherkey')).equal(null); @@ -562,10 +562,10 @@ describe("AlDefaultClient", () => { describe('when collectRequestLog is set to true',() => { beforeEach(() => { - AlDefaultClient.collectRequestLog = true; + AlRootClient.collectRequestLog = true; }); afterEach(()=>{ - AlDefaultClient.reset(); + AlRootClient.reset(); }); it('should log the details for a PUT request', async() => { const apiRequestParams: APIRequestParams = {service_name: 'aims', version: 'v1', account_id: '2'}; @@ -574,14 +574,14 @@ describe("AlDefaultClient", () => { expect(req.method()).to.equal('PUT'); return res.status(200).body({"hello":"TinyBodyOf44bytes"}); }); - await AlDefaultClient.put(apiRequestParams).then((r) => { + await AlRootClient.put(apiRequestParams).then((r) => { expect(apiRequestParams.method).to.equal('PUT'); }); - expect(AlDefaultClient.getExecutionRequestLog().length).equal(1); - expect(AlDefaultClient.getExecutionRequestLog()[0].method).equal("PUT"); - expect(AlDefaultClient.getExecutionRequestLog()[0].responseContentLength).equal(44); - expect(AlDefaultClient.getExecutionRequestLog()[0].durationMs).lessThan(100); // This is a mock so should be fast. - expect(AlDefaultClient.getExecutionRequestLog()[0].url).equal("https://api.global-integration.product.dev.alertlogic.com/aims/v1/2"); + expect(AlRootClient.getExecutionRequestLog().length).equal(1); + expect(AlRootClient.getExecutionRequestLog()[0].method).equal("PUT"); + expect(AlRootClient.getExecutionRequestLog()[0].responseContentLength).equal(44); + expect(AlRootClient.getExecutionRequestLog()[0].durationMs).lessThan(100); // This is a mock so should be fast. + expect(AlRootClient.getExecutionRequestLog()[0].url).equal("https://api.global-integration.product.dev.alertlogic.com/aims/v1/2"); }); it('should log the details for a GET request', async () => { // Here we mock out a second response from back end... @@ -590,13 +590,13 @@ describe("AlDefaultClient", () => { headers: {'Content-Length':'24'}, body: "lot of users", })); - let response = await AlDefaultClient.get({ service_name: 'aims', version: 'v1', account_id: '2', path: 'users'}); + let response = await AlRootClient.get({ service_name: 'aims', version: 'v1', account_id: '2', path: 'users'}); expect(response).to.equals("lot of users"); // Response body should not be affected. - expect(AlDefaultClient.getExecutionRequestLog().length).equal(1); - expect(AlDefaultClient.getExecutionRequestLog()[0].method).equal("GET"); - expect(AlDefaultClient.getExecutionRequestLog()[0].responseContentLength).equal(24); - expect(AlDefaultClient.getExecutionRequestLog()[0].durationMs).lessThan(100); // This is a mock so should be fast. - expect(AlDefaultClient.getExecutionRequestLog()[0].url).equal("https://api.global-integration.product.dev.alertlogic.com/aims/v1/2/users"); + expect(AlRootClient.getExecutionRequestLog().length).equal(1); + expect(AlRootClient.getExecutionRequestLog()[0].method).equal("GET"); + expect(AlRootClient.getExecutionRequestLog()[0].responseContentLength).equal(24); + expect(AlRootClient.getExecutionRequestLog()[0].durationMs).lessThan(100); // This is a mock so should be fast. + expect(AlRootClient.getExecutionRequestLog()[0].url).equal("https://api.global-integration.product.dev.alertlogic.com/aims/v1/2/users"); }); it('should should log the details for a POST request', async() => { const apiRequestParams: APIRequestParams = {service_name: 'aims', version: 'v1', account_id: '2'}; @@ -605,15 +605,15 @@ describe("AlDefaultClient", () => { expect(req.method()).to.equal('POST'); return res.status(200).body({"body":"This is the body of the post"}); }); - await AlDefaultClient.form(apiRequestParams).then((r) => { + await AlRootClient.form(apiRequestParams).then((r) => { expect(apiRequestParams.headers['Content-Type']).to.equal('multipart/form-data'); expect(apiRequestParams.method).to.equal('POST'); }); - expect(AlDefaultClient.getExecutionRequestLog().length).equal(1); - expect(AlDefaultClient.getExecutionRequestLog()[0].method).equal("POST"); - expect(AlDefaultClient.getExecutionRequestLog()[0].responseContentLength).equal(64); - expect(AlDefaultClient.getExecutionRequestLog()[0].durationMs).lessThan(100); // This is a mock so should be fast. - expect(AlDefaultClient.getExecutionRequestLog()[0].url).equal("https://api.global-integration.product.dev.alertlogic.com/aims/v1/2"); + expect(AlRootClient.getExecutionRequestLog().length).equal(1); + expect(AlRootClient.getExecutionRequestLog()[0].method).equal("POST"); + expect(AlRootClient.getExecutionRequestLog()[0].responseContentLength).equal(64); + expect(AlRootClient.getExecutionRequestLog()[0].durationMs).lessThan(100); // This is a mock so should be fast. + expect(AlRootClient.getExecutionRequestLog()[0].url).equal("https://api.global-integration.product.dev.alertlogic.com/aims/v1/2"); }); it('should log the details for a DELETE request', async () => { const apiRequestParams: APIRequestParams = {service_name: 'aims', version: 'v1', account_id: '2'}; @@ -622,26 +622,26 @@ describe("AlDefaultClient", () => { expect(req.method()).to.equal('DELETE'); return res.status(200).body({}); }); - await AlDefaultClient.delete(apiRequestParams).then((r) => { + await AlRootClient.delete(apiRequestParams).then((r) => { expect(apiRequestParams.method).to.equal('DELETE'); }); - expect(AlDefaultClient.getExecutionRequestLog().length).equal(1); - expect(AlDefaultClient.getExecutionRequestLog()[0].method).equal("DELETE"); - expect(AlDefaultClient.getExecutionRequestLog()[0].responseContentLength).equal(0); - expect(AlDefaultClient.getExecutionRequestLog()[0].durationMs).lessThan(100); // This is a mock so should be fast. - expect(AlDefaultClient.getExecutionRequestLog()[0].url).equal("https://api.global-integration.product.dev.alertlogic.com/aims/v1/2"); + expect(AlRootClient.getExecutionRequestLog().length).equal(1); + expect(AlRootClient.getExecutionRequestLog()[0].method).equal("DELETE"); + expect(AlRootClient.getExecutionRequestLog()[0].responseContentLength).equal(0); + expect(AlRootClient.getExecutionRequestLog()[0].durationMs).lessThan(100); // This is a mock so should be fast. + expect(AlRootClient.getExecutionRequestLog()[0].url).equal("https://api.global-integration.product.dev.alertlogic.com/aims/v1/2"); }); it('should reset() clean execution log array', async () => { xhrMock.get('https://api.global-integration.product.dev.alertlogic.com/aims/v1/2/users', once({ status: 200, body: "lot of users", })); - let response = await AlDefaultClient.get({ service_name: 'aims', version: 'v1', account_id: '2', path: 'users'}); + let response = await AlRootClient.get({ service_name: 'aims', version: 'v1', account_id: '2', path: 'users'}); expect(response).to.equals("lot of users"); // Response body should not be affected. - expect(AlDefaultClient.getExecutionRequestLog().length).equal(1); + expect(AlRootClient.getExecutionRequestLog().length).equal(1); // Calling reset. - AlDefaultClient.reset(); - expect(AlDefaultClient.getExecutionRequestLog().length).equal(0); + AlRootClient.reset(); + expect(AlRootClient.getExecutionRequestLog().length).equal(0); }); it('should getExecutionSummary() return a summary of requests in the log', async () => { let apiRequestParams: APIRequestParams = {service_name: 'aims', version: 'v1', account_id: '2'}; @@ -652,18 +652,18 @@ describe("AlDefaultClient", () => { return res.status(200).body({"body":"This is the body a 256 size post"}); }); // First post. - await AlDefaultClient.form(apiRequestParams).then((r) => { + await AlRootClient.form(apiRequestParams).then((r) => { expect(apiRequestParams.headers['Content-Type']).to.equal('multipart/form-data'); expect(apiRequestParams.method).to.equal('POST'); }); // Second post. - await AlDefaultClient.form(apiRequestParams).then((r) => { + await AlRootClient.form(apiRequestParams).then((r) => { expect(apiRequestParams.headers['Content-Type']).to.equal('multipart/form-data'); expect(apiRequestParams.method).to.equal('POST'); }); - let summaryTest = AlDefaultClient.getExecutionSummary(); + let summaryTest = AlRootClient.getExecutionSummary(); // let´s validate the summary. expect(summaryTest.numberOfRequests).equal(2); expect(summaryTest.totalBytes).equal(512); diff --git a/test/error-handler/al-error-handler.spec.ts b/test/error-handler/al-error-handler.spec.ts index 28fbe7ee..8e1425c4 100644 --- a/test/error-handler/al-error-handler.spec.ts +++ b/test/error-handler/al-error-handler.spec.ts @@ -1,8 +1,8 @@ import { expect } from 'chai'; import { describe } from 'mocha'; import * as sinon from 'sinon'; -import { AlBaseError } from "../../src/common"; -import { AlErrorHandler } from '../../src/error-handler'; +import { AlBaseError } from "../../src/errors"; +import { AlErrorHandler } from '../../src/errors'; import { AxiosResponse, AxiosRequestConfig } from 'axios'; describe('AlErrorHandler', () => { diff --git a/test/session/al-session-detector.spec.ts b/test/session/al-session-detector.spec.ts index ba59d22d..5d5cf453 100644 --- a/test/session/al-session-detector.spec.ts +++ b/test/session/al-session-detector.spec.ts @@ -8,10 +8,11 @@ import { AlConduitClient, AlSessionDetector, AlLocatorService, - AIMSClient, + AlRootClient, AlSession, ConfigOption, - AlRuntimeConfiguration + AlRuntimeConfiguration, + AlsAIMS, } from '@al/core'; describe('AlSessionDetector', () => { @@ -27,7 +28,7 @@ describe('AlSessionDetector', () => { sessionDetector = new AlSessionDetector( conduit, true ); warnStub = sinon.stub( console, 'warn' ).callThrough(); errorStub = sinon.stub( console, 'error' ).callThrough(); - getTokenInfoStub = sinon.stub( AIMSClient, 'getTokenInfo' ).returns( Promise.resolve( exampleSession.authentication ) ); + getTokenInfoStub = sinon.stub( AlRootClient.getClient(AlsAIMS), 'getTokenInfo' ).returns( Promise.resolve( exampleSession.authentication ) ); sinon.stub( AlSession, "ready" ).returns( Promise.resolve() ); } ); diff --git a/test/session/al-session.spec.ts b/test/session/al-session.spec.ts index 49d1e633..c078f6fa 100644 --- a/test/session/al-session.spec.ts +++ b/test/session/al-session.spec.ts @@ -5,18 +5,18 @@ import { import { describe } from 'mocha'; import * as sinon from 'sinon'; import { - AIMSClient, AIMSAccount, AIMSSessionDescriptor, AlClientBeforeRequestEvent, - AlDefaultClient, + AlRootClient, AlDataValidationError, AlSession, AlSessionInstance, AlCabinet, - SubscriptionsClient, AlEntitlementCollection, AlRuntimeConfiguration, ConfigOption, + AlsAIMS, + AlsSubscriptions, } from "@al/core"; import { exampleActing, @@ -87,9 +87,9 @@ describe('AlSession Test Suite:', () => { let managedAccountsStub; let entitlementsStub; beforeEach( async () => { - accountDetailsStub = sinon.stub( AIMSClient, 'getAccountDetails' ).returns( Promise.resolve( actingAccount ) ); - managedAccountsStub = sinon.stub( AIMSClient, 'getManagedAccounts' ).returns( Promise.resolve( [] ) ); - entitlementsStub = sinon.stub( SubscriptionsClient, 'getEntitlements' ); + accountDetailsStub = sinon.stub( AlRootClient.getClient(AlsAIMS), 'getAccountDetails' ).returns( Promise.resolve( actingAccount ) ); + managedAccountsStub = sinon.stub( AlRootClient.getClient(AlsAIMS), 'getManagedAccounts' ).returns( Promise.resolve( [] ) ); + entitlementsStub = sinon.stub( AlRootClient.getClient(AlsSubscriptions), 'getEntitlements' ); entitlementsStub.withArgs("2").resolves( AlEntitlementCollection.fromArray( [ 'cloud_defender', 'cloud_insight' ] ) ); entitlementsStub.withArgs("5").resolves( AlEntitlementCollection.fromArray( [ 'assess', 'detect', 'respond' ] ) ); await AlSession.setAuthentication(sessionDescriptor); @@ -209,9 +209,9 @@ describe('AlSession', () => { describe("constructor", () => { let accountDetailsStub, managedAccountsStub, entitlementsStub; beforeEach( () => { - accountDetailsStub = sinon.stub( AIMSClient, 'getAccountDetails' ).returns( Promise.resolve( exampleSession.authentication.account ) ); - managedAccountsStub = sinon.stub( AIMSClient, 'getManagedAccounts' ).returns( Promise.resolve( [] ) ); - entitlementsStub = sinon.stub( SubscriptionsClient, 'getEntitlements' ).resolves( AlEntitlementCollection.fromArray( [ 'cloud_defender', 'cloud_insight' ] ) ); + accountDetailsStub = sinon.stub( AlRootClient.getClient(AlsAIMS), 'getAccountDetails' ).returns( Promise.resolve( exampleSession.authentication.account ) ); + managedAccountsStub = sinon.stub( AlRootClient.getClient(AlsAIMS), 'getManagedAccounts' ).returns( Promise.resolve( [] ) ); + entitlementsStub = sinon.stub( AlRootClient.getClient(AlsSubscriptions), 'getEntitlements' ).resolves( AlEntitlementCollection.fromArray( [ 'cloud_defender', 'cloud_insight' ] ) ); } ); afterEach( () => { sinon.restore(); @@ -369,7 +369,7 @@ describe('AlSession', () => { it( "should authenticate properly given a valid client response", async () => { let session = new AlSessionInstance(); - let clientAuthStub = sinon.stub( AlDefaultClient, 'authenticate' ).returns( Promise.resolve( exampleSession ) ); + let clientAuthStub = sinon.stub( AlRootClient, 'authenticate' ).returns( Promise.resolve( exampleSession ) ); expect( session.isActive() ).to.equal( false ); let result = await session.authenticate( "mcnielsen@alertlogic.com", "b1gB1rdL!ves!" ); @@ -382,7 +382,7 @@ describe('AlSession', () => { it( "should authenticate properly given a valid client response", async () => { let session = new AlSessionInstance(); - let clientAuthStub = sinon.stub( AlDefaultClient, 'authenticateWithMFASessionToken' ).returns( Promise.resolve( exampleSession ) ); + let clientAuthStub = sinon.stub( AlRootClient, 'authenticateWithMFASessionToken' ).returns( Promise.resolve( exampleSession ) ); expect( session.isActive() ).to.equal( false ); let result = await session.authenticateWithSessionToken( "SOME_ARBITRARY_SESSION_TOKEN", "123456" ); @@ -396,7 +396,7 @@ describe('AlSession', () => { it( "should authenticate properly given a valid client response", async () => { let session = new AlSessionInstance(); - let clientAuthStub = sinon.stub( AIMSClient, 'getTokenInfo' ).returns( Promise.resolve( exampleSession.authentication ) ); + let clientAuthStub = sinon.stub( AlRootClient.getClient(AlsAIMS), 'getTokenInfo' ).returns( Promise.resolve( exampleSession.authentication ) ); expect( session.isActive() ).to.equal( false ); let result = await session.authenticateWithAccessToken( "SOME_ARBITRARY_ACCESS_TOKEN" ); @@ -409,7 +409,7 @@ describe('AlSession', () => { describe( 'with acting account/location override', () => { it("should work", async () => { let session = new AlSessionInstance(); - let clientAuthStub = sinon.stub( AlDefaultClient, 'authenticate' ).returns( Promise.resolve( exampleSession ) ); + let clientAuthStub = sinon.stub( AlRootClient, 'authenticate' ).returns( Promise.resolve( exampleSession ) ); let fakeAccount = { id: '6710880', @@ -439,9 +439,9 @@ describe('AlSession', () => { beforeEach( () => { session = new AlSessionInstance(); - accountDetailsStub = sinon.stub( AIMSClient, 'getAccountDetails' ).returns( Promise.resolve( accountDetails ) ); - managedAccountsStub = sinon.stub( AIMSClient, 'getManagedAccounts' ).returns( Promise.resolve( managedAccounts ) ); - entitlementsStub = sinon.stub( SubscriptionsClient, 'getEntitlements' ).returns( Promise.resolve( entitlements ) ); + accountDetailsStub = sinon.stub( AlRootClient.getClient(AlsAIMS), 'getAccountDetails' ).returns( Promise.resolve( accountDetails ) ); + managedAccountsStub = sinon.stub( AlRootClient.getClient(AlsAIMS), 'getManagedAccounts' ).returns( Promise.resolve( managedAccounts ) ); + entitlementsStub = sinon.stub( AlRootClient.getClient(AlsSubscriptions), 'getEntitlements' ).returns( Promise.resolve( entitlements ) ); } ); afterEach( () => { diff --git a/test/subscriptions-client/subscriptions-client.spec.ts b/test/subscriptions-client/subscriptions-client.spec.ts index 005df965..dac3c9a2 100644 --- a/test/subscriptions-client/subscriptions-client.spec.ts +++ b/test/subscriptions-client/subscriptions-client.spec.ts @@ -4,12 +4,13 @@ import { } from 'chai'; import { describe } from 'mocha'; import * as sinon from 'sinon'; -import { SubscriptionsClient } from "@al/core"; +import { AlLocation, AlsSubscriptions, AlRootClient } from "@al/core"; const serviceName = 'subscriptions'; const accountId = '12345'; const queryParams = { foo: 'bar' }; const serviceVersion = "v1"; +const subscriptionsClient = AlRootClient.getClient( AlsSubscriptions ); afterEach(() => { sinon.restore(); @@ -18,17 +19,16 @@ describe('Subscriptions Client Test Suite:', () => { describe('when retrieving entitlements for a given account', () => { let stub: sinon.SinonSpy; beforeEach(() => { - stub = sinon.stub(SubscriptionsClient['alClient'], 'get'); + stub = sinon.stub(subscriptionsClient, 'get'); }); afterEach(() => { stub.restore(); }); // Tautological tests are empty tests xit('should call get() on the AlDefaultClient instance to the entitlements endpoint', async() => { - await SubscriptionsClient.getRawEntitlements(accountId, queryParams); + await subscriptionsClient.getRawEntitlements(accountId, queryParams); expect(stub.callCount).to.equal(1); const payload = { - service_name: serviceName, account_id: accountId, path: '/entitlements', params: queryParams, @@ -39,17 +39,16 @@ describe('Subscriptions Client Test Suite:', () => { describe('when retrieving accounts for a given enitlement', () => { let stub: sinon.SinonSpy; beforeEach(() => { - stub = sinon.stub(SubscriptionsClient['alClient'], 'get'); + stub = sinon.stub(subscriptionsClient, 'get'); }); afterEach(() => { stub.restore(); }); xit('should call get() on the AlDefaultClient instance to the entitlements endpoint', async() => { const productFamily = 'log_manager'; - await SubscriptionsClient.getAccountsByEntitlement(accountId, productFamily); + await subscriptionsClient.getAccountsByEntitlement(accountId, productFamily); expect(stub.callCount).to.equal(1); const payload = { - service_name: serviceName, account_id: accountId, path: `/entitlements/${productFamily}`, }; @@ -59,7 +58,7 @@ describe('Subscriptions Client Test Suite:', () => { describe('when creating an AWS subscription', () => { let stub: sinon.SinonSpy; beforeEach(() => { - stub = sinon.stub(SubscriptionsClient['alClient'], 'post'); + stub = sinon.stub(subscriptionsClient, 'post'); }); afterEach(() => { stub.restore(); @@ -70,11 +69,10 @@ describe('Subscriptions Client Test Suite:', () => { aws_customer_identifier:'7vBT7cnzEYf', status:'subscribe-success', }; - await SubscriptionsClient.createAWSSubscription(accountId, subscription); + await subscriptionsClient.createAWSSubscription(accountId, subscription); expect(stub.callCount).to.equal(1); const payload = { - service_name: serviceName, - version: serviceVersion, + service_stack: AlLocation.InsightAPI, account_id: accountId, path: '/subscription/aws', data: subscription, @@ -85,7 +83,7 @@ describe('Subscriptions Client Test Suite:', () => { describe('when creating a full subscription', () => { let stub: sinon.SinonSpy; beforeEach(() => { - stub = sinon.stub(SubscriptionsClient['alClient'], 'post'); + stub = sinon.stub(subscriptionsClient, 'post'); }); afterEach(() => { stub.restore(); @@ -100,11 +98,9 @@ describe('Subscriptions Client Test Suite:', () => { active: true, type: 'manual', }; - await SubscriptionsClient.createFullSubscription(accountId, entitlements); + await subscriptionsClient.createFullSubscription(accountId, entitlements); expect(stub.callCount).to.equal(1); const payload = { - service_name: serviceName, - version: serviceVersion, account_id: accountId, path: '/subscription', data: subscriptionData, @@ -115,17 +111,15 @@ describe('Subscriptions Client Test Suite:', () => { describe('when creating a standard subscription', () => { let stub: sinon.SinonSpy; beforeEach(() => { - stub = sinon.stub(SubscriptionsClient['alClient'], 'post'); + stub = sinon.stub(subscriptionsClient, 'post'); }); afterEach(() => { stub.restore(); }); it('should call post() on the AlDefaultClient instance to the standard subscription endpoint', async() => { - await SubscriptionsClient.createStandardSubscription(accountId); + await subscriptionsClient.createStandardSubscription(accountId); expect(stub.callCount).to.equal(1); const payload = { - service_name: serviceName, - version: serviceVersion, account_id: accountId, path: '/subscription/sync/standard', }; @@ -135,18 +129,16 @@ describe('Subscriptions Client Test Suite:', () => { describe('when retrieving a single subscription', () => { let stub: sinon.SinonSpy; beforeEach(() => { - stub = sinon.stub(SubscriptionsClient['alClient'], 'get'); + stub = sinon.stub(subscriptionsClient, 'get'); }); afterEach(() => { stub.restore(); }); it('should call get() on the AlDefaultClient instance to the subscription endpoint for the supplied subscription ID', async() => { const subscriptionId = '123-ABC=-?!'; - await SubscriptionsClient.getSubscription(accountId, subscriptionId); + await subscriptionsClient.getSubscription(accountId, subscriptionId); expect(stub.callCount).to.equal(1); const payload = { - service_name: serviceName, - version: serviceVersion, account_id: accountId, path: `/subscription/${subscriptionId}`, }; @@ -156,17 +148,15 @@ describe('Subscriptions Client Test Suite:', () => { describe('when retrieving all subscriptions', () => { let stub: sinon.SinonSpy; beforeEach(() => { - stub = sinon.stub(SubscriptionsClient['alClient'], 'get'); + stub = sinon.stub(subscriptionsClient, 'get'); }); afterEach(() => { stub.restore(); }); it('should call get() on the AlDefaultClient instance to the subscriptions endpoint for the supplied subscription ID', async() => { - await SubscriptionsClient.getSubscriptions(accountId); + await subscriptionsClient.getSubscriptions(accountId); expect(stub.callCount).to.equal(1); const payload = { - service_name: serviceName, - version: serviceVersion, account_id: accountId, path: '/subscriptions', }; @@ -176,7 +166,7 @@ describe('Subscriptions Client Test Suite:', () => { describe('when retrieving all subscriptions', () => { let stub: sinon.SinonSpy; beforeEach(() => { - stub = sinon.stub(SubscriptionsClient['alClient'], 'put'); + stub = sinon.stub(subscriptionsClient, 'put'); }); afterEach(() => { stub.restore(); @@ -186,11 +176,9 @@ describe('Subscriptions Client Test Suite:', () => { product_code:'ebbgj0o0g5cwo4**********', status:'unsubscribe-success', }; - await SubscriptionsClient.updateAWSSubscription(accountId, subscription); + await subscriptionsClient.updateAWSSubscription(accountId, subscription); expect(stub.callCount).to.equal(1); const payload = { - service_name: serviceName, - version: serviceVersion, account_id: accountId, path: '/subscription/aws', data: subscription, diff --git a/tsconfig.json b/tsconfig.json index e0c0576f..81a12fe7 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -18,6 +18,7 @@ "moduleResolution" : "node", "noImplicitAny" : false, "noUnusedLocals" : false, + "noEmitHelpers" : true, "outDir" : "./dist/commonjs", "sourceMap" : true, "strict" : true,