From 5d721b807e1969c1eb767a6d241ff1d8381e146e Mon Sep 17 00:00:00 2001 From: Kevin Nielsen Date: Thu, 25 Aug 2022 15:39:01 -0700 Subject: [PATCH] ENG-0000 - Refresh - Updated typescript to 4.7.x - Updated other packages to corresponding latest version - AlApiClient renamed to AlXHRAdapter for accuracy - AlDefaultClient renamed to AlRootClient (again, for accuracy) - Added @ServiceClient decorator and AlBaseServiceClient, allowing JIT service instantiation and better tree shaking - Updated AIMSClient and SubscriptionsClient to use new client model - Retired some obsolete content Client Architecture: Previously, our API Client architecture has consisted of declaring the client class and then immediately instantiating it as a global variable. In practice, this means that clients a) cannot be tree shaken or bundled outside of the main bundle, and b) every client must by compiled and instantiated before application bootstrap. This is dumb. The new model uses a decorator to identify classes that represent a client. The decorator stores the class's constructor and some default settings for it into a dictionary, which can be used to instantiate the client on-demand. For example: ``` @ServiceClient( { service_name: "gestalt", service_stack: AlLocation.GestaltAPI, version: 1 } ) export class AlsGestalt extends AlBaseServiceClient { ... } ``` Or ``` @ServiceClient( { service_name: "iris", version: 'v3', residencyAware: true } ) export class AlsIris extends AlBaseServiceClient { ... } ``` These classes do not need to be instantiated until they are actually needed. Additional, the properties provided to the ServiceClient decorator as used as defaults, and the AlBaseServiceClient provides convenience `get`, `put`, `post`, `delete`, and `request` methods to facilitate extremely minimal implementations. Nomenclature: Client classes should begin with an "Als" prefix, and be stored with a .service-client.ts extension. --- package-lock.json | 1278 +++++++++++------ package.json | 17 +- src/aims-client/aims-client.ts | 878 ----------- src/aims-client/index.ts | 2 - src/{aims-client => client/aims}/README.md | 0 .../aims}/aims.schematics.ts | 0 src/client/aims/aims.service-client.ts | 702 +++++++++ src/client/aims/index.ts | 2 + .../aims}/types/index.ts | 0 .../aims}/types/types.ts | 3 +- .../{al-api-client.ts => al-xhr-adapter.ts} | 81 +- src/client/index.ts | 11 +- .../subscriptions}/README.md | 0 src/client/subscriptions/index.ts | 2 + .../subscriptions.service-client.ts} | 67 +- .../types/al-subscription.types.ts | 0 .../subscriptions}/types/index.ts | 0 src/client/types/al-base.service-client.ts | 47 + src/client/types/api-definition.types.ts | 26 +- src/client/types/index.ts | 1 + src/common/cardstack/al-cardstack-view.ts | 8 +- src/common/errors/al-error.types.ts.backup | 180 --- src/common/index.ts | 1 - src/common/utility/al-merge-helper.ts | 79 - src/common/utility/al-trigger.types.ts | 4 +- src/common/utility/al-validation.types.ts | 2 +- src/common/utility/error-utilities.ts | 15 - src/common/utility/index.ts | 1 - .../al-error-handler.ts | 18 +- src/{error-handler => errors}/index.ts | 1 + .../errors => errors/types}/al-error.types.ts | 19 +- src/{common/errors => errors/types}/index.ts | 0 src/index.ts | 4 +- src/session/al-session.ts | 56 +- src/session/events/events.ts | 4 +- src/session/null-session.ts | 2 +- src/session/types/types.ts | 4 +- .../utilities/al-authentication.utility.ts | 2 +- src/session/utilities/al-conduit-client.ts | 2 +- src/session/utilities/al-session-detector.ts | 14 +- src/subscriptions-client/index.ts | 2 - test/aims-client/aims-client.spec.ts | 160 +-- test/client/al-api-client.spec.ts | 188 +-- test/error-handler/al-error-handler.spec.ts | 4 +- test/session/al-session-detector.spec.ts | 7 +- test/session/al-session.spec.ts | 32 +- .../subscriptions-client.spec.ts | 50 +- tsconfig.json | 1 + 48 files changed, 1948 insertions(+), 2029 deletions(-) delete mode 100644 src/aims-client/aims-client.ts delete mode 100644 src/aims-client/index.ts rename src/{aims-client => client/aims}/README.md (100%) rename src/{aims-client => client/aims}/aims.schematics.ts (100%) create mode 100644 src/client/aims/aims.service-client.ts create mode 100644 src/client/aims/index.ts rename src/{aims-client => client/aims}/types/index.ts (100%) rename src/{aims-client => client/aims}/types/types.ts (97%) rename src/client/{al-api-client.ts => al-xhr-adapter.ts} (93%) rename src/{subscriptions-client => client/subscriptions}/README.md (100%) create mode 100644 src/client/subscriptions/index.ts rename src/{subscriptions-client/subscriptions-client.ts => client/subscriptions/subscriptions.service-client.ts} (73%) rename src/{subscriptions-client => client/subscriptions}/types/al-subscription.types.ts (100%) rename src/{subscriptions-client => client/subscriptions}/types/index.ts (100%) create mode 100644 src/client/types/al-base.service-client.ts delete mode 100644 src/common/errors/al-error.types.ts.backup delete mode 100644 src/common/utility/al-merge-helper.ts delete mode 100644 src/common/utility/error-utilities.ts rename src/{error-handler => errors}/al-error-handler.ts (81%) rename src/{error-handler => errors}/index.ts (67%) rename src/{common/errors => errors/types}/al-error.types.ts (89%) rename src/{common/errors => errors/types}/index.ts (100%) delete mode 100644 src/subscriptions-client/index.ts 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,