diff --git a/.builder/actions/crt_size_check.py b/.builder/actions/crt_size_check.py index 8811e7b7c..b9c363a42 100644 --- a/.builder/actions/crt_size_check.py +++ b/.builder/actions/crt_size_check.py @@ -11,7 +11,7 @@ def run(self, env): # Maximum package size (for current platform) in bytes # NOTE: if you increase this, you might also need to increase the # limit in continuous-delivery/pack.sh - max_size = 7_750_000 + max_size = 8_000_000 # size of current folder folder_size = 0 # total size in bytes diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index fdf306552..d0ce72ae3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -7,7 +7,7 @@ on: - 'docs' env: - BUILDER_VERSION: v0.9.56 + BUILDER_VERSION: v0.9.62 BUILDER_SOURCE: releases BUILDER_HOST: https://d19elf31gohf1l.cloudfront.net PACKAGE_NAME: aws-crt-nodejs @@ -129,8 +129,21 @@ jobs: cd aws-crt-nodejs node ./scripts/build --target-arch ia32 -DAWS_WARNINGS_ARE_ERRORS=ON - osx: - runs-on: macos-12 # latest + macos: + runs-on: macos-14 # latest + steps: + - name: Build ${{ env.PACKAGE_NAME }} + consumers + run: | + python3 -c "from urllib.request import urlretrieve; urlretrieve('${{ env.BUILDER_HOST }}/${{ env.BUILDER_SOURCE }}/${{ env.BUILDER_VERSION }}/builder.pyz?run=${{ env.RUN }}', 'builder')" + chmod a+x builder + ./builder build -p ${{ env.PACKAGE_NAME }} --spec=downstream + - name: Check backward compatibility for Macos + run: | + cd aws-crt-nodejs + python3 codebuild/macos_compatibility_check.py arm64 + + macos-x64: + runs-on: macos-14-large # latest steps: - name: Build ${{ env.PACKAGE_NAME }} + consumers run: | diff --git a/CMakeLists.txt b/CMakeLists.txt index 45638ba0a..30224fa1b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -43,11 +43,17 @@ if (BUILD_DEPS) add_subdirectory(crt/aws-c-common) if (UNIX AND NOT APPLE) - set(SEARCH_LIBCRYPTO OFF) - set(DISABLE_GO ON) - set(DISABLE_PERL ON) - set(BUILD_LIBSSL OFF) - add_subdirectory(crt/aws-lc) + include(AwsPrebuildDependency) + # s2n-tls uses libcrypto during its configuration, so we need to prebuild aws-lc. + prebuild_dependency( + DEPENDENCY_NAME AWSLC + SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/crt/aws-lc + CMAKE_ARGUMENTS + -DDISABLE_GO=ON + -DDISABLE_PERL=ON + -DBUILD_LIBSSL=OFF + -DBUILD_TESTING=OFF + ) set(UNSAFE_TREAT_WARNINGS_AS_ERRORS OFF) add_subdirectory(crt/s2n) endif() diff --git a/builder.json b/builder.json index f3e23eb54..eb51f0a2a 100644 --- a/builder.json +++ b/builder.json @@ -66,6 +66,14 @@ "al2012": { "!packages": [], "!imports": [ "node-14" ] + }, + "macos": { + "architectures": { + "arm64": { + "_comment": "Mac OS (arm64) has only experimental support for Node v15 and earlier, so stick to Node v16, see Node v15 docs: https://github.com/nodejs/node/blob/v15.x/BUILDING.md#platform-list", + "!imports": [ "node-16" ] + } + } } }, "targets": { diff --git a/continuous-delivery/pack.sh b/continuous-delivery/pack.sh index 5512dd64b..15e1fb5e3 100644 --- a/continuous-delivery/pack.sh +++ b/continuous-delivery/pack.sh @@ -39,7 +39,7 @@ mkdir $UNZIP tar -xf aws-crt-$CURRENT_TAG.tgz -C $UNZIP PACK_FILE_SIZE_KB=$(du -sk $UNZIP | awk '{print $1}') echo "Current package size: ${PACK_FILE_SIZE_KB}" -if expr $PACK_FILE_SIZE_KB \> "$((25000))" ; then +if expr $PACK_FILE_SIZE_KB \> "$((26000))" ; then # the package size is too large, return -1 echo "Package size is too large!" exit -1 diff --git a/continuous-delivery/pack.yml b/continuous-delivery/pack.yml index b3d021b69..4050b7e0b 100644 --- a/continuous-delivery/pack.yml +++ b/continuous-delivery/pack.yml @@ -2,7 +2,7 @@ version: 0.2 phases: install: runtime-versions: - nodejs: 10 + nodejs: 14 pre_build: commands: - cd aws-crt-nodejs diff --git a/continuous-delivery/publish.yml b/continuous-delivery/publish.yml index 1931063f9..3c2322dfd 100644 --- a/continuous-delivery/publish.yml +++ b/continuous-delivery/publish.yml @@ -2,7 +2,7 @@ version: 0.2 phases: install: runtime-versions: - nodejs: 10 + nodejs: 14 build: commands: - cd aws-crt-nodejs diff --git a/continuous-delivery/test-version-exists.yml b/continuous-delivery/test-version-exists.yml index dcb900f40..72bba9d5e 100644 --- a/continuous-delivery/test-version-exists.yml +++ b/continuous-delivery/test-version-exists.yml @@ -2,7 +2,7 @@ version: 0.2 phases: install: runtime-versions: - nodejs: 10 + nodejs: 14 build: commands: - cd aws-crt-nodejs diff --git a/crt/aws-c-auth b/crt/aws-c-auth index 6ba7a0f86..53a31bacf 160000 --- a/crt/aws-c-auth +++ b/crt/aws-c-auth @@ -1 +1 @@ -Subproject commit 6ba7a0f8688c713dfe137716dbd5be324c2315b0 +Subproject commit 53a31bacf2918e848e00b052d2e25cba0be069d9 diff --git a/crt/aws-c-cal b/crt/aws-c-cal index b52d9e8ee..77ca3aea8 160000 --- a/crt/aws-c-cal +++ b/crt/aws-c-cal @@ -1 +1 @@ -Subproject commit b52d9e8ee7af8155e6928c977ec5fde25a507ba0 +Subproject commit 77ca3aea879bc768082fe7ec715adcde8e98c332 diff --git a/crt/aws-c-common b/crt/aws-c-common index 86e9e27a2..8419fe707 160000 --- a/crt/aws-c-common +++ b/crt/aws-c-common @@ -1 +1 @@ -Subproject commit 86e9e27a23148e9468c15cae9cd23a7cbc74b542 +Subproject commit 8419fe7077778b5ca40e8822f969665bbddc226c diff --git a/crt/aws-c-compression b/crt/aws-c-compression index 99ec79ee2..ea1d421a4 160000 --- a/crt/aws-c-compression +++ b/crt/aws-c-compression @@ -1 +1 @@ -Subproject commit 99ec79ee2970f1a045d4ced1501b97ee521f2f85 +Subproject commit ea1d421a421ad83a540309a94c38d50b6a5d836b diff --git a/crt/aws-c-event-stream b/crt/aws-c-event-stream index 63d1e1021..1a70c50f7 160000 --- a/crt/aws-c-event-stream +++ b/crt/aws-c-event-stream @@ -1 +1 @@ -Subproject commit 63d1e1021b04ce3c3b1fc1895078ac85e0430b24 +Subproject commit 1a70c50f78a6e706f1f91a4ed138478271b6d9d3 diff --git a/crt/aws-c-http b/crt/aws-c-http index 6a1c157c2..d83f8d701 160000 --- a/crt/aws-c-http +++ b/crt/aws-c-http @@ -1 +1 @@ -Subproject commit 6a1c157c20640a607102738909e89561a41e91e9 +Subproject commit d83f8d70143ddce5ab4e479175fbd44ba994211b diff --git a/crt/aws-c-io b/crt/aws-c-io index bf2d72230..878b4fa02 160000 --- a/crt/aws-c-io +++ b/crt/aws-c-io @@ -1 +1 @@ -Subproject commit bf2d72230727f02eddb5b16c4e6c5ac5a3f203a7 +Subproject commit 878b4fa027bda4041493f06e0562d5e98bb3deb8 diff --git a/crt/aws-c-mqtt b/crt/aws-c-mqtt index db285e39f..551df5536 160000 --- a/crt/aws-c-mqtt +++ b/crt/aws-c-mqtt @@ -1 +1 @@ -Subproject commit db285e39f4f0d6f9903644f08e4cd7aceddadca6 +Subproject commit 551df55369faad7dec852f538089f0e385d569a9 diff --git a/crt/aws-c-sdkutils b/crt/aws-c-sdkutils index fd8c0ba2e..8c7af71f9 160000 --- a/crt/aws-c-sdkutils +++ b/crt/aws-c-sdkutils @@ -1 +1 @@ -Subproject commit fd8c0ba2e233997eaaefe82fb818b8b444b956d3 +Subproject commit 8c7af71f91ed5b9d2a043d51f120495f43723f80 diff --git a/crt/aws-checksums b/crt/aws-checksums index 321b80555..aac442a2d 160000 --- a/crt/aws-checksums +++ b/crt/aws-checksums @@ -1 +1 @@ -Subproject commit 321b805559c8e911be5bddba13fcbd222a3e2d3a +Subproject commit aac442a2dbbb5e72d0a3eca8313cf65e7e1cac2f diff --git a/crt/aws-lc b/crt/aws-lc index dc4e28145..4e54dd836 160000 --- a/crt/aws-lc +++ b/crt/aws-lc @@ -1 +1 @@ -Subproject commit dc4e28145ceb6d46b5475e833f2da8def6d583fe +Subproject commit 4e54dd8363396f257d7a2317c48101e18170e6fb diff --git a/crt/s2n b/crt/s2n index 171c96a23..114ccab0f 160000 --- a/crt/s2n +++ b/crt/s2n @@ -1 +1 @@ -Subproject commit 171c96a232eb2bf45415340378b55b3bb6dd29cd +Subproject commit 114ccab0ff2cde491203ac841837d0d39b767412 diff --git a/lib/browser/io.ts b/lib/browser/io.ts index cf120279f..1ce2939f7 100644 --- a/lib/browser/io.ts +++ b/lib/browser/io.ts @@ -19,8 +19,10 @@ * @mergeTarget */ -export { TlsVersion, SocketType, SocketDomain } from "../common/io"; -import { SocketType, SocketDomain } from "../common/io"; +import { setLogLevel, LogLevel, SocketType, SocketDomain } from "../common/io"; +// Do not re-export the logging functions in common; they are package-private +export { setLogLevel, LogLevel, TlsVersion, SocketType, SocketDomain } from "../common/io"; + /** * @return false, as ALPN is not configurable from the browser @@ -112,3 +114,7 @@ export class SocketOptions { public keep_alive_max_failed_probes = 0) { } } + +export function enable_logging(level: LogLevel) { + setLogLevel(level); +} diff --git a/lib/browser/mqtt_request_response/protocol_adapter.spec.ts b/lib/browser/mqtt_request_response/protocol_adapter.spec.ts index 55797c1e9..70e4a9188 100644 --- a/lib/browser/mqtt_request_response/protocol_adapter.spec.ts +++ b/lib/browser/mqtt_request_response/protocol_adapter.spec.ts @@ -27,12 +27,22 @@ interface TestingOptions { builder_mutator311?: (builder: aws_iot_mqtt311.AwsIotMqttConnectionConfigBuilder) => aws_iot_mqtt311.AwsIotMqttConnectionConfigBuilder, } -function build_protocol_client_mqtt5(builder_mutator?: (builder: aws_iot_mqtt5.AwsIotMqtt5ClientConfigBuilder) => aws_iot_mqtt5.AwsIotMqtt5ClientConfigBuilder) : mqtt5.Mqtt5Client { - let provider: auth.StaticCredentialProvider = new auth.StaticCredentialProvider({ +function getTestingCredentials() : auth.AWSCredentials { + let credentials : auth.AWSCredentials = { aws_access_id: test_utils.ClientEnvironmentalConfig.AWS_IOT_ACCESS_KEY_ID, aws_secret_key: test_utils.ClientEnvironmentalConfig.AWS_IOT_SECRET_ACCESS_KEY, aws_region: "us-east-1" - }); + }; + + if (test_utils.ClientEnvironmentalConfig.AWS_IOT_SESSION_TOKEN !== "") { + credentials.aws_sts_token = test_utils.ClientEnvironmentalConfig.AWS_IOT_SESSION_TOKEN; + } + + return credentials; +} + +function build_protocol_client_mqtt5(builder_mutator?: (builder: aws_iot_mqtt5.AwsIotMqtt5ClientConfigBuilder) => aws_iot_mqtt5.AwsIotMqtt5ClientConfigBuilder) : mqtt5.Mqtt5Client { + let provider: auth.StaticCredentialProvider = new auth.StaticCredentialProvider(getTestingCredentials()); let builder = aws_iot_mqtt5.AwsIotMqtt5ClientConfigBuilder.newWebsocketMqttBuilderWithSigv4Auth( test_utils.ClientEnvironmentalConfig.AWS_IOT_HOST, @@ -56,11 +66,7 @@ function build_protocol_client_mqtt5(builder_mutator?: (builder: aws_iot_mqtt5.A } function build_protocol_client_mqtt311(builder_mutator?: (builder: aws_iot_mqtt311.AwsIotMqttConnectionConfigBuilder) => aws_iot_mqtt311.AwsIotMqttConnectionConfigBuilder) : mqtt311.MqttClientConnection { - let provider: auth.StaticCredentialProvider = new auth.StaticCredentialProvider({ - aws_access_id: test_utils.ClientEnvironmentalConfig.AWS_IOT_ACCESS_KEY_ID, - aws_secret_key: test_utils.ClientEnvironmentalConfig.AWS_IOT_SECRET_ACCESS_KEY, - aws_region: "us-east-1" - }); + let provider: auth.StaticCredentialProvider = new auth.StaticCredentialProvider(getTestingCredentials()); let builder = aws_iot_mqtt311.AwsIotMqttConnectionConfigBuilder.new_builder_for_websocket(); builder.with_credential_provider(provider); @@ -353,11 +359,11 @@ async function do_get_connection_state_test(version: ProtocolVersion) { version: version }); - expect(context.adapter.getConnectionState()).toEqual(protocol_adapter.ConnectionState.DISCONNECTED); + expect(context.adapter.getConnectionState()).toEqual(protocol_adapter.ConnectionState.Disconnected); await context.open(); - expect(context.adapter.getConnectionState()).toEqual(protocol_adapter.ConnectionState.CONNECTED); + expect(context.adapter.getConnectionState()).toEqual(protocol_adapter.ConnectionState.Connected); await context.close(); } @@ -380,7 +386,7 @@ async function do_connection_event_test(version: ProtocolVersion) { await context.open(); let connection_event1 : protocol_adapter.ConnectionStatusEvent = (await event1_promise)[0]; - expect(connection_event1.status).toEqual(protocol_adapter.ConnectionState.CONNECTED); + expect(connection_event1.status).toEqual(protocol_adapter.ConnectionState.Connected); expect(connection_event1.joinedSession).toEqual(false); let event2_promise = once(context.adapter, protocol_adapter.ProtocolClientAdapter.CONNECTION_STATUS); @@ -388,7 +394,7 @@ async function do_connection_event_test(version: ProtocolVersion) { await context.stopProtocolClient(); let connection_event2 : protocol_adapter.ConnectionStatusEvent = (await event2_promise)[0]; - expect(connection_event2.status).toEqual(protocol_adapter.ConnectionState.DISCONNECTED); + expect(connection_event2.status).toEqual(protocol_adapter.ConnectionState.Disconnected); } test_utils.conditional_test(test_utils.ClientEnvironmentalConfig.hasIoTCoreEnvironmentCred())('Protocol Adapter Connection Event Sequence - Mqtt5', async () => { diff --git a/lib/browser/mqtt_request_response/protocol_adapter.ts b/lib/browser/mqtt_request_response/protocol_adapter.ts index f0c7f46fe..8ca06643a 100644 --- a/lib/browser/mqtt_request_response/protocol_adapter.ts +++ b/lib/browser/mqtt_request_response/protocol_adapter.ts @@ -40,7 +40,8 @@ export interface SubscribeOptions { export interface SubscribeCompletionEvent { topicFilter: string, - err?: ICrtError + err?: ICrtError, + retryable?: boolean, } export type SubscribeCompletionEventListener = (event: SubscribeCompletionEvent) => void; @@ -59,9 +60,9 @@ export interface UnsubscribeCompletionEvent { export type UnsubscribeCompletionEventListener = (event: UnsubscribeCompletionEvent) => void; export enum ConnectionState { - CONNECTED = 0, - DISCONNECTED = 1, -}; + Connected = 0, + Disconnected = 1, +} export interface ConnectionStatusEvent { status: ConnectionState, @@ -86,39 +87,39 @@ export class ProtocolClientAdapter extends BufferedEventEmitter { private connectionState: ConnectionState; private connectionSuccessListener5 : mqtt5.ConnectionSuccessEventListener = (event : mqtt5.ConnectionSuccessEvent) => { - this.connectionState = ConnectionState.CONNECTED; + this.connectionState = ConnectionState.Connected; setImmediate(() => { this.emit(ProtocolClientAdapter.CONNECTION_STATUS, { - status: ConnectionState.CONNECTED, + status: ConnectionState.Connected, joinedSession: event.connack.sessionPresent, })}); }; private disconnectionListener5 : mqtt5.DisconnectionEventListener = (event : mqtt5.DisconnectionEvent) => { - this.connectionState = ConnectionState.DISCONNECTED; + this.connectionState = ConnectionState.Disconnected; setImmediate(() => { this.emit(ProtocolClientAdapter.CONNECTION_STATUS, { - status: ConnectionState.DISCONNECTED, + status: ConnectionState.Disconnected, })}); }; private connectionSuccessListener311 : mqtt311.MqttConnectionSuccess = (event : mqtt311.OnConnectionSuccessResult) => { - this.connectionState = ConnectionState.CONNECTED; + this.connectionState = ConnectionState.Connected; setImmediate(() => { this.emit(ProtocolClientAdapter.CONNECTION_STATUS, { - status: ConnectionState.CONNECTED, + status: ConnectionState.Connected, joinedSession: event.session_present, })}); }; private disconnectionListener311 : mqtt311.MqttConnectionDisconnected = () => { - this.connectionState = ConnectionState.DISCONNECTED; + this.connectionState = ConnectionState.Disconnected; setImmediate(() => { this.emit(ProtocolClientAdapter.CONNECTION_STATUS, { - status: ConnectionState.DISCONNECTED, + status: ConnectionState.Disconnected, })}); }; private constructor() { super(); - this.connectionState = ConnectionState.DISCONNECTED; + this.connectionState = ConnectionState.Disconnected; this.closed = false; } @@ -129,7 +130,7 @@ export class ProtocolClientAdapter extends BufferedEventEmitter { client.addListener(mqtt5.Mqtt5Client.CONNECTION_SUCCESS, adapter.connectionSuccessListener5); client.addListener(mqtt5.Mqtt5Client.DISCONNECTION, adapter.disconnectionListener5); - adapter.connectionState = client.isConnected() ? ConnectionState.CONNECTED : ConnectionState.DISCONNECTED; + adapter.connectionState = client.isConnected() ? ConnectionState.Connected : ConnectionState.Disconnected; return adapter; } @@ -141,7 +142,7 @@ export class ProtocolClientAdapter extends BufferedEventEmitter { client.addListener(mqtt311.MqttClientConnection.CONNECTION_SUCCESS, adapter.connectionSuccessListener311); client.addListener(mqtt311.MqttClientConnection.DISCONNECT, adapter.disconnectionListener311); - adapter.connectionState = client.is_connected() ? ConnectionState.CONNECTED : ConnectionState.DISCONNECTED; + adapter.connectionState = client.is_connected() ? ConnectionState.Connected : ConnectionState.Disconnected; return adapter; } @@ -270,8 +271,10 @@ export class ProtocolClientAdapter extends BufferedEventEmitter { topicFilter: subscribeOptions.topicFilter, }; - if (!mqtt5.isSuccessfulSubackReasonCode(suback.reasonCodes[0])) { + let reasonCode = suback.reasonCodes[0]; + if (!mqtt5.isSuccessfulSubackReasonCode(reasonCode)) { subscribeResult.err = new CrtError(ProtocolClientAdapter.FAILING_SUBACK_REASON_CODE); + subscribeResult.retryable = ProtocolClientAdapter.isSubackReasonCodeRetryable(reasonCode); } } }, @@ -279,7 +282,8 @@ export class ProtocolClientAdapter extends BufferedEventEmitter { if (!subscribeResult) { subscribeResult = { topicFilter: subscribeOptions.topicFilter, - err: err + err: err, + retryable: false }; } } @@ -294,8 +298,10 @@ export class ProtocolClientAdapter extends BufferedEventEmitter { if (response.qos >= 128) { subscribeResult.err = new CrtError(ProtocolClientAdapter.FAILING_SUBACK_REASON_CODE); + subscribeResult.retryable = true; } else if (response.error_code) { subscribeResult.err = new CrtError("Internal Error"); + subscribeResult.retryable = true; } } }, @@ -303,7 +309,8 @@ export class ProtocolClientAdapter extends BufferedEventEmitter { if (!subscribeResult) { subscribeResult = { topicFilter: subscribeOptions.topicFilter, - err: err + err: err, + retryable: false, }; } } @@ -317,7 +324,8 @@ export class ProtocolClientAdapter extends BufferedEventEmitter { if (!subscribeResult) { subscribeResult = { topicFilter: subscribeOptions.topicFilter, - err: new CrtError(ProtocolClientAdapter.OPERATION_TIMEOUT) + err: new CrtError(ProtocolClientAdapter.OPERATION_TIMEOUT), + retryable: true, }; } }, @@ -364,7 +372,7 @@ export class ProtocolClientAdapter extends BufferedEventEmitter { unsubscribeResult = { topicFilter: unsubscribeOptions.topicFilter, err: err, - retryable: false, // TODO: reevaluate if we can do anything here + retryable: false, } } } @@ -383,7 +391,7 @@ export class ProtocolClientAdapter extends BufferedEventEmitter { unsubscribeResult = { topicFilter: unsubscribeOptions.topicFilter, err: err, - retryable: false, // TODO: reevaluate + retryable: false, }; } } @@ -453,8 +461,20 @@ export class ProtocolClientAdapter extends BufferedEventEmitter { private static isUnsubackReasonCodeRetryable(reasonCode: mqtt5.UnsubackReasonCode) : boolean { switch (reasonCode) { - case mqtt5.UnsubackReasonCode.UnspecifiedError: case mqtt5.UnsubackReasonCode.ImplementationSpecificError: + case mqtt5.UnsubackReasonCode.PacketIdentifierInUse: + return true; + + default: + return false; + } + } + + private static isSubackReasonCodeRetryable(reasonCode: mqtt5.SubackReasonCode) : boolean { + switch (reasonCode) { + case mqtt5.SubackReasonCode.PacketIdentifierInUse: + case mqtt5.SubackReasonCode.ImplementationSpecificError: + case mqtt5.SubackReasonCode.QuotaExceeded: return true; default: diff --git a/lib/browser/mqtt_request_response/protocol_adapter_mock.ts b/lib/browser/mqtt_request_response/protocol_adapter_mock.ts new file mode 100644 index 000000000..5d22c8163 --- /dev/null +++ b/lib/browser/mqtt_request_response/protocol_adapter_mock.ts @@ -0,0 +1,204 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ + + +import * as protocol_adapter from "./protocol_adapter"; +import {BufferedEventEmitter} from "../../common/event"; +import {ICrtError} from "../../common/error"; +import * as subscription_manager from "./subscription_manager"; + + +export interface ProtocolAdapterApiCall { + methodName: string; + args: any; +} + +export interface MockProtocolAdapterOptions { + subscribeHandler?: (subscribeOptions: protocol_adapter.SubscribeOptions) => void, + unsubscribeHandler?: (unsubscribeOptions: protocol_adapter.UnsubscribeOptions) => void, +} + +export class MockProtocolAdapter extends BufferedEventEmitter { + + private apiCalls: Array = new Array(); + private connectionState: protocol_adapter.ConnectionState = protocol_adapter.ConnectionState.Disconnected; + + constructor(private options?: MockProtocolAdapterOptions) { + super(); + } + + // ProtocolAdapter API + close() : void { + + } + + publish(publishOptions : protocol_adapter.PublishOptions) : void { + this.apiCalls.push({ + methodName: "publish", + args: publishOptions + }); + } + + subscribe(subscribeOptions : protocol_adapter.SubscribeOptions) : void { + this.apiCalls.push({ + methodName: "subscribe", + args: subscribeOptions + }); + + if (this.options && this.options.subscribeHandler) { + this.options.subscribeHandler(subscribeOptions); + } + } + + unsubscribe(unsubscribeOptions : protocol_adapter.UnsubscribeOptions) : void { + this.apiCalls.push({ + methodName: "unsubscribe", + args: unsubscribeOptions + }); + + if (this.options && this.options.unsubscribeHandler) { + this.options.unsubscribeHandler(unsubscribeOptions); + } + } + + // Internal Testing API + connect(joinedSession?: boolean) : void { + if (this.connectionState === protocol_adapter.ConnectionState.Disconnected) { + this.connectionState = protocol_adapter.ConnectionState.Connected; + + this.emit('connectionStatus', { + status: protocol_adapter.ConnectionState.Connected, + joinedSession: joinedSession + }); + } + } + + disconnect() : void { + if (this.connectionState === protocol_adapter.ConnectionState.Connected) { + this.connectionState = protocol_adapter.ConnectionState.Disconnected; + + this.emit('connectionStatus', { + status: protocol_adapter.ConnectionState.Disconnected, + }); + } + } + + getApiCalls(): Array { + return this.apiCalls; + } + + getConnectionState() : protocol_adapter.ConnectionState { + return this.connectionState; + } + + completeSubscribe(topicFilter: string, err?: ICrtError, retryable?: boolean) : void { + let event : protocol_adapter.SubscribeCompletionEvent = { + topicFilter: topicFilter + }; + if (err !== undefined) { + event.err = err; + } + if (retryable !== undefined) { + event.retryable = retryable; + } + + this.emit(protocol_adapter.ProtocolClientAdapter.SUBSCRIBE_COMPLETION, event); + } + + completeUnsubscribe(topicFilter: string, err?: ICrtError, retryable?: boolean) : void { + let event : protocol_adapter.UnsubscribeCompletionEvent = { + topicFilter: topicFilter + }; + if (err !== undefined) { + event.err = err; + } + if (retryable !== undefined) { + event.retryable = retryable; + } + + this.emit(protocol_adapter.ProtocolClientAdapter.UNSUBSCRIBE_COMPLETION, event); + } + + // Events + on(event: 'publishCompletion', listener: protocol_adapter.PublishCompletionEventListener): this; + + on(event: 'subscribeCompletion', listener: protocol_adapter.SubscribeCompletionEventListener): this; + + on(event: 'unsubscribeCompletion', listener: protocol_adapter.UnsubscribeCompletionEventListener): this; + + on(event: 'connectionStatus', listener: protocol_adapter.ConnectionStatusEventListener): this; + + on(event: string | symbol, listener: (...args: any[]) => void): this { + super.on(event, listener); + return this; + } +} + +export interface SubscriptionManagerEvent { + type: subscription_manager.SubscriptionEventType, + data: any, +}; + +export function subscriptionManagerEventSequenceContainsEvent(eventSequence: SubscriptionManagerEvent[], expectedEvent: SubscriptionManagerEvent) : boolean { + for (let event of eventSequence) { + if (event.type !== expectedEvent.type) { + continue; + } + + if (expectedEvent.data.hasOwnProperty('operationId')) { + if (!event.data.hasOwnProperty('operationId') || expectedEvent.data.operationId !== event.data.operationId) { + continue; + } + } + + if (expectedEvent.data.hasOwnProperty('topicFilter')) { + if (!event.data.hasOwnProperty('topicFilter') || expectedEvent.data.topicFilter !== event.data.topicFilter) { + continue; + } + } + + return true; + } + + return false; +} + +export function subscriptionManagerEventSequenceContainsEvents(eventSequence: SubscriptionManagerEvent[], expectedEvents: SubscriptionManagerEvent[]) : boolean { + for (let expectedEvent of expectedEvents) { + if (!subscriptionManagerEventSequenceContainsEvent(eventSequence, expectedEvent)) { + return false; + } + } + + return true; +} + +export function protocolAdapterApiCallSequenceContainsApiCall(apiCallSequence: ProtocolAdapterApiCall[], expectedApiCall: ProtocolAdapterApiCall) : boolean { + for (let apiCall of apiCallSequence) { + if (apiCall.methodName !== expectedApiCall.methodName) { + continue; + } + + if (expectedApiCall.args.hasOwnProperty('topicFilter')) { + if (!apiCall.args.hasOwnProperty('topicFilter') || expectedApiCall.args.topicFilter !== apiCall.args.topicFilter) { + continue; + } + } + + return true; + } + + return false; +} + +export function protocolAdapterApiCallSequenceContainsApiCalls(apiCallSequence: ProtocolAdapterApiCall[], expectedApiCalls: ProtocolAdapterApiCall[]) : boolean { + for (let expectedApiCall of expectedApiCalls) { + if (!protocolAdapterApiCallSequenceContainsApiCall(apiCallSequence, expectedApiCall)) { + return false; + } + } + + return true; +} \ No newline at end of file diff --git a/lib/browser/mqtt_request_response/subscription_manager.spec.ts b/lib/browser/mqtt_request_response/subscription_manager.spec.ts new file mode 100644 index 000000000..18e4c27cd --- /dev/null +++ b/lib/browser/mqtt_request_response/subscription_manager.spec.ts @@ -0,0 +1,1967 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ + + +import * as subscription_manager from "./subscription_manager"; +import {once} from "events"; +import {newLiftedPromise} from "../../common/promise"; +import {CrtError} from "../error"; +import * as protocol_adapter_mock from "./protocol_adapter_mock"; + +jest.setTimeout(10000); + + +function createBasicSubscriptionManagerConfig() : subscription_manager.SubscriptionManagerConfig { + return { + maxRequestResponseSubscriptions: 2, + maxStreamingSubscriptions: 1, + operationTimeoutInSeconds: 30, + }; +} + +test('Subscription Manager - Acquire Subscribing Success', async () => { + let adapter = new protocol_adapter_mock.MockProtocolAdapter(); + adapter.connect(); + + // @ts-ignore + let subscriptionManager = new subscription_manager.SubscriptionManager(adapter, createBasicSubscriptionManagerConfig()); + + let filter1 = "a/b/+"; + let filter2 = "hello/world"; + let filter3 = "a/b/events"; + let expectedApiCalls : Array = new Array( + { + methodName: 'subscribe', + args: { + topicFilter: filter1, + timeoutInSeconds: 30 + } + }, + { + methodName: 'subscribe', + args: { + topicFilter: filter2, + timeoutInSeconds: 30 + } + }, + { + methodName: 'subscribe', + args: { + topicFilter: filter3, + timeoutInSeconds: 30 + } + } + ); + + let subscribeSuccessPromise1 = once(subscriptionManager, subscription_manager.SubscriptionManager.SUBSCRIBE_SUCCESS); + expect(subscriptionManager.acquireSubscription({ + operationId: 1, + type: subscription_manager.SubscriptionType.RequestResponse, + topicFilters: [filter1] + })).toEqual(subscription_manager.AcquireSubscriptionResult.Subscribing); + + adapter.completeSubscribe(filter1); + + let subscribeSuccess1 = (await subscribeSuccessPromise1)[0]; + expect(subscribeSuccess1.topicFilter).toEqual(filter1); + expect(subscribeSuccess1.operationId).toEqual(1); + + expect(adapter.getApiCalls()).toEqual(expectedApiCalls.slice(0, 1)); + + let subscribeSuccessPromise2 = once(subscriptionManager, subscription_manager.SubscriptionManager.SUBSCRIBE_SUCCESS); + expect(subscriptionManager.acquireSubscription({ + operationId: 2, + type: subscription_manager.SubscriptionType.RequestResponse, + topicFilters: [filter2] + })).toEqual(subscription_manager.AcquireSubscriptionResult.Subscribing); + + adapter.completeSubscribe(filter2); + + let subscribeSuccess2 = (await subscribeSuccessPromise2)[0]; + expect(subscribeSuccess2.topicFilter).toEqual(filter2); + expect(subscribeSuccess2.operationId).toEqual(2); + + expect(adapter.getApiCalls()).toEqual(expectedApiCalls.slice(0, 2)); + + let streamingSubscriptionEstablishedPromise = once(subscriptionManager, subscription_manager.SubscriptionManager.STREAMING_SUBSCRIPTION_ESTABLISHED); + + expect(subscriptionManager.acquireSubscription({ + operationId: 3, + type: subscription_manager.SubscriptionType.EventStream, + topicFilters: [filter3] + })).toEqual(subscription_manager.AcquireSubscriptionResult.Subscribing); + + adapter.completeSubscribe(filter3); + + let streamingSubscriptionEstablished = (await streamingSubscriptionEstablishedPromise)[0]; + expect(streamingSubscriptionEstablished.topicFilter).toEqual(filter3); + expect(streamingSubscriptionEstablished.operationId).toEqual(3); + + expect(adapter.getApiCalls()).toEqual(expectedApiCalls); +}); + +test('Subscription Manager - Acquire Multiple Subscribing Success', async () => { + let adapter = new protocol_adapter_mock.MockProtocolAdapter(); + adapter.connect(); + + // @ts-ignore + let subscriptionManager = new subscription_manager.SubscriptionManager(adapter, createBasicSubscriptionManagerConfig()); + + let filter1 = "a/b/accepted"; + let filter2 = "a/b/rejected"; + let expectedApiCalls : Array = new Array( + { + methodName: 'subscribe', + args: { + topicFilter: filter1, + timeoutInSeconds: 30 + } + }, + { + methodName: 'subscribe', + args: { + topicFilter: filter2, + timeoutInSeconds: 30 + } + }, + ); + + let allPromise = newLiftedPromise(); + let subscribeSuccesses = new Array(); + subscriptionManager.addListener(subscription_manager.SubscriptionManager.SUBSCRIBE_SUCCESS, (event) => { + subscribeSuccesses.push(event); + if (subscribeSuccesses.length == 2) { + allPromise.resolve(); + } + }); + + expect(subscriptionManager.acquireSubscription({ + operationId: 1, + type: subscription_manager.SubscriptionType.RequestResponse, + topicFilters: [filter1, filter2] + })).toEqual(subscription_manager.AcquireSubscriptionResult.Subscribing); + + adapter.completeSubscribe(filter1); + adapter.completeSubscribe(filter2); + + await allPromise.promise; + + let expectedSubscribeSuccesses = new Array( + { + topicFilter: filter1, + operationId: 1, + }, + { + topicFilter: filter2, + operationId: 1, + } + ); + expect(subscribeSuccesses).toEqual(expectedSubscribeSuccesses); + + expect(adapter.getApiCalls()).toEqual(expectedApiCalls); +}); + +test('Subscription Manager - Acquire Existing Subscribing', async () => { + let adapter = new protocol_adapter_mock.MockProtocolAdapter(); + adapter.connect(); + + // @ts-ignore + let subscriptionManager = new subscription_manager.SubscriptionManager(adapter, createBasicSubscriptionManagerConfig()); + + let filter1 = "a/b/+"; + let filter2 = "hello/world"; + let expectedApiCalls : Array = new Array( + { + methodName: 'subscribe', + args: { + topicFilter: filter1, + timeoutInSeconds: 30 + } + }, + { + methodName: 'subscribe', + args: { + topicFilter: filter2, + timeoutInSeconds: 30 + } + } + ); + + expect(subscriptionManager.acquireSubscription({ + operationId: 1, + type: subscription_manager.SubscriptionType.RequestResponse, + topicFilters: [filter1] + })).toEqual(subscription_manager.AcquireSubscriptionResult.Subscribing); + + expect(subscriptionManager.acquireSubscription({ + operationId: 2, + type: subscription_manager.SubscriptionType.EventStream, + topicFilters: [filter2] + })).toEqual(subscription_manager.AcquireSubscriptionResult.Subscribing); + + expect(adapter.getApiCalls()).toEqual(expectedApiCalls); + + expect(subscriptionManager.acquireSubscription({ + operationId: 3, + type: subscription_manager.SubscriptionType.RequestResponse, + topicFilters: [filter1] + })).toEqual(subscription_manager.AcquireSubscriptionResult.Subscribing); + + expect(subscriptionManager.acquireSubscription({ + operationId: 4, + type: subscription_manager.SubscriptionType.EventStream, + topicFilters: [filter2] + })).toEqual(subscription_manager.AcquireSubscriptionResult.Subscribing); + + expect(adapter.getApiCalls()).toEqual(expectedApiCalls); +}); + +test('Subscription Manager - Acquire Multi Existing Subscribing', async () => { + let adapter = new protocol_adapter_mock.MockProtocolAdapter(); + adapter.connect(); + + // @ts-ignore + let subscriptionManager = new subscription_manager.SubscriptionManager(adapter, createBasicSubscriptionManagerConfig()); + + let filter1 = "a/b/+"; + let filter2 = "hello/world"; + let expectedApiCalls : Array = new Array( + { + methodName: 'subscribe', + args: { + topicFilter: filter1, + timeoutInSeconds: 30 + } + }, + { + methodName: 'subscribe', + args: { + topicFilter: filter2, + timeoutInSeconds: 30 + } + } + ); + + expect(subscriptionManager.acquireSubscription({ + operationId: 1, + type: subscription_manager.SubscriptionType.RequestResponse, + topicFilters: [filter1, filter2] + })).toEqual(subscription_manager.AcquireSubscriptionResult.Subscribing); + + expect(adapter.getApiCalls()).toEqual(expectedApiCalls); + + expect(subscriptionManager.acquireSubscription({ + operationId: 2, + type: subscription_manager.SubscriptionType.RequestResponse, + topicFilters: [filter1, filter2] + })).toEqual(subscription_manager.AcquireSubscriptionResult.Subscribing); + + expect(adapter.getApiCalls()).toEqual(expectedApiCalls); +}); + +test('Subscription Manager - Acquire Multi Partially Subscribed', async () => { + let adapter = new protocol_adapter_mock.MockProtocolAdapter(); + adapter.connect(); + + // @ts-ignore + let subscriptionManager = new subscription_manager.SubscriptionManager(adapter, createBasicSubscriptionManagerConfig()); + + let filter1 = "a/b/+"; + let filter2 = "hello/world"; + let expectedApiCalls : Array = new Array( + { + methodName: 'subscribe', + args: { + topicFilter: filter1, + timeoutInSeconds: 30 + } + }, + { + methodName: 'subscribe', + args: { + topicFilter: filter2, + timeoutInSeconds: 30 + } + } + ); + + expect(subscriptionManager.acquireSubscription({ + operationId: 1, + type: subscription_manager.SubscriptionType.RequestResponse, + topicFilters: [filter1] + })).toEqual(subscription_manager.AcquireSubscriptionResult.Subscribing); + + expect(adapter.getApiCalls()).toEqual(expectedApiCalls.slice(0, 1)); + + expect(subscriptionManager.acquireSubscription({ + operationId: 2, + type: subscription_manager.SubscriptionType.RequestResponse, + topicFilters: [filter1, filter2] + })).toEqual(subscription_manager.AcquireSubscriptionResult.Subscribing); + + expect(adapter.getApiCalls()).toEqual(expectedApiCalls); +}); + +test('Subscription Manager - Acquire Subscribed Success', async () => { + let adapter = new protocol_adapter_mock.MockProtocolAdapter(); + adapter.connect(); + + // @ts-ignore + let subscriptionManager = new subscription_manager.SubscriptionManager(adapter, createBasicSubscriptionManagerConfig()); + + let filter1 = "a/b/+"; + let filter2 = "hello/world"; + let expectedApiCalls : Array = new Array( + { + methodName: 'subscribe', + args: { + topicFilter: filter1, + timeoutInSeconds: 30 + } + }, + { + methodName: 'subscribe', + args: { + topicFilter: filter2, + timeoutInSeconds: 30 + } + }, + ); + + let subscribeSuccessPromise1 = once(subscriptionManager, subscription_manager.SubscriptionManager.SUBSCRIBE_SUCCESS); + expect(subscriptionManager.acquireSubscription({ + operationId: 1, + type: subscription_manager.SubscriptionType.RequestResponse, + topicFilters: [filter1] + })).toEqual(subscription_manager.AcquireSubscriptionResult.Subscribing); + + adapter.completeSubscribe(filter1); + + let subscribeSuccess1 = (await subscribeSuccessPromise1)[0]; + expect(subscribeSuccess1.topicFilter).toEqual(filter1); + expect(subscribeSuccess1.operationId).toEqual(1); + + expect(adapter.getApiCalls()).toEqual(expectedApiCalls.slice(0, 1)); + + let streamingSubscriptionEstablishedPromise = once(subscriptionManager, subscription_manager.SubscriptionManager.STREAMING_SUBSCRIPTION_ESTABLISHED); + + expect(subscriptionManager.acquireSubscription({ + operationId: 2, + type: subscription_manager.SubscriptionType.EventStream, + topicFilters: [filter2] + })).toEqual(subscription_manager.AcquireSubscriptionResult.Subscribing); + + adapter.completeSubscribe(filter2); + + let streamingSubscriptionEstablished = (await streamingSubscriptionEstablishedPromise)[0]; + expect(streamingSubscriptionEstablished.topicFilter).toEqual(filter2); + expect(streamingSubscriptionEstablished.operationId).toEqual(2); + + expect(adapter.getApiCalls()).toEqual(expectedApiCalls); + + expect(subscriptionManager.acquireSubscription({ + operationId: 3, + type: subscription_manager.SubscriptionType.RequestResponse, + topicFilters: [filter1] + })).toEqual(subscription_manager.AcquireSubscriptionResult.Subscribed); + + expect(subscriptionManager.acquireSubscription({ + operationId: 4, + type: subscription_manager.SubscriptionType.EventStream, + topicFilters: [filter2] + })).toEqual(subscription_manager.AcquireSubscriptionResult.Subscribed); + + expect(adapter.getApiCalls()).toEqual(expectedApiCalls); +}); + +test('Subscription Manager - Acquire Multi Subscribed Success', async () => { + let adapter = new protocol_adapter_mock.MockProtocolAdapter(); + adapter.connect(); + + // @ts-ignore + let subscriptionManager = new subscription_manager.SubscriptionManager(adapter, createBasicSubscriptionManagerConfig()); + + let filter1 = "a/b/+"; + let filter2 = "hello/world"; + let expectedApiCalls : Array = new Array( + { + methodName: 'subscribe', + args: { + topicFilter: filter1, + timeoutInSeconds: 30 + } + }, + { + methodName: 'subscribe', + args: { + topicFilter: filter2, + timeoutInSeconds: 30 + } + }, + ); + + let subscribeSuccessPromise1 = once(subscriptionManager, subscription_manager.SubscriptionManager.SUBSCRIBE_SUCCESS); + expect(subscriptionManager.acquireSubscription({ + operationId: 1, + type: subscription_manager.SubscriptionType.RequestResponse, + topicFilters: [filter1] + })).toEqual(subscription_manager.AcquireSubscriptionResult.Subscribing); + + adapter.completeSubscribe(filter1); + + let subscribeSuccess1 = (await subscribeSuccessPromise1)[0]; + expect(subscribeSuccess1.topicFilter).toEqual(filter1); + expect(subscribeSuccess1.operationId).toEqual(1); + + expect(adapter.getApiCalls()).toEqual(expectedApiCalls.slice(0, 1)); + + let subscribeSuccessPromise2 = once(subscriptionManager, subscription_manager.SubscriptionManager.SUBSCRIBE_SUCCESS); + + expect(subscriptionManager.acquireSubscription({ + operationId: 2, + type: subscription_manager.SubscriptionType.RequestResponse, + topicFilters: [filter2] + })).toEqual(subscription_manager.AcquireSubscriptionResult.Subscribing); + + adapter.completeSubscribe(filter2); + + let subscribeSuccess2 = (await subscribeSuccessPromise2)[0]; + expect(subscribeSuccess2.topicFilter).toEqual(filter2); + expect(subscribeSuccess2.operationId).toEqual(2); + + expect(adapter.getApiCalls()).toEqual(expectedApiCalls); + + expect(subscriptionManager.acquireSubscription({ + operationId: 3, + type: subscription_manager.SubscriptionType.RequestResponse, + topicFilters: [filter1, filter2] + })).toEqual(subscription_manager.AcquireSubscriptionResult.Subscribed); + + expect(adapter.getApiCalls()).toEqual(expectedApiCalls); +}); + +test('Subscription Manager - Acquire Request-Response Blocked', async () => { + let adapter = new protocol_adapter_mock.MockProtocolAdapter(); + adapter.connect(); + + // @ts-ignore + let subscriptionManager = new subscription_manager.SubscriptionManager(adapter, createBasicSubscriptionManagerConfig()); + + let filter1 = "a/b/+"; + let filter2 = "hello/world"; + let filter3 = "fail/ure"; + + let expectedApiCalls : Array = new Array( + { + methodName: 'subscribe', + args: { + topicFilter: filter1, + timeoutInSeconds: 30 + } + }, + { + methodName: 'subscribe', + args: { + topicFilter: filter2, + timeoutInSeconds: 30 + } + }, + ); + + expect(subscriptionManager.acquireSubscription({ + operationId: 1, + type: subscription_manager.SubscriptionType.RequestResponse, + topicFilters: [filter1] + })).toEqual(subscription_manager.AcquireSubscriptionResult.Subscribing); + + expect(adapter.getApiCalls()).toEqual(expectedApiCalls.slice(0, 1)); + + expect(subscriptionManager.acquireSubscription({ + operationId: 2, + type: subscription_manager.SubscriptionType.RequestResponse, + topicFilters: [filter2] + })).toEqual(subscription_manager.AcquireSubscriptionResult.Subscribing); + + expect(adapter.getApiCalls()).toEqual(expectedApiCalls); + + expect(subscriptionManager.acquireSubscription({ + operationId: 3, + type: subscription_manager.SubscriptionType.RequestResponse, + topicFilters: [filter3] + })).toEqual(subscription_manager.AcquireSubscriptionResult.Blocked); + + expect(adapter.getApiCalls()).toEqual(expectedApiCalls); +}); + +test('Subscription Manager - Acquire Multi Request-Response Partial Blocked', async () => { + let adapter = new protocol_adapter_mock.MockProtocolAdapter(); + adapter.connect(); + + // @ts-ignore + let subscriptionManager = new subscription_manager.SubscriptionManager(adapter, createBasicSubscriptionManagerConfig()); + + let filter1 = "a/b/+"; + let filter2 = "hello/world"; + let filter3 = "fail/ure"; + + let expectedApiCalls : Array = new Array( + { + methodName: 'subscribe', + args: { + topicFilter: filter1, + timeoutInSeconds: 30 + } + }, + ); + + expect(subscriptionManager.acquireSubscription({ + operationId: 1, + type: subscription_manager.SubscriptionType.RequestResponse, + topicFilters: [filter1] + })).toEqual(subscription_manager.AcquireSubscriptionResult.Subscribing); + + expect(adapter.getApiCalls()).toEqual(expectedApiCalls); + + expect(subscriptionManager.acquireSubscription({ + operationId: 2, + type: subscription_manager.SubscriptionType.RequestResponse, + topicFilters: [filter2, filter3] + })).toEqual(subscription_manager.AcquireSubscriptionResult.Blocked); + + expect(adapter.getApiCalls()).toEqual(expectedApiCalls); +}); + +test('Subscription Manager - Acquire Streaming Blocked', async () => { + let adapter = new protocol_adapter_mock.MockProtocolAdapter(); + adapter.connect(); + + // @ts-ignore + let subscriptionManager = new subscription_manager.SubscriptionManager(adapter, createBasicSubscriptionManagerConfig()); + + let filter1 = "a/b/+"; + let filter2 = "hello/world"; + + let expectedApiCalls : Array = new Array( + { + methodName: 'subscribe', + args: { + topicFilter: filter1, + timeoutInSeconds: 30 + } + }, + { + methodName: 'unsubscribe', + args: { + topicFilter: filter1, + timeoutInSeconds: 30 + } + }, + ); + + let streamingSubscriptionEstablishedPromise = once(subscriptionManager, subscription_manager.SubscriptionManager.STREAMING_SUBSCRIPTION_ESTABLISHED); + + expect(subscriptionManager.acquireSubscription({ + operationId: 1, + type: subscription_manager.SubscriptionType.EventStream, + topicFilters: [filter1] + })).toEqual(subscription_manager.AcquireSubscriptionResult.Subscribing); + + adapter.completeSubscribe(filter1); + + let streamingSubscriptionEstablished = (await streamingSubscriptionEstablishedPromise)[0]; + expect(streamingSubscriptionEstablished.topicFilter).toEqual(filter1); + expect(streamingSubscriptionEstablished.operationId).toEqual(1); + + expect(adapter.getApiCalls()).toEqual(expectedApiCalls.slice(0, 1)); + + let subscriptionOrphanedPromise = once(subscriptionManager, subscription_manager.SubscriptionManager.SUBSCRIPTION_ORPHANED); + subscriptionManager.releaseSubscription({ + operationId: 1, + topicFilters: [filter1] + }); + + let subscriptionOrphaned = (await subscriptionOrphanedPromise)[0]; + expect(subscriptionOrphaned.topicFilter).toEqual(filter1); + + subscriptionManager.purge(); + + expect(adapter.getApiCalls()).toEqual(expectedApiCalls); + + expect(subscriptionManager.acquireSubscription({ + operationId: 2, + type: subscription_manager.SubscriptionType.EventStream, + topicFilters: [filter2] + })).toEqual(subscription_manager.AcquireSubscriptionResult.Blocked); + + expect(adapter.getApiCalls()).toEqual(expectedApiCalls); +}); + +test('Subscription Manager - Acquire Multi Streaming Blocked', async () => { + let adapter = new protocol_adapter_mock.MockProtocolAdapter(); + adapter.connect(); + + let config = createBasicSubscriptionManagerConfig(); + config.maxStreamingSubscriptions = 2; + + // @ts-ignore + let subscriptionManager = new subscription_manager.SubscriptionManager(adapter, config); + + let filter1 = "a/b/+"; + let filter2 = "hello/world"; + let filter3 = "foo/bar"; + + let expectedApiCalls : Array = new Array( + { + methodName: 'subscribe', + args: { + topicFilter: filter1, + timeoutInSeconds: 30 + } + }, + { + methodName: 'unsubscribe', + args: { + topicFilter: filter1, + timeoutInSeconds: 30 + } + }, + ); + + let streamingSubscriptionEstablishedPromise = once(subscriptionManager, subscription_manager.SubscriptionManager.STREAMING_SUBSCRIPTION_ESTABLISHED); + + expect(subscriptionManager.acquireSubscription({ + operationId: 1, + type: subscription_manager.SubscriptionType.EventStream, + topicFilters: [filter1] + })).toEqual(subscription_manager.AcquireSubscriptionResult.Subscribing); + + adapter.completeSubscribe(filter1); + + let streamingSubscriptionEstablished = (await streamingSubscriptionEstablishedPromise)[0]; + expect(streamingSubscriptionEstablished.topicFilter).toEqual(filter1); + expect(streamingSubscriptionEstablished.operationId).toEqual(1); + + expect(adapter.getApiCalls()).toEqual(expectedApiCalls.slice(0, 1)); + + let subscriptionOrphanedPromise = once(subscriptionManager, subscription_manager.SubscriptionManager.SUBSCRIPTION_ORPHANED); + subscriptionManager.releaseSubscription({ + operationId: 1, + topicFilters: [filter1] + }); + + let subscriptionOrphaned = (await subscriptionOrphanedPromise)[0]; + expect(subscriptionOrphaned.topicFilter).toEqual(filter1); + + subscriptionManager.purge(); + + expect(adapter.getApiCalls()).toEqual(expectedApiCalls); + + expect(subscriptionManager.acquireSubscription({ + operationId: 2, + type: subscription_manager.SubscriptionType.EventStream, + topicFilters: [filter2, filter3] + })).toEqual(subscription_manager.AcquireSubscriptionResult.Blocked); + + expect(adapter.getApiCalls()).toEqual(expectedApiCalls); +}); + +test('Subscription Manager - Acquire Streaming NoCapacity, None Allowed', async () => { + let adapter = new protocol_adapter_mock.MockProtocolAdapter(); + adapter.connect(); + + let config = createBasicSubscriptionManagerConfig(); + config.maxStreamingSubscriptions = 0; + + // @ts-ignore + let subscriptionManager = new subscription_manager.SubscriptionManager(adapter, config); + + let filter1 = "a/b/+"; + + let expectedApiCalls : Array = new Array(); + + expect(subscriptionManager.acquireSubscription({ + operationId: 1, + type: subscription_manager.SubscriptionType.EventStream, + topicFilters: [filter1] + })).toEqual(subscription_manager.AcquireSubscriptionResult.NoCapacity); + + expect(adapter.getApiCalls()).toEqual(expectedApiCalls); +}); + +test('Subscription Manager - Acquire Streaming NoCapacity, Too Many', async () => { + let adapter = new protocol_adapter_mock.MockProtocolAdapter(); + adapter.connect(); + + let config = createBasicSubscriptionManagerConfig(); + config.maxStreamingSubscriptions = 4; + + // @ts-ignore + let subscriptionManager = new subscription_manager.SubscriptionManager(adapter, config); + + for (let i = 0; i < 4; i++) { + let filter = `a/b/${i}`; + expect(subscriptionManager.acquireSubscription({ + operationId: i + 1, + type: subscription_manager.SubscriptionType.EventStream, + topicFilters: [filter] + })).toEqual(subscription_manager.AcquireSubscriptionResult.Subscribing); + } + + let filter1 = "hello/world"; + + expect(subscriptionManager.acquireSubscription({ + operationId: 1, + type: subscription_manager.SubscriptionType.EventStream, + topicFilters: [filter1] + })).toEqual(subscription_manager.AcquireSubscriptionResult.NoCapacity); +}); + +test('Subscription Manager - Acquire Multi Streaming NoCapacity', async () => { + let adapter = new protocol_adapter_mock.MockProtocolAdapter(); + adapter.connect(); + + let config = createBasicSubscriptionManagerConfig(); + config.maxStreamingSubscriptions = 2; + + // @ts-ignore + let subscriptionManager = new subscription_manager.SubscriptionManager(adapter, config); + + let filter1 = "a/b/+"; + let filter2 = "hello/world"; + let filter3 = "foo/bar"; + + let expectedApiCalls : Array = new Array( + { + methodName: 'subscribe', + args: { + topicFilter: filter1, + timeoutInSeconds: 30 + } + }, + ); + + let streamingSubscriptionEstablishedPromise = once(subscriptionManager, subscription_manager.SubscriptionManager.STREAMING_SUBSCRIPTION_ESTABLISHED); + + expect(subscriptionManager.acquireSubscription({ + operationId: 1, + type: subscription_manager.SubscriptionType.EventStream, + topicFilters: [filter1] + })).toEqual(subscription_manager.AcquireSubscriptionResult.Subscribing); + + adapter.completeSubscribe(filter1); + + let streamingSubscriptionEstablished = (await streamingSubscriptionEstablishedPromise)[0]; + expect(streamingSubscriptionEstablished.topicFilter).toEqual(filter1); + expect(streamingSubscriptionEstablished.operationId).toEqual(1); + + expect(adapter.getApiCalls()).toEqual(expectedApiCalls); + + expect(subscriptionManager.acquireSubscription({ + operationId: 2, + type: subscription_manager.SubscriptionType.EventStream, + topicFilters: [filter2, filter3] + })).toEqual(subscription_manager.AcquireSubscriptionResult.NoCapacity); + + expect(adapter.getApiCalls()).toEqual(expectedApiCalls); +}); + +test('Subscription Manager - Acquire Failure Mixed Subscription Types', async () => { + let adapter = new protocol_adapter_mock.MockProtocolAdapter(); + adapter.connect(); + + let config = createBasicSubscriptionManagerConfig(); + config.maxStreamingSubscriptions = 2; + + // @ts-ignore + let subscriptionManager = new subscription_manager.SubscriptionManager(adapter, config); + + let filter1 = "a/b/+"; + + expect(subscriptionManager.acquireSubscription({ + operationId: 1, + type: subscription_manager.SubscriptionType.RequestResponse, + topicFilters: [filter1] + })).toEqual(subscription_manager.AcquireSubscriptionResult.Subscribing); + + expect(subscriptionManager.acquireSubscription({ + operationId: 2, + type: subscription_manager.SubscriptionType.EventStream, + topicFilters: [filter1] + })).toEqual(subscription_manager.AcquireSubscriptionResult.Failure); +}); + +test('Subscription Manager - Acquire Multi Failure Mixed Subscription Types', async () => { + let adapter = new protocol_adapter_mock.MockProtocolAdapter(); + adapter.connect(); + + let config = createBasicSubscriptionManagerConfig(); + config.maxStreamingSubscriptions = 2; + + // @ts-ignore + let subscriptionManager = new subscription_manager.SubscriptionManager(adapter, config); + + let filter1 = "a/b/+"; + let filter2 = "c/d"; + + expect(subscriptionManager.acquireSubscription({ + operationId: 1, + type: subscription_manager.SubscriptionType.RequestResponse, + topicFilters: [filter1] + })).toEqual(subscription_manager.AcquireSubscriptionResult.Subscribing); + + expect(subscriptionManager.acquireSubscription({ + operationId: 2, + type: subscription_manager.SubscriptionType.EventStream, + topicFilters: [filter1, filter2] + })).toEqual(subscription_manager.AcquireSubscriptionResult.Failure); +}); + +test('Subscription Manager - Acquire Failure Poisoned', async () => { + let adapter = new protocol_adapter_mock.MockProtocolAdapter(); + adapter.connect(); + + let config = createBasicSubscriptionManagerConfig(); + config.maxStreamingSubscriptions = 2; + + // @ts-ignore + let subscriptionManager = new subscription_manager.SubscriptionManager(adapter, config); + + let filter1 = "a/b/+"; + + expect(subscriptionManager.acquireSubscription({ + operationId: 1, + type: subscription_manager.SubscriptionType.EventStream, + topicFilters: [filter1] + })).toEqual(subscription_manager.AcquireSubscriptionResult.Subscribing); + + let subscriptionHaltedPromise = once(subscriptionManager, subscription_manager.SubscriptionManager.STREAMING_SUBSCRIPTION_HALTED); + + adapter.completeSubscribe(filter1, new CrtError("Unrecoverable Error")); + + let subscriptionHalted = (await subscriptionHaltedPromise)[0]; + expect(subscriptionHalted.topicFilter).toEqual(filter1); + + expect(subscriptionManager.acquireSubscription({ + operationId: 2, + type: subscription_manager.SubscriptionType.EventStream, + topicFilters: [filter1] + })).toEqual(subscription_manager.AcquireSubscriptionResult.Failure); +}); + + + + +test('Subscription Manager - RequestResponse Multi Acquire/Release triggers Unsubscribe', async () => { + let adapter = new protocol_adapter_mock.MockProtocolAdapter(); + adapter.connect(); + + // @ts-ignore + let subscriptionManager = new subscription_manager.SubscriptionManager(adapter, createBasicSubscriptionManagerConfig()); + + let filter1 = "a/b/accepted"; + let expectedApiCalls : Array = new Array( + { + methodName: 'subscribe', + args: { + topicFilter: filter1, + timeoutInSeconds: 30 + } + }, + { + methodName: 'unsubscribe', + args: { + topicFilter: filter1, + timeoutInSeconds: 30 + } + }, + ); + + let allPromise = newLiftedPromise(); + let events = new Array(); + subscriptionManager.addListener(subscription_manager.SubscriptionManager.SUBSCRIBE_SUCCESS, (event) => { + events.push({ + type: subscription_manager.SubscriptionEventType.SubscribeSuccess, + data: event + }); + if (events.length == 2) { + allPromise.resolve(); + } + }); + + expect(subscriptionManager.acquireSubscription({ + operationId: 1, + type: subscription_manager.SubscriptionType.RequestResponse, + topicFilters: [filter1] + })).toEqual(subscription_manager.AcquireSubscriptionResult.Subscribing); + + expect(subscriptionManager.acquireSubscription({ + operationId: 2, + type: subscription_manager.SubscriptionType.RequestResponse, + topicFilters: [filter1] + })).toEqual(subscription_manager.AcquireSubscriptionResult.Subscribing); + + adapter.completeSubscribe(filter1); + + await allPromise.promise; + + let expectedSubscribeSuccesses : protocol_adapter_mock.SubscriptionManagerEvent[] = [ + { + type: subscription_manager.SubscriptionEventType.SubscribeSuccess, + data: { + topicFilter: filter1, + operationId: 1, + } + }, + { + type: subscription_manager.SubscriptionEventType.SubscribeSuccess, + data: { + topicFilter: filter1, + operationId: 2, + } + } + ]; + + expect(protocol_adapter_mock.subscriptionManagerEventSequenceContainsEvents(events, expectedSubscribeSuccesses)).toBeTruthy(); + expect(adapter.getApiCalls()).toEqual(expectedApiCalls.slice(0, 1)); + + subscriptionManager.releaseSubscription({ + operationId: 1, + topicFilters: [filter1] + }); + + subscriptionManager.purge(); + + expect(adapter.getApiCalls()).toEqual(expectedApiCalls.slice(0, 1)); + + subscriptionManager.releaseSubscription({ + operationId: 2, + topicFilters: [filter1] + }); + + expect(adapter.getApiCalls()).toEqual(expectedApiCalls.slice(0, 1)); + + subscriptionManager.purge(); + + expect(adapter.getApiCalls()).toEqual(expectedApiCalls); +}); + +test('Subscription Manager - Multi Acquire/Release Multi triggers Unsubscribes', async () => { + let adapter = new protocol_adapter_mock.MockProtocolAdapter(); + adapter.connect(); + + // @ts-ignore + let subscriptionManager = new subscription_manager.SubscriptionManager(adapter, createBasicSubscriptionManagerConfig()); + + let filter1 = "a/b/accepted"; + let filter2 = "a/b/rejected"; + let expectedSubscribes : protocol_adapter_mock.ProtocolAdapterApiCall[] = [ + { + methodName: 'subscribe', + args: { + topicFilter: filter1, + timeoutInSeconds: 30 + } + }, + { + methodName: 'subscribe', + args: { + topicFilter: filter2, + timeoutInSeconds: 30 + } + }, + ]; + + let expectedUnsubscribes : protocol_adapter_mock.ProtocolAdapterApiCall[] = [ + { + methodName: 'unsubscribe', + args: { + topicFilter: filter1, + timeoutInSeconds: 30 + } + }, + { + methodName: 'unsubscribe', + args: { + topicFilter: filter2, + timeoutInSeconds: 30 + } + }, + ]; + + let allSubscribedPromise = newLiftedPromise(); + let events = new Array(); + subscriptionManager.addListener(subscription_manager.SubscriptionManager.SUBSCRIBE_SUCCESS, (event) => { + events.push({ + type: subscription_manager.SubscriptionEventType.SubscribeSuccess, + data: event + }); + if (events.length == 4) { + allSubscribedPromise.resolve(); + } + }); + + expect(subscriptionManager.acquireSubscription({ + operationId: 1, + type: subscription_manager.SubscriptionType.RequestResponse, + topicFilters: [filter1, filter2] + })).toEqual(subscription_manager.AcquireSubscriptionResult.Subscribing); + + expect(subscriptionManager.acquireSubscription({ + operationId: 2, + type: subscription_manager.SubscriptionType.RequestResponse, + topicFilters: [filter1, filter2] + })).toEqual(subscription_manager.AcquireSubscriptionResult.Subscribing); + + adapter.completeSubscribe(filter1); + adapter.completeSubscribe(filter2); + + await allSubscribedPromise.promise; + + let expectedSubscribeSuccesses : protocol_adapter_mock.SubscriptionManagerEvent[] = [ + { + type: subscription_manager.SubscriptionEventType.SubscribeSuccess, + data: { + topicFilter: filter1, + operationId: 1, + } + }, + { + type: subscription_manager.SubscriptionEventType.SubscribeSuccess, + data: { + topicFilter: filter1, + operationId: 2, + } + }, + { + type: subscription_manager.SubscriptionEventType.SubscribeSuccess, + data: { + topicFilter: filter2, + operationId: 1, + } + }, + { + type: subscription_manager.SubscriptionEventType.SubscribeSuccess, + data: { + topicFilter: filter2, + operationId: 2, + } + }, + ]; + + expect(protocol_adapter_mock.subscriptionManagerEventSequenceContainsEvents(events, expectedSubscribeSuccesses)).toBeTruthy(); + expect(protocol_adapter_mock.protocolAdapterApiCallSequenceContainsApiCalls(adapter.getApiCalls(), expectedSubscribes)).toBeTruthy(); + + subscriptionManager.releaseSubscription({ + operationId: 1, + topicFilters: [filter1, filter2] + }); + + subscriptionManager.purge(); + + expect(protocol_adapter_mock.protocolAdapterApiCallSequenceContainsApiCalls(adapter.getApiCalls(), expectedUnsubscribes)).toBeFalsy(); + + subscriptionManager.releaseSubscription({ + operationId: 2, + topicFilters: [filter1, filter2] + }); + + expect(protocol_adapter_mock.protocolAdapterApiCallSequenceContainsApiCalls(adapter.getApiCalls(), expectedUnsubscribes)).toBeFalsy(); + + subscriptionManager.purge(); + + expect(protocol_adapter_mock.protocolAdapterApiCallSequenceContainsApiCalls(adapter.getApiCalls(), expectedUnsubscribes)).toBeTruthy(); +}); + +test('Subscription Manager - Streaming Multi Acquire/Release triggers Unsubscribe', async () => { + let adapter = new protocol_adapter_mock.MockProtocolAdapter(); + adapter.connect(); + + // @ts-ignore + let subscriptionManager = new subscription_manager.SubscriptionManager(adapter, createBasicSubscriptionManagerConfig()); + + let filter1 = "a/b/accepted"; + let expectedApiCalls : Array = new Array( + { + methodName: 'subscribe', + args: { + topicFilter: filter1, + timeoutInSeconds: 30 + } + }, + { + methodName: 'unsubscribe', + args: { + topicFilter: filter1, + timeoutInSeconds: 30 + } + }, + ); + + let allPromise = newLiftedPromise(); + let events = new Array(); + subscriptionManager.addListener(subscription_manager.SubscriptionManager.STREAMING_SUBSCRIPTION_ESTABLISHED, (event) => { + events.push({ + type: subscription_manager.SubscriptionEventType.StreamingSubscriptionEstablished, + data: event + }); + if (events.length == 2) { + allPromise.resolve(); + } + }); + + expect(subscriptionManager.acquireSubscription({ + operationId: 1, + type: subscription_manager.SubscriptionType.EventStream, + topicFilters: [filter1] + })).toEqual(subscription_manager.AcquireSubscriptionResult.Subscribing); + + expect(subscriptionManager.acquireSubscription({ + operationId: 2, + type: subscription_manager.SubscriptionType.EventStream, + topicFilters: [filter1] + })).toEqual(subscription_manager.AcquireSubscriptionResult.Subscribing); + + adapter.completeSubscribe(filter1); + + await allPromise.promise; + + let expectedStreamingSubscriptionEstablishments : protocol_adapter_mock.SubscriptionManagerEvent[] = [ + { + type: subscription_manager.SubscriptionEventType.StreamingSubscriptionEstablished, + data: { + topicFilter: filter1, + operationId: 1, + } + }, + { + type: subscription_manager.SubscriptionEventType.StreamingSubscriptionEstablished, + data: { + topicFilter: filter1, + operationId: 2, + } + } + ]; + + expect(protocol_adapter_mock.subscriptionManagerEventSequenceContainsEvents(events, expectedStreamingSubscriptionEstablishments)).toBeTruthy(); + expect(adapter.getApiCalls()).toEqual(expectedApiCalls.slice(0, 1)); + + subscriptionManager.releaseSubscription({ + operationId: 1, + topicFilters: [filter1] + }); + + subscriptionManager.purge(); + + expect(adapter.getApiCalls()).toEqual(expectedApiCalls.slice(0, 1)); + + subscriptionManager.releaseSubscription({ + operationId: 2, + topicFilters: [filter1] + }); + + expect(adapter.getApiCalls()).toEqual(expectedApiCalls.slice(0, 1)); + + subscriptionManager.purge(); + + expect(adapter.getApiCalls()).toEqual(expectedApiCalls); +}); + +async function doUnsubscribeMakesRoomTest(shouldUnsubscribeSucceed: boolean) { + let adapter = new protocol_adapter_mock.MockProtocolAdapter(); + adapter.connect(); + + // @ts-ignore + let subscriptionManager = new subscription_manager.SubscriptionManager(adapter, createBasicSubscriptionManagerConfig()); + + let filter1 = "a/b/accepted"; + let filter2 = "a/b/rejected"; + let filter3 = "hello/world"; + let expectedSubscribes : protocol_adapter_mock.ProtocolAdapterApiCall[] = [ + { + methodName: 'subscribe', + args: { + topicFilter: filter1, + timeoutInSeconds: 30 + } + }, + { + methodName: 'subscribe', + args: { + topicFilter: filter2, + timeoutInSeconds: 30 + } + }, + ]; + + let blockedSubscribe = { + methodName: 'subscribe', + args: { + topicFilter: filter3, + timeoutInSeconds: 30 + } + }; + + let expectedUnsubscribes : protocol_adapter_mock.ProtocolAdapterApiCall[] = [ + { + methodName: 'unsubscribe', + args: { + topicFilter: filter1, + timeoutInSeconds: 30 + } + }, + ]; + + let allSubscribedPromise = newLiftedPromise(); + let events = new Array(); + subscriptionManager.addListener(subscription_manager.SubscriptionManager.SUBSCRIBE_SUCCESS, (event) => { + events.push({ + type: subscription_manager.SubscriptionEventType.SubscribeSuccess, + data: event + }); + if (events.length == 2) { + allSubscribedPromise.resolve(); + } + }); + + expect(subscriptionManager.acquireSubscription({ + operationId: 1, + type: subscription_manager.SubscriptionType.RequestResponse, + topicFilters: [filter1] + })).toEqual(subscription_manager.AcquireSubscriptionResult.Subscribing); + + expect(subscriptionManager.acquireSubscription({ + operationId: 2, + type: subscription_manager.SubscriptionType.RequestResponse, + topicFilters: [filter2] + })).toEqual(subscription_manager.AcquireSubscriptionResult.Subscribing); + + expect(subscriptionManager.acquireSubscription({ + operationId: 3, + type: subscription_manager.SubscriptionType.RequestResponse, + topicFilters: [filter3] + })).toEqual(subscription_manager.AcquireSubscriptionResult.Blocked); + + adapter.completeSubscribe(filter1); + adapter.completeSubscribe(filter2); + + await allSubscribedPromise.promise; + + let expectedSubscribeSuccesses : protocol_adapter_mock.SubscriptionManagerEvent[] = [ + { + type: subscription_manager.SubscriptionEventType.SubscribeSuccess, + data: { + topicFilter: filter1, + operationId: 1, + } + }, + { + type: subscription_manager.SubscriptionEventType.SubscribeSuccess, + data: { + topicFilter: filter2, + operationId: 2, + } + }, + ]; + + expect(protocol_adapter_mock.subscriptionManagerEventSequenceContainsEvents(events, expectedSubscribeSuccesses)).toBeTruthy(); + expect(protocol_adapter_mock.protocolAdapterApiCallSequenceContainsApiCalls(adapter.getApiCalls(), expectedSubscribes)).toBeTruthy(); + + expect(subscriptionManager.acquireSubscription({ + operationId: 3, + type: subscription_manager.SubscriptionType.RequestResponse, + topicFilters: [filter3] + })).toEqual(subscription_manager.AcquireSubscriptionResult.Blocked); + + subscriptionManager.releaseSubscription({ + operationId: 1, + topicFilters: [filter1] + }); + + expect(subscriptionManager.acquireSubscription({ + operationId: 3, + type: subscription_manager.SubscriptionType.RequestResponse, + topicFilters: [filter3] + })).toEqual(subscription_manager.AcquireSubscriptionResult.Blocked); + + expect(protocol_adapter_mock.protocolAdapterApiCallSequenceContainsApiCalls(adapter.getApiCalls(), expectedUnsubscribes)).toBeFalsy(); + + subscriptionManager.purge(); + + expect(subscriptionManager.acquireSubscription({ + operationId: 3, + type: subscription_manager.SubscriptionType.RequestResponse, + topicFilters: [filter3] + })).toEqual(subscription_manager.AcquireSubscriptionResult.Blocked); + + expect(protocol_adapter_mock.protocolAdapterApiCallSequenceContainsApiCalls(adapter.getApiCalls(), expectedUnsubscribes)).toBeTruthy(); + + if (shouldUnsubscribeSucceed) { + adapter.completeUnsubscribe(filter1); + } else { + adapter.completeUnsubscribe(filter1, new CrtError("Help")); + } + + expect(protocol_adapter_mock.protocolAdapterApiCallSequenceContainsApiCall(adapter.getApiCalls(), blockedSubscribe)).toBeFalsy(); + + subscriptionManager.purge(); + + let expectedAcquireResult = shouldUnsubscribeSucceed ? subscription_manager.AcquireSubscriptionResult.Subscribing : subscription_manager.AcquireSubscriptionResult.Blocked; + expect(subscriptionManager.acquireSubscription({ + operationId: 3, + type: subscription_manager.SubscriptionType.RequestResponse, + topicFilters: [filter3] + })).toEqual(expectedAcquireResult); + + expect(protocol_adapter_mock.protocolAdapterApiCallSequenceContainsApiCall(adapter.getApiCalls(), blockedSubscribe)).toEqual(shouldUnsubscribeSucceed); +} + +test('Subscription Manager - Successful Unsubscribe Frees Subscription Space', async () => { + await doUnsubscribeMakesRoomTest(true); +}); + +test('Subscription Manager - Unsuccessful Unsubscribe Does Not Free Subscription Space', async () => { + await doUnsubscribeMakesRoomTest(false); +}); + +test('Subscription Manager - Synchronous RequestResponse Subscribe Failure causes acquire failure', async () => { + let adapter = new protocol_adapter_mock.MockProtocolAdapter({ + subscribeHandler: (subscribeOptions) => { throw new CrtError("Bad"); } + }); + adapter.connect(); + + // @ts-ignore + let subscriptionManager = new subscription_manager.SubscriptionManager(adapter, createBasicSubscriptionManagerConfig()); + + let filter1 = "a/b/+"; + let expectedApiCalls : Array = new Array( + { + methodName: 'subscribe', + args: { + topicFilter: filter1, + timeoutInSeconds: 30 + } + }, + ); + + expect(subscriptionManager.acquireSubscription({ + operationId: 1, + type: subscription_manager.SubscriptionType.RequestResponse, + topicFilters: [filter1] + })).toEqual(subscription_manager.AcquireSubscriptionResult.Failure); + + expect(adapter.getApiCalls()).toEqual(expectedApiCalls); +}); + +test('Subscription Manager - Synchronous Streaming Subscribe Failure causes acquire failure and poisons future acquires', async () => { + let attemptNumber = 0; + + let adapter = new protocol_adapter_mock.MockProtocolAdapter({ + subscribeHandler: (subscribeOptions) => { + attemptNumber++; + if (attemptNumber == 1) { + throw new CrtError("Bad"); + } + } + }); + adapter.connect(); + + // @ts-ignore + let subscriptionManager = new subscription_manager.SubscriptionManager(adapter, createBasicSubscriptionManagerConfig()); + + let filter1 = "a/b/+"; + let expectedApiCalls : Array = new Array( + { + methodName: 'subscribe', + args: { + topicFilter: filter1, + timeoutInSeconds: 30 + } + }, + ); + + expect(subscriptionManager.acquireSubscription({ + operationId: 1, + type: subscription_manager.SubscriptionType.EventStream, + topicFilters: [filter1] + })).toEqual(subscription_manager.AcquireSubscriptionResult.Failure); + + expect(adapter.getApiCalls()).toEqual(expectedApiCalls); + + subscriptionManager.purge(); + + expect(subscriptionManager.acquireSubscription({ + operationId: 2, + type: subscription_manager.SubscriptionType.EventStream, + topicFilters: [filter1] + })).toEqual(subscription_manager.AcquireSubscriptionResult.Failure); + + expect(adapter.getApiCalls()).toEqual(expectedApiCalls); +}); + +test('Subscription Manager - RequestResponse Acquire Subscribe with error emits SubscribeFailed', async () => { + let adapter = new protocol_adapter_mock.MockProtocolAdapter(); + adapter.connect(); + + // @ts-ignore + let subscriptionManager = new subscription_manager.SubscriptionManager(adapter, createBasicSubscriptionManagerConfig()); + + let filter1 = "a/b/+"; + let expectedApiCalls : Array = new Array( + { + methodName: 'subscribe', + args: { + topicFilter: filter1, + timeoutInSeconds: 30 + } + }, + ); + + expect(subscriptionManager.acquireSubscription({ + operationId: 1, + type: subscription_manager.SubscriptionType.RequestResponse, + topicFilters: [filter1] + })).toEqual(subscription_manager.AcquireSubscriptionResult.Subscribing); + + let subscribeFailedPromise = once(subscriptionManager, subscription_manager.SubscriptionManager.SUBSCRIBE_FAILURE); + adapter.completeSubscribe(filter1, new CrtError("Derp")); + + let subscribeFailed = (await subscribeFailedPromise)[0]; + expect(subscribeFailed.topicFilter).toEqual(filter1); + expect(subscribeFailed.operationId).toEqual(1); + + expect(adapter.getApiCalls()).toEqual(expectedApiCalls); +}); + +test('Subscription Manager - Streaming Acquire Subscribe with retryable error triggers resubscribe', async () => { + let adapter = new protocol_adapter_mock.MockProtocolAdapter(); + adapter.connect(); + + // @ts-ignore + let subscriptionManager = new subscription_manager.SubscriptionManager(adapter, createBasicSubscriptionManagerConfig()); + + let filter1 = "a/b/+"; + let expectedApiCalls : Array = new Array( + { + methodName: 'subscribe', + args: { + topicFilter: filter1, + timeoutInSeconds: 30 + } + }, + { + methodName: 'subscribe', + args: { + topicFilter: filter1, + timeoutInSeconds: 30 + } + }, + ); + + expect(subscriptionManager.acquireSubscription({ + operationId: 1, + type: subscription_manager.SubscriptionType.EventStream, + topicFilters: [filter1] + })).toEqual(subscription_manager.AcquireSubscriptionResult.Subscribing); + + expect(adapter.getApiCalls()).toEqual(expectedApiCalls.slice(0, 1)); + + adapter.completeSubscribe(filter1, new CrtError("Derp"), true); + + expect(adapter.getApiCalls()).toEqual(expectedApiCalls); +}); + +function getExpectedEventTypeForOfflineAcquireOnlineTest(subscriptionType: subscription_manager.SubscriptionType, shouldSubscribeSucceed: boolean) : subscription_manager.SubscriptionEventType { + if (subscriptionType == subscription_manager.SubscriptionType.RequestResponse) { + if (shouldSubscribeSucceed) { + return subscription_manager.SubscriptionEventType.SubscribeSuccess; + } else { + return subscription_manager.SubscriptionEventType.SubscribeFailure; + } + } else { + if (shouldSubscribeSucceed) { + return subscription_manager.SubscriptionEventType.StreamingSubscriptionEstablished; + } else { + return subscription_manager.SubscriptionEventType.StreamingSubscriptionHalted; + } + } +} + +async function offlineAcquireOnlineTest(subscriptionType: subscription_manager.SubscriptionType, shouldSubscribeSucceed: boolean) { + let adapter = new protocol_adapter_mock.MockProtocolAdapter(); + + // @ts-ignore + let subscriptionManager = new subscription_manager.SubscriptionManager(adapter, createBasicSubscriptionManagerConfig()); + + let filter1 = "a/b/+"; + let expectedApiCalls : Array = new Array( + { + methodName: 'subscribe', + args: { + topicFilter: filter1, + timeoutInSeconds: 30 + } + }, + ); + + expect(subscriptionManager.acquireSubscription({ + operationId: 1, + type: subscriptionType, + topicFilters: [filter1] + })).toEqual(subscription_manager.AcquireSubscriptionResult.Subscribing); + + expect(adapter.getApiCalls()).toEqual([]); + + adapter.connect(); + + expect(adapter.getApiCalls()).toEqual(expectedApiCalls); + + let anyPromise = newLiftedPromise(); + let events = new Array(); + subscriptionManager.addListener(subscription_manager.SubscriptionManager.SUBSCRIBE_SUCCESS, (event) => { + events.push({ + type: subscription_manager.SubscriptionEventType.SubscribeSuccess, + data: event + }); + anyPromise.resolve(); + }); + subscriptionManager.addListener(subscription_manager.SubscriptionManager.SUBSCRIBE_FAILURE, (event) => { + events.push({ + type: subscription_manager.SubscriptionEventType.SubscribeFailure, + data: event + }); + anyPromise.resolve(); + }); + subscriptionManager.addListener(subscription_manager.SubscriptionManager.STREAMING_SUBSCRIPTION_ESTABLISHED, (event) => { + events.push({ + type: subscription_manager.SubscriptionEventType.StreamingSubscriptionEstablished, + data: event + }); + anyPromise.resolve(); + }); + subscriptionManager.addListener(subscription_manager.SubscriptionManager.STREAMING_SUBSCRIPTION_HALTED, (event) => { + events.push({ + type: subscription_manager.SubscriptionEventType.StreamingSubscriptionHalted, + data: event + }); + anyPromise.resolve(); + }); + + if (shouldSubscribeSucceed) { + adapter.completeSubscribe(filter1); + } else { + adapter.completeSubscribe(filter1, new CrtError("Argh")); + } + + await anyPromise.promise; + + expect(events.length).toEqual(1); + let event = events[0]; + expect(event.type).toEqual(getExpectedEventTypeForOfflineAcquireOnlineTest(subscriptionType, shouldSubscribeSucceed)); + expect(event.data.topicFilter).toEqual(filter1); +} + +test('Subscription Manager - RequestResponse Acquire While Offline, Going online triggers Subscribe, Subscribe Success', async () => { + await offlineAcquireOnlineTest(subscription_manager.SubscriptionType.RequestResponse, true); +}); + +test('Subscription Manager - RequestResponse Acquire While Offline, Going online triggers Subscribe, Subscribe Failure', async () => { + await offlineAcquireOnlineTest(subscription_manager.SubscriptionType.RequestResponse, false); +}); + +test('Subscription Manager - Streaming Acquire While Offline, Going online triggers Subscribe, Subscribe Success', async () => { + await offlineAcquireOnlineTest(subscription_manager.SubscriptionType.EventStream, true); +}); + +test('Subscription Manager - Streaming Acquire While Offline, Going online triggers Subscribe, Subscribe Failure', async () => { + await offlineAcquireOnlineTest(subscription_manager.SubscriptionType.EventStream, false); +}); + +async function offlineAcquireReleaseOnlineTest(subscriptionType: subscription_manager.SubscriptionType) { + let adapter = new protocol_adapter_mock.MockProtocolAdapter(); + + // @ts-ignore + let subscriptionManager = new subscription_manager.SubscriptionManager(adapter, createBasicSubscriptionManagerConfig()); + + let filter1 = "a/b/+"; + let filter2 = "hello/world" + let expectedApiCalls : Array = new Array( + { + methodName: 'subscribe', + args: { + topicFilter: filter2, + timeoutInSeconds: 30 + } + }, + ); + + expect(subscriptionManager.acquireSubscription({ + operationId: 1, + type: subscriptionType, + topicFilters: [filter1] + })).toEqual(subscription_manager.AcquireSubscriptionResult.Subscribing); + + expect(adapter.getApiCalls()).toEqual([]); + + subscriptionManager.releaseSubscription({ + operationId: 1, + topicFilters: [filter1], + }); + + expect(adapter.getApiCalls()).toEqual([]); + + adapter.connect(); + + expect(adapter.getApiCalls()).toEqual([]); + + expect(subscriptionManager.acquireSubscription({ + operationId: 2, + type: subscriptionType, + topicFilters: [filter2] + })).toEqual(subscription_manager.AcquireSubscriptionResult.Subscribing); + + expect(adapter.getApiCalls()).toEqual(expectedApiCalls); +} + +test('Subscription Manager - RequestResponse Acquire-Release While Offline, Going online triggers nothing', async () => { + await offlineAcquireReleaseOnlineTest(subscription_manager.SubscriptionType.RequestResponse); +}); + +test('Subscription Manager - Streaming Acquire-Release While Offline, Going online triggers nothing', async () => { + await offlineAcquireReleaseOnlineTest(subscription_manager.SubscriptionType.EventStream); +}); + +async function acquireOfflineReleaseAcquireOnlineTest(subscriptionType: subscription_manager.SubscriptionType) { + let adapter = new protocol_adapter_mock.MockProtocolAdapter(); + adapter.connect(); + + let config = createBasicSubscriptionManagerConfig(); + config.maxStreamingSubscriptions = 2; + + // @ts-ignore + let subscriptionManager = new subscription_manager.SubscriptionManager(adapter, config); + + let filter1 = "a/b/+"; + let filter2 = "hello/world"; + let expectedApiCalls : Array = new Array( + { + methodName: 'subscribe', + args: { + topicFilter: filter1, + timeoutInSeconds: 30 + } + }, + { + methodName: 'subscribe', + args: { + topicFilter: filter2, + timeoutInSeconds: 30 + } + }, + { + methodName: 'unsubscribe', + args: { + topicFilter: filter1, + timeoutInSeconds: 30 + } + }, + ); + + expect(subscriptionManager.acquireSubscription({ + operationId: 1, + type: subscriptionType, + topicFilters: [filter1] + })).toEqual(subscription_manager.AcquireSubscriptionResult.Subscribing); + + expect(adapter.getApiCalls()).toEqual(expectedApiCalls.slice(0,1)); + + adapter.completeSubscribe(filter1); + + adapter.disconnect(); + + subscriptionManager.releaseSubscription({ + operationId: 1, + topicFilters: [filter1], + }); + + expect(adapter.getApiCalls()).toEqual(expectedApiCalls.slice(0,1)); + + expect(subscriptionManager.acquireSubscription({ + operationId: 2, + type: subscriptionType, + topicFilters: [filter2] + })).toEqual(subscription_manager.AcquireSubscriptionResult.Subscribing); + + expect(protocol_adapter_mock.protocolAdapterApiCallSequenceContainsApiCalls(adapter.getApiCalls(), expectedApiCalls)).toBeFalsy(); + + adapter.connect(true); + + expect(protocol_adapter_mock.protocolAdapterApiCallSequenceContainsApiCalls(adapter.getApiCalls(), expectedApiCalls)).toBeTruthy(); +} + +test('Subscription Manager - RequestResponse Release-Acquire2 while offline, Going online triggers Unsubscribe and Subscribe', async () => { + await acquireOfflineReleaseAcquireOnlineTest(subscription_manager.SubscriptionType.RequestResponse); +}); + +test('Subscription Manager - Streaming Release-Acquire2 while offline, Going online triggers Unsubscribe and Subscribe', async () => { + await acquireOfflineReleaseAcquireOnlineTest(subscription_manager.SubscriptionType.EventStream); +}); + +async function closeTest(subscriptionType: subscription_manager.SubscriptionType, completeSubscribe: boolean, closeWhileConnected: boolean) { + let adapter = new protocol_adapter_mock.MockProtocolAdapter(); + adapter.connect(); + + // @ts-ignore + let subscriptionManager = new subscription_manager.SubscriptionManager(adapter, createBasicSubscriptionManagerConfig()); + + let filter1 = "a/b/+"; + let expectedApiCalls : Array = new Array( + { + methodName: 'subscribe', + args: { + topicFilter: filter1, + timeoutInSeconds: 30 + } + }, + { + methodName: 'unsubscribe', + args: { + topicFilter: filter1, + timeoutInSeconds: 30 + } + }, + ); + + expect(subscriptionManager.acquireSubscription({ + operationId: 1, + type: subscriptionType, + topicFilters: [filter1] + })).toEqual(subscription_manager.AcquireSubscriptionResult.Subscribing); + + expect(adapter.getApiCalls()).toEqual(expectedApiCalls.slice(0,1)); + + if (completeSubscribe) { + adapter.completeSubscribe(filter1); + } + + if (!closeWhileConnected) { + adapter.disconnect(); + } + + subscriptionManager.close(); + + expect(adapter.getApiCalls()).toEqual(expectedApiCalls); +} + +test('Subscription Manager - Close while request-response subscribed and online triggers unsubscribe', async () => { + await closeTest(subscription_manager.SubscriptionType.RequestResponse, true, true); +}); + +test('Subscription Manager - Close while streaming subscribed and online triggers unsubscribe', async () => { + await closeTest(subscription_manager.SubscriptionType.EventStream, true, true); +}); + +test('Subscription Manager - Close while request-response subscribing and online triggers unsubscribe', async () => { + await closeTest(subscription_manager.SubscriptionType.RequestResponse, false, true); +}); + +test('Subscription Manager - Close while streaming subscribing and online triggers unsubscribe', async () => { + await closeTest(subscription_manager.SubscriptionType.EventStream, false, true); +}); + +test('Subscription Manager - Close while request-response subscribing and offline triggers unsubscribe', async () => { + await closeTest(subscription_manager.SubscriptionType.RequestResponse, false, false); +}); + +test('Subscription Manager - Close while streaming subscribing and offline triggers unsubscribe', async () => { + await closeTest(subscription_manager.SubscriptionType.EventStream, false, false); +}); + +async function noSessionSubscriptionEndedTest(offlineWhileUnsubscribing: boolean) { + let adapter = new protocol_adapter_mock.MockProtocolAdapter(); + adapter.connect(); + + // @ts-ignore + let subscriptionManager = new subscription_manager.SubscriptionManager(adapter, createBasicSubscriptionManagerConfig()); + + let filter1 = "a/b/+"; + let expectedApiCalls : Array = new Array( + { + methodName: 'subscribe', + args: { + topicFilter: filter1, + timeoutInSeconds: 30 + } + }, + { + methodName: 'unsubscribe', + args: { + topicFilter: filter1, + timeoutInSeconds: 30 + } + }, + ); + + expect(subscriptionManager.acquireSubscription({ + operationId: 1, + type: subscription_manager.SubscriptionType.RequestResponse, + topicFilters: [filter1] + })).toEqual(subscription_manager.AcquireSubscriptionResult.Subscribing); + + expect(adapter.getApiCalls()).toEqual(expectedApiCalls.slice(0,1)); + + adapter.completeSubscribe(filter1); + + if (offlineWhileUnsubscribing) { + subscriptionManager.releaseSubscription({ + operationId: 1, + topicFilters: [filter1] + }); + + subscriptionManager.purge(); + + expect(adapter.getApiCalls()).toEqual(expectedApiCalls); + } + + let subscriptionEndedPromise = once(subscriptionManager, subscription_manager.SubscriptionManager.SUBSCRIPTION_ENDED); + + adapter.disconnect(); + adapter.connect(); + + if (!offlineWhileUnsubscribing) { + let subscriptionEnded = (await subscriptionEndedPromise)[0]; + expect(subscriptionEnded.topicFilter).toEqual(filter1); + } + + let reaquire: subscription_manager.AcquireSubscriptionConfig = { + operationId: 2, + type: subscription_manager.SubscriptionType.RequestResponse, + topicFilters : [filter1], + }; + + if (offlineWhileUnsubscribing) { + expect(subscriptionManager.acquireSubscription(reaquire)).toEqual(subscription_manager.AcquireSubscriptionResult.Blocked); + + adapter.completeUnsubscribe(filter1, new CrtError("timeout")); + } + + expect(subscriptionManager.acquireSubscription(reaquire)).toEqual(subscription_manager.AcquireSubscriptionResult.Subscribing); +} + +test('Subscription Manager - Subscribed Session Rejoin Failure triggers subscription ended', async () => { + await noSessionSubscriptionEndedTest(false); +}); + +test('Subscription Manager - Subscribed Session Rejoin Failure while unsubscribing triggers subscription ended', async () => { + await noSessionSubscriptionEndedTest(true); +}); + +test('Subscription Manager - Subscribed Streaming Session Rejoin Failure triggers resubscribe and emits SubscriptionLost', async () => { + let adapter = new protocol_adapter_mock.MockProtocolAdapter(); + adapter.connect(); + + // @ts-ignore + let subscriptionManager = new subscription_manager.SubscriptionManager(adapter, createBasicSubscriptionManagerConfig()); + + let filter1 = "a/b/+"; + let expectedApiCalls : Array = new Array( + { + methodName: 'subscribe', + args: { + topicFilter: filter1, + timeoutInSeconds: 30 + } + }, + { + methodName: 'subscribe', + args: { + topicFilter: filter1, + timeoutInSeconds: 30 + } + }, + ); + + expect(subscriptionManager.acquireSubscription({ + operationId: 1, + type: subscription_manager.SubscriptionType.EventStream, + topicFilters: [filter1] + })).toEqual(subscription_manager.AcquireSubscriptionResult.Subscribing); + + expect(adapter.getApiCalls()).toEqual(expectedApiCalls.slice(0,1)); + + adapter.completeSubscribe(filter1); + + let subscriptionLostPromise = once(subscriptionManager, subscription_manager.SubscriptionManager.STREAMING_SUBSCRIPTION_LOST); + + adapter.disconnect(); + + expect(adapter.getApiCalls()).toEqual(expectedApiCalls.slice(0,1)); + + adapter.connect(); + + let subscriptionLost = (await subscriptionLostPromise)[0]; + expect(subscriptionLost.topicFilter).toEqual(filter1); + + expect(adapter.getApiCalls()).toEqual(expectedApiCalls); +}); + +async function doPurgeTest(subscriptionType: subscription_manager.SubscriptionType) { + let adapter = new protocol_adapter_mock.MockProtocolAdapter(); + adapter.connect(); + + // @ts-ignore + let subscriptionManager = new subscription_manager.SubscriptionManager(adapter, createBasicSubscriptionManagerConfig()); + + let filter1 = "a/b/+"; + let expectedApiCalls : Array = new Array( + { + methodName: 'subscribe', + args: { + topicFilter: filter1, + timeoutInSeconds: 30 + } + }, + { + methodName: 'unsubscribe', + args: { + topicFilter: filter1, + timeoutInSeconds: 30 + } + }, + ); + + expect(subscriptionManager.acquireSubscription({ + operationId: 1, + type: subscription_manager.SubscriptionType.EventStream, + topicFilters: [filter1] + })).toEqual(subscription_manager.AcquireSubscriptionResult.Subscribing); + + expect(adapter.getApiCalls()).toEqual(expectedApiCalls.slice(0,1)); + + adapter.completeSubscribe(filter1); + + let subscriptionOrphanedPromise = once(subscriptionManager, subscription_manager.SubscriptionManager.SUBSCRIPTION_ORPHANED); + + subscriptionManager.releaseSubscription({ + operationId: 1, + topicFilters: [filter1], + }); + + let subscriptionOrphaned = (await subscriptionOrphanedPromise)[0]; + expect(subscriptionOrphaned.topicFilter).toEqual(filter1); + + expect(adapter.getApiCalls()).toEqual(expectedApiCalls.slice(0,1)); + + subscriptionManager.purge(); + + expect(adapter.getApiCalls()).toEqual(expectedApiCalls); +} + +test('Subscription Manager - Subscribed RequestResponse emits orphaned event on release', async () => { + await doPurgeTest(subscription_manager.SubscriptionType.RequestResponse); +}); + +test('Subscription Manager - Subscribed Streaming emits orphaned event on release', async () => { + await doPurgeTest(subscription_manager.SubscriptionType.EventStream); +}); \ No newline at end of file diff --git a/lib/browser/mqtt_request_response/subscription_manager.ts b/lib/browser/mqtt_request_response/subscription_manager.ts new file mode 100644 index 000000000..2c5f0b6cb --- /dev/null +++ b/lib/browser/mqtt_request_response/subscription_manager.ts @@ -0,0 +1,636 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ + +import {BufferedEventEmitter} from "../../common/event"; +import * as protocol_adapter from "./protocol_adapter"; +import * as io from "../../common/io"; + +/** + * + * @packageDocumentation + * @module mqtt_request_response + * + */ + +// exported for tests only +export enum SubscriptionEventType { + SubscribeSuccess, + SubscribeFailure, + SubscriptionEnded, + StreamingSubscriptionEstablished, + StreamingSubscriptionLost, + StreamingSubscriptionHalted, + SubscriptionOrphaned, + UnsubscribeComplete +} + +function subscriptionEventTypeToString(eventType: SubscriptionEventType) : string { + switch (eventType) { + case SubscriptionEventType.SubscribeSuccess: + return "SubscribeSuccess"; + case SubscriptionEventType.SubscribeFailure: + return "SubscribeFailure"; + case SubscriptionEventType.SubscriptionEnded: + return "SubscriptionEnded"; + case SubscriptionEventType.StreamingSubscriptionEstablished: + return "StreamingSubscriptionEstablished"; + case SubscriptionEventType.StreamingSubscriptionLost: + return "StreamingSubscriptionLost"; + case SubscriptionEventType.StreamingSubscriptionHalted: + return "StreamingSubscriptionHalted"; + case SubscriptionEventType.SubscriptionOrphaned: + return "SubscriptionOrphaned"; + case SubscriptionEventType.UnsubscribeComplete: + return "UnsubscribeComplete"; + default: + return "Unknown"; + } +} + +export interface SubscribeSuccessEvent { + topicFilter: string, + operationId: number, +} + +export type SubscribeSuccessEventListener = (event: SubscribeSuccessEvent) => void; + +export interface SubscribeFailureEvent { + topicFilter: string, + operationId: number, +} + +export type SubscribeFailureEventListener = (event: SubscribeFailureEvent) => void; + +export interface SubscriptionEndedEvent { + topicFilter: string, + operationId: number, +} + +export type SubscriptionEndedEventListener = (event: SubscriptionEndedEvent) => void; + +export interface StreamingSubscriptionEstablishedEvent { + topicFilter: string, + operationId: number, +} + +export type StreamingSubscriptionEstablishedEventListener = (event: StreamingSubscriptionEstablishedEvent) => void; + +export interface StreamingSubscriptionLostEvent { + topicFilter: string, + operationId: number, +} + +export type StreamingSubscriptionLostEventListener = (event: StreamingSubscriptionLostEvent) => void; + +export interface StreamingSubscriptionHaltedEvent { + topicFilter: string, + operationId: number, +} + +export type StreamingSubscriptionHaltedEventListener = (event: StreamingSubscriptionHaltedEvent) => void; + +export interface SubscriptionOrphanedEvent { + topicFilter: string, +} + +export type SubscriptionOrphanedEventListener = (event: SubscriptionOrphanedEvent) => void; + +export interface UnsubscribeCompleteEvent { + topicFilter: string, +} + +export type UnsubscribeCompleteEventListener = (event: UnsubscribeCompleteEvent) => void; + +export enum SubscriptionType { + EventStream, + RequestResponse, +} + +export interface AcquireSubscriptionConfig { + topicFilters: Array, + operationId: number, + type: SubscriptionType, +} + +export interface ReleaseSubscriptionsConfig { + topicFilters: Array, + operationId: number, +} + +export enum AcquireSubscriptionResult { + Subscribed, + Subscribing, + Blocked, + NoCapacity, + Failure, +} + +export interface SubscriptionManagerConfig { + maxRequestResponseSubscriptions: number, + maxStreamingSubscriptions: number, + operationTimeoutInSeconds: number, +} + +enum SubscriptionStatus { + Subscribed, + NotSubscribed, +} + +enum SubscriptionPendingAction { + Nothing, + Subscribing, + Unsubscribing, +} + +interface SubscriptionRecord { + topicFilter: string, + listeners: Set, + status: SubscriptionStatus, + pendingAction: SubscriptionPendingAction, + type: SubscriptionType, + + /* + * A poisoned record represents a subscription that we will never try to subscribe to because a previous + * attempt resulted in a failure that we judge to be "terminal." Terminal failures include permission failures + * and validation failures. To remove a poisoned record, all listeners must be removed. For request-response + * operations this will happen naturally. For streaming operations, the operation must be closed by the user (in + * response to the user-facing event we emit on the streaming operation when the failure that poisons the + * record occurs). + */ + poisoned: boolean, +} + +interface SubscriptionStats { + requestResponseCount: number, + streamingCount: number, + unsubscribingStreamingCount: number, +} + +export class SubscriptionManager extends BufferedEventEmitter { + private static logSubject : string = "SubscriptionManager"; + + private closed: boolean = false; + private records: Map; + + constructor(private adapter: protocol_adapter.ProtocolClientAdapter, private options: SubscriptionManagerConfig) { + super(); + + this.records = new Map(); + + this.adapter.addListener(protocol_adapter.ProtocolClientAdapter.SUBSCRIBE_COMPLETION, this.handleSubscribeCompletionEvent.bind(this)); + this.adapter.addListener(protocol_adapter.ProtocolClientAdapter.UNSUBSCRIBE_COMPLETION, this.handleUnsubscribeCompletionEvent.bind(this)); + this.adapter.addListener(protocol_adapter.ProtocolClientAdapter.CONNECTION_STATUS, this.handleConnectionStatusEvent.bind(this)); + } + + close() { + this.closed = true; + + this.unsubscribeAll(); + } + + acquireSubscription(options: AcquireSubscriptionConfig) : AcquireSubscriptionResult { + if (this.closed) { + return AcquireSubscriptionResult.Failure; + } + + if (options.topicFilters.length == 0) { + return AcquireSubscriptionResult.Failure; + } + + for (let topicFilter of options.topicFilters) { + let existingRecord = this.records.get(topicFilter); + if (!existingRecord) { + continue; + } + + if (existingRecord.poisoned) { + io.logError(SubscriptionManager.logSubject, `acquire subscription for '${topicFilter}' via operation '${options.operationId}' failed - existing subscription is poisoned and has not been released`); + return AcquireSubscriptionResult.Failure; + } + if (existingRecord.type != options.type) { + io.logError(SubscriptionManager.logSubject, `acquire subscription for '${topicFilter}' via operation '${options.operationId}' failed - conflicts with subscription type of existing subscription`); + return AcquireSubscriptionResult.Failure; + } + } + + let subscriptionsNeeded : number = 0; + for (let topicFilter of options.topicFilters) { + let existingRecord = this.records.get(topicFilter); + if (existingRecord) { + if (existingRecord.pendingAction == SubscriptionPendingAction.Unsubscribing) { + io.logDebug(SubscriptionManager.logSubject, `acquire subscription for '${topicFilter}' via operation '${options.operationId}' blocked - existing subscription is unsubscribing`); + return AcquireSubscriptionResult.Blocked; + } + } else { + subscriptionsNeeded++; + } + } + + if (subscriptionsNeeded > 0) { + let stats = this.getStats(); + if (options.type == SubscriptionType.RequestResponse) { + if (subscriptionsNeeded > this.options.maxRequestResponseSubscriptions - stats.requestResponseCount) { + io.logDebug(SubscriptionManager.logSubject, `acquire subscription for request operation '${options.operationId}' blocked - insufficient room`); + return AcquireSubscriptionResult.Blocked; + } + } else { + if (subscriptionsNeeded + stats.streamingCount > this.options.maxStreamingSubscriptions) { + if (subscriptionsNeeded + stats.streamingCount <= this.options.maxStreamingSubscriptions + stats.unsubscribingStreamingCount) { + io.logDebug(SubscriptionManager.logSubject, `acquire subscription for streaming operation '${options.operationId}' blocked - insufficient room`); + return AcquireSubscriptionResult.Blocked; + } else { + io.logError(SubscriptionManager.logSubject, `acquire subscription for streaming operation '${options.operationId}' failed - insufficient room`); + return AcquireSubscriptionResult.NoCapacity; + } + } + } + } + + let isFullySubscribed = true; + for (let topicFilter of options.topicFilters) { + let existingRecord = this.records.get(topicFilter); + if (!existingRecord) { + existingRecord = { + topicFilter: topicFilter, + listeners: new Set(), + status: SubscriptionStatus.NotSubscribed, + pendingAction: SubscriptionPendingAction.Nothing, + type: options.type, + poisoned: false, + }; + + this.records.set(topicFilter, existingRecord); + } + + existingRecord.listeners.add(options.operationId); + io.logDebug(SubscriptionManager.logSubject, `added listener '${options.operationId}' to subscription '${topicFilter}', ${existingRecord.listeners.size} listeners total`); + + if (existingRecord.status != SubscriptionStatus.Subscribed) { + isFullySubscribed = false; + } + } + + if (isFullySubscribed) { + io.logDebug(SubscriptionManager.logSubject, `acquire subscription for operation '${options.operationId}' fully subscribed - all required subscriptions are active`); + return AcquireSubscriptionResult.Subscribed; + } + + for (let topicFilter of options.topicFilters) { + let existingRecord = this.records.get(topicFilter); + try { + // @ts-ignore + this.activateSubscription(existingRecord); + } catch (err) { + io.logError(SubscriptionManager.logSubject, `acquire subscription for operation '${options.operationId}' failed subscription activation: ${(err as Error).toString()}`); + return AcquireSubscriptionResult.Failure; + } + } + + io.logDebug(SubscriptionManager.logSubject, `acquire subscription for operation '${options.operationId}' subscribing - waiting on one or more subscriptions to complete`); + return AcquireSubscriptionResult.Subscribing; + } + + releaseSubscription(options: ReleaseSubscriptionsConfig) { + if (this.closed) { + return; + } + + for (let topicFilter of options.topicFilters) { + this.removeSubscriptionListener(topicFilter, options.operationId); + } + } + + purge() { + if (this.closed) { + return; + } + + io.logDebug(SubscriptionManager.logSubject, `purging unused subscriptions`); + let toRemove : Array = new Array(); + for (let [_, record] of this.records) { + if (record.listeners.size > 0) { + continue; + } + + io.logDebug(SubscriptionManager.logSubject, `subscription '${record.topicFilter}' has zero listeners and is a candidate for removal`); + + if (this.adapter.getConnectionState() == protocol_adapter.ConnectionState.Connected) { + this.unsubscribe(record, false); + } + + if (record.status == SubscriptionStatus.NotSubscribed && record.pendingAction == SubscriptionPendingAction.Nothing) { + toRemove.push(record.topicFilter); + } + } + + for (let topicFilter of toRemove) { + io.logDebug(SubscriptionManager.logSubject, `deleting subscription '${topicFilter}'`); + this.records.delete(topicFilter); + } + } + + static SUBSCRIBE_SUCCESS : string = 'subscribeSuccess'; + static SUBSCRIBE_FAILURE : string = 'subscribeFailure'; + static SUBSCRIPTION_ENDED : string = 'subscriptionEnded'; + static STREAMING_SUBSCRIPTION_ESTABLISHED : string = "streamingSubscriptionEstablished"; + static STREAMING_SUBSCRIPTION_LOST : string = "streamingSubscriptionLost"; + static STREAMING_SUBSCRIPTION_HALTED : string = "streamingSubscriptionHalted"; + static SUBSCRIPTION_ORPHANED : string = "subscriptionOrphaned"; + static UNSUBSCRIBE_COMPLETE : string = "unsubscribeComplete"; + + on(event: 'subscribeSuccess', listener: SubscribeSuccessEventListener): this; + on(event: 'subscribeFailure', listener: SubscribeFailureEventListener): this; + on(event: 'subscriptionEnded', listener: SubscriptionEndedEventListener): this; + on(event: 'streamingSubscriptionEstablished', listener: StreamingSubscriptionEstablishedEventListener): this; + on(event: 'streamingSubscriptionLost', listener: StreamingSubscriptionLostEventListener): this; + on(event: 'streamingSubscriptionHalted', listener: StreamingSubscriptionHaltedEventListener): this; + on(event: 'subscriptionOrphaned', listener: SubscriptionOrphanedEventListener): this; + on(event: 'unsubscribeComplete', listener: UnsubscribeCompleteEventListener): this; + + on(event: string | symbol, listener: (...args: any[]) => void): this { + super.on(event, listener); + return this; + } + + private getStats() : SubscriptionStats { + let stats : SubscriptionStats = { + requestResponseCount: 0, + streamingCount: 0, + unsubscribingStreamingCount: 0, + }; + + for (let [_, value] of this.records) { + if (value.type == SubscriptionType.RequestResponse) { + stats.requestResponseCount++; + } else if (value.type == SubscriptionType.EventStream) { + stats.streamingCount++; + if (value.pendingAction == SubscriptionPendingAction.Unsubscribing) { + stats.unsubscribingStreamingCount++; + } + } + } + + io.logDebug(SubscriptionManager.logSubject, `Current stats -- ${stats.requestResponseCount} request-response subscription records, ${stats.streamingCount} event stream subscription records, ${stats.unsubscribingStreamingCount} unsubscribing event stream subscriptions`); + + return stats; + } + + private unsubscribe(record: SubscriptionRecord, isShutdown: boolean) { + const currentlySubscribed = record.status == SubscriptionStatus.Subscribed; + const currentlySubscribing = record.pendingAction == SubscriptionPendingAction.Subscribing; + const currentlyUnsubscribing = record.pendingAction == SubscriptionPendingAction.Unsubscribing; + + let shouldUnsubscribe = currentlySubscribed && !currentlyUnsubscribing; + if (isShutdown) { + shouldUnsubscribe = shouldUnsubscribe || currentlySubscribing; + } + + if (!shouldUnsubscribe) { + io.logDebug(SubscriptionManager.logSubject, `subscription '${record.topicFilter}' has no listeners but is not in a state that allows unsubscribe yet`); + return; + } + + try { + this.adapter.unsubscribe({ + topicFilter: record.topicFilter, + timeoutInSeconds: this.options.operationTimeoutInSeconds + }); + } catch (err) { + io.logError(SubscriptionManager.logSubject, `synchronous unsubscribe failure for '${record.topicFilter}': ${(err as Error).toString()}`); + return; + } + + io.logDebug(SubscriptionManager.logSubject, `unsubscribe submitted for '${record.topicFilter}'`); + + record.pendingAction = SubscriptionPendingAction.Unsubscribing; + } + + private unsubscribeAll() { + for (let [_, value] of this.records) { + this.unsubscribe(value, true); + } + } + + private removeSubscriptionListener(topicFilter: string, operationId: number) { + let record = this.records.get(topicFilter); + if (!record) { + return; + } + + record.listeners.delete(operationId); + + let remainingListenerCount: number = record.listeners.size; + io.logDebug(SubscriptionManager.logSubject, `removed listener '${operationId}' from '${record.topicFilter}', ${remainingListenerCount} listeners left`); + if (remainingListenerCount > 0) { + return; + } + + setImmediate(() => { + this.emit(SubscriptionManager.SUBSCRIPTION_ORPHANED, { + topicFilter: topicFilter + }); + }); + } + + private emitEvents(record: SubscriptionRecord, eventType: SubscriptionEventType) { + for (let id of record.listeners) { + let event = { + topicFilter: record.topicFilter, + operationId: id, + }; + + io.logDebug(SubscriptionManager.logSubject, `emitting ${subscriptionEventTypeToString(eventType)} subscription event for '${record.topicFilter}' with id ${id}`); + + setImmediate(() => { + switch (eventType) { + case SubscriptionEventType.SubscribeSuccess: + this.emit(SubscriptionManager.SUBSCRIBE_SUCCESS, event); + break; + + case SubscriptionEventType.SubscribeFailure: + this.emit(SubscriptionManager.SUBSCRIBE_FAILURE, event); + break; + + case SubscriptionEventType.SubscriptionEnded: + this.emit(SubscriptionManager.SUBSCRIPTION_ENDED, event); + break; + + case SubscriptionEventType.StreamingSubscriptionEstablished: + this.emit(SubscriptionManager.STREAMING_SUBSCRIPTION_ESTABLISHED, event); + break; + + case SubscriptionEventType.StreamingSubscriptionLost: + this.emit(SubscriptionManager.STREAMING_SUBSCRIPTION_LOST, event); + break; + + case SubscriptionEventType.StreamingSubscriptionHalted: + this.emit(SubscriptionManager.STREAMING_SUBSCRIPTION_HALTED, event); + break; + + default: + break; + } + }); + } + } + + // this method re-throws dependent errors + private activateSubscription(record: SubscriptionRecord) { + if (record.poisoned) { + return; + } + + if (this.adapter.getConnectionState() != protocol_adapter.ConnectionState.Connected || record.listeners.size == 0) { + return; + } + + if (record.status != SubscriptionStatus.NotSubscribed || record.pendingAction != SubscriptionPendingAction.Nothing) { + return; + } + + try { + this.adapter.subscribe({ + topicFilter: record.topicFilter, + timeoutInSeconds: this.options.operationTimeoutInSeconds + }); + + io.logDebug(SubscriptionManager.logSubject, `initiated subscribe operation for '${record.topicFilter}'`); + + record.pendingAction = SubscriptionPendingAction.Subscribing; + } catch (err) { + io.logError(SubscriptionManager.logSubject, `synchronous failure subscribing to '${record.topicFilter}': ${(err as Error).toString()}`); + + if (record.type == SubscriptionType.RequestResponse) { + this.emitEvents(record, SubscriptionEventType.SubscribeFailure); + } else { + record.poisoned = true; + this.emitEvents(record, SubscriptionEventType.StreamingSubscriptionHalted); + } + + throw err; + } + } + + private handleRequestSubscribeCompletionEvent(record: SubscriptionRecord, event: protocol_adapter.SubscribeCompletionEvent) { + record.pendingAction = SubscriptionPendingAction.Nothing; + if (!event.err) { + record.status = SubscriptionStatus.Subscribed; + this.emitEvents(record, SubscriptionEventType.SubscribeSuccess); + } else { + this.emitEvents(record, SubscriptionEventType.SubscribeFailure); + } + } + + private handleStreamingSubscribeCompletionEvent(record: SubscriptionRecord, event: protocol_adapter.SubscribeCompletionEvent) { + record.pendingAction = SubscriptionPendingAction.Nothing; + if (!event.err) { + record.status = SubscriptionStatus.Subscribed; + this.emitEvents(record, SubscriptionEventType.StreamingSubscriptionEstablished); + } else { + if (event.retryable && !this.closed) { + this.activateSubscription(record); + } else { + record.poisoned = true; + this.emitEvents(record, SubscriptionEventType.StreamingSubscriptionHalted); + } + } + } + + private handleSubscribeCompletionEvent(event: protocol_adapter.SubscribeCompletionEvent) { + io.logDebug(SubscriptionManager.logSubject, ` received a protocol adapter subscribe completion event: ${JSON.stringify(event)}`); + + let record = this.records.get(event.topicFilter); + if (!record) { + return; + } + + if (record.pendingAction != SubscriptionPendingAction.Subscribing) { + return; + } + + if (record.type == SubscriptionType.RequestResponse) { + this.handleRequestSubscribeCompletionEvent(record, event); + } else { + this.handleStreamingSubscribeCompletionEvent(record, event); + } + } + + private handleUnsubscribeCompletionEvent(event: protocol_adapter.UnsubscribeCompletionEvent) { + io.logDebug(SubscriptionManager.logSubject, ` received a protocol adapter unsubscribe completion event: ${JSON.stringify(event)}`); + + let record = this.records.get(event.topicFilter); + if (!record) { + return; + } + + if (record.pendingAction != SubscriptionPendingAction.Unsubscribing) { + return; + } + + record.pendingAction = SubscriptionPendingAction.Nothing; + if (!event.err) { + record.status = SubscriptionStatus.NotSubscribed; + let topicFilter = record.topicFilter; + + setImmediate(() => { + this.emit(SubscriptionManager.UNSUBSCRIBE_COMPLETE, { + topicFilter: topicFilter + }); + }); + } + } + + private handleSessionLost() { + let toRemove = new Array(); + for (let [_, record] of this.records) { + if (record.status != SubscriptionStatus.Subscribed) { + continue; + } + + record.status = SubscriptionStatus.NotSubscribed; + if (record.type == SubscriptionType.RequestResponse) { + this.emitEvents(record, SubscriptionEventType.SubscriptionEnded); + if (record.pendingAction != SubscriptionPendingAction.Unsubscribing) { + toRemove.push(record.topicFilter); + } + } else { + this.emitEvents(record, SubscriptionEventType.StreamingSubscriptionLost); + } + } + + for (let topicFilter in toRemove) { + this.records.delete(topicFilter); + } + + for (let [_, record] of this.records) { + if (record.type == SubscriptionType.EventStream) { + this.activateSubscription(record); + } + } + } + + private activateIdleSubscriptions() { + for (let [_, record] of this.records) { + this.activateSubscription(record); + } + } + + private handleConnectionStatusEvent(event: protocol_adapter.ConnectionStatusEvent) { + io.logDebug(SubscriptionManager.logSubject, ` received a protocol adapter connection status event: ${JSON.stringify(event)}`); + + if (event.status != protocol_adapter.ConnectionState.Connected) { + return; + } + + if (!event.joinedSession) { + this.handleSessionLost(); + } + + this.purge(); + this.activateIdleSubscriptions(); + } + +} + diff --git a/lib/common/io.ts b/lib/common/io.ts index d2d104ef9..594671130 100644 --- a/lib/common/io.ts +++ b/lib/common/io.ts @@ -63,3 +63,95 @@ export enum SocketDomain { /** UNIX domain socket/Windows named pipes */ LOCAL = 2, } + +/** + * The amount of detail that will be logged + * @category Logging + */ +export enum LogLevel { + /** No logging whatsoever. */ + NONE = 0, + /** Only fatals. In practice, this will not do much, as the process will log and then crash (intentionally) if a fatal condition occurs */ + FATAL = 1, + /** Only errors */ + ERROR = 2, + /** Only warnings and errors */ + WARN = 3, + /** Information about connection/stream creation/destruction events */ + INFO = 4, + /** Enough information to debug the chain of events a given network connection encounters */ + DEBUG = 5, + /** Everything. Only use this if you really need to know EVERY single call */ + TRACE = 6 +} + +let logLevel : LogLevel = LogLevel.NONE; + +/** + * Sets the amount of detail that will be logged + * @param level - maximum level of logging detail. Log invocations at a higher level of detail will be ignored. + * + * @category Logging + */ +export function setLogLevel(level: LogLevel) { + logLevel = level; +} + +/* + * The logging API is exported to library-internal, but stays private beyond the package boundary, so the following API + * decisions are not binding. + */ + +export function logFatal(subject: string, logLine: string) { + if (logLevel < LogLevel.FATAL) { + return; + } + + let currentTime = new Date().toISOString(); + console.log(`[FATAL] [${currentTime}] [${subject}] - ${logLine}`); +} + +export function logError(subject: string, logLine: string) { + if (logLevel < LogLevel.ERROR) { + return; + } + + let currentTime = new Date().toISOString(); + console.log(`[ERROR] [${currentTime}] [${subject}] - ${logLine}`); +} + +export function logWarn(subject: string, logLine: string) { + if (logLevel < LogLevel.WARN) { + return; + } + + let currentTime = new Date().toISOString(); + console.log(`[WARN] [${currentTime}] [${subject}] - ${logLine}`); +} + +export function logInfo(subject: string, logLine: string) { + if (logLevel < LogLevel.INFO) { + return; + } + + let currentTime = new Date().toISOString(); + console.log(`[INFO] [${currentTime}] [${subject}] - ${logLine}`); +} + +export function logDebug(subject: string, logLine: string) { + if (logLevel < LogLevel.DEBUG) { + return; + } + + let currentTime = new Date().toISOString(); + console.log(`[DEBUG] [${currentTime}] [${subject}] - ${logLine}`); +} + +export function logTrace(subject: string, logLine: string) { + if (logLevel < LogLevel.TRACE) { + return; + } + + let currentTime = new Date().toISOString(); + console.log(`[TRACE] [${currentTime}] [${subject}] - ${logLine}`); +} \ No newline at end of file diff --git a/lib/native/io.ts b/lib/native/io.ts index d77c25afe..5cc70de01 100644 --- a/lib/native/io.ts +++ b/lib/native/io.ts @@ -21,9 +21,10 @@ import crt_native from './binding'; import { NativeResource } from "./native_resource"; -import { TlsVersion, SocketType, SocketDomain } from '../common/io'; +import { setLogLevel, LogLevel, TlsVersion, SocketType, SocketDomain } from '../common/io'; import { Readable } from 'stream'; -export { TlsVersion, SocketType, SocketDomain } from '../common/io'; +// Do not re-export the logging functions in common; they are package-private +export { setLogLevel, LogLevel, TlsVersion, SocketType, SocketDomain } from '../common/io'; import { CrtError } from './error'; /** @@ -56,27 +57,6 @@ export function error_code_to_name(error_code: number): string { return crt_native.error_code_to_name(error_code); } -/** - * The amount of detail that will be logged - * @category Logging - */ -export enum LogLevel { - /** No logging whatsoever. Equivalent to never calling {@link enable_logging}. */ - NONE = 0, - /** Only fatals. In practice, this will not do much, as the process will log and then crash (intentionally) if a fatal condition occurs */ - FATAL = 1, - /** Only errors */ - ERROR = 2, - /** Only warnings and errors */ - WARN = 3, - /** Information about connection/stream creation/destruction events */ - INFO = 4, - /** Enough information to debug the chain of events a given network connection encounters */ - DEBUG = 5, - /** Everything. Only use this if you really need to know EVERY single call */ - TRACE = 6 -} - /** * Enables logging of the native AWS CRT libraries. * @param level - The logging level to filter to. It is not possible to log less than WARN. @@ -86,6 +66,7 @@ export enum LogLevel { */ export function enable_logging(level: LogLevel) { crt_native.io_logging_enable(level); + setLogLevel(level); } /** diff --git a/package-lock.json b/package-lock.json index 2dde09e37..c25668ee0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5,13 +5,13 @@ "requires": true, "dependencies": { "@ampproject/remapping": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz", - "integrity": "sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", + "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", "dev": true, "requires": { - "@jridgewell/gen-mapping": "^0.3.0", - "@jridgewell/trace-mapping": "^0.3.9" + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" } }, "@aws-sdk/util-utf8-browser": { @@ -23,89 +23,37 @@ } }, "@babel/code-frame": { - "version": "7.23.5", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz", - "integrity": "sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.7.tgz", + "integrity": "sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==", "dev": true, "requires": { - "@babel/highlight": "^7.23.4", - "chalk": "^2.4.2" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } + "@babel/highlight": "^7.24.7", + "picocolors": "^1.0.0" } }, "@babel/compat-data": { - "version": "7.23.5", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.23.5.tgz", - "integrity": "sha512-uU27kfDRlhfKl+w1U6vp16IuvSLtjAxdArVXPa9BvLkrr7CYIsxH5adpHObeAGY/41+syctUWOZ140a2Rvkgjw==", + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.25.2.tgz", + "integrity": "sha512-bYcppcpKBvX4znYaPEeFau03bp89ShqNMLs+rmdptMw+heSZh9+z84d2YG+K7cYLbWwzdjtDoW/uqZmPjulClQ==", "dev": true }, "@babel/core": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.9.tgz", - "integrity": "sha512-5q0175NOjddqpvvzU+kDiSOAk4PfdO6FvwCWoQ6RO7rTzEe8vlo+4HVfcnAREhD4npMs0e9uZypjTwzZPCf/cw==", + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.25.2.tgz", + "integrity": "sha512-BBt3opiCOxUr9euZ5/ro/Xv8/V7yJ5bjYMqG/C1YAo8MIKAnumZalCN+msbci3Pigy4lIQfPUpfMM27HMGaYEA==", "dev": true, "requires": { "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.23.5", - "@babel/generator": "^7.23.6", - "@babel/helper-compilation-targets": "^7.23.6", - "@babel/helper-module-transforms": "^7.23.3", - "@babel/helpers": "^7.23.9", - "@babel/parser": "^7.23.9", - "@babel/template": "^7.23.9", - "@babel/traverse": "^7.23.9", - "@babel/types": "^7.23.9", + "@babel/code-frame": "^7.24.7", + "@babel/generator": "^7.25.0", + "@babel/helper-compilation-targets": "^7.25.2", + "@babel/helper-module-transforms": "^7.25.2", + "@babel/helpers": "^7.25.0", + "@babel/parser": "^7.25.0", + "@babel/template": "^7.25.0", + "@babel/traverse": "^7.25.2", + "@babel/types": "^7.25.2", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -128,26 +76,26 @@ } }, "@babel/generator": { - "version": "7.23.6", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.6.tgz", - "integrity": "sha512-qrSfCYxYQB5owCmGLbl8XRpX1ytXlpueOb0N0UmQwA073KZxejgQTzAmJezxvpwQD9uGtK2shHdi55QT+MbjIw==", + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.25.0.tgz", + "integrity": "sha512-3LEEcj3PVW8pW2R1SR1M89g/qrYk/m/mB/tLqn7dn4sbBUQyTqnlod+II2U4dqiGtUmkcnAmkMDralTFZttRiw==", "dev": true, "requires": { - "@babel/types": "^7.23.6", - "@jridgewell/gen-mapping": "^0.3.2", - "@jridgewell/trace-mapping": "^0.3.17", + "@babel/types": "^7.25.0", + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25", "jsesc": "^2.5.1" } }, "@babel/helper-compilation-targets": { - "version": "7.23.6", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.23.6.tgz", - "integrity": "sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ==", + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.25.2.tgz", + "integrity": "sha512-U2U5LsSaZ7TAt3cfaymQ8WHh0pxvdHoEk6HVpaexxixjyEquMh0L0YNJNM6CTGKMXV1iksi0iZkGw4AcFkPaaw==", "dev": true, "requires": { - "@babel/compat-data": "^7.23.5", - "@babel/helper-validator-option": "^7.23.5", - "browserslist": "^4.22.2", + "@babel/compat-data": "^7.25.2", + "@babel/helper-validator-option": "^7.24.8", + "browserslist": "^4.23.1", "lru-cache": "^5.1.1", "semver": "^6.3.1" }, @@ -175,115 +123,82 @@ } } }, - "@babel/helper-environment-visitor": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", - "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", - "dev": true - }, - "@babel/helper-function-name": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", - "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", - "dev": true, - "requires": { - "@babel/template": "^7.22.15", - "@babel/types": "^7.23.0" - } - }, - "@babel/helper-hoist-variables": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", - "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", - "dev": true, - "requires": { - "@babel/types": "^7.22.5" - } - }, "@babel/helper-module-imports": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz", - "integrity": "sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.7.tgz", + "integrity": "sha512-8AyH3C+74cgCVVXow/myrynrAGv+nTVg5vKu2nZph9x7RcRwzmh0VFallJuFTZ9mx6u4eSdXZfcOzSqTUm0HCA==", "dev": true, "requires": { - "@babel/types": "^7.22.15" + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7" } }, "@babel/helper-module-transforms": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.3.tgz", - "integrity": "sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ==", + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.25.2.tgz", + "integrity": "sha512-BjyRAbix6j/wv83ftcVJmBt72QtHI56C7JXZoG2xATiLpmoC7dpd8WnkikExHDVPpi/3qCmO6WY1EaXOluiecQ==", "dev": true, "requires": { - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-module-imports": "^7.22.15", - "@babel/helper-simple-access": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/helper-validator-identifier": "^7.22.20" + "@babel/helper-module-imports": "^7.24.7", + "@babel/helper-simple-access": "^7.24.7", + "@babel/helper-validator-identifier": "^7.24.7", + "@babel/traverse": "^7.25.2" } }, "@babel/helper-plugin-utils": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.7.tgz", - "integrity": "sha512-Rq76wjt7yz9AAc1KnlRKNAi/dMSVWgDRx43FHoJEbcYU6xOWaE2dVPwcdTukJrjxS65GITyfbvEYHvkirZ6uEg==", + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.8.tgz", + "integrity": "sha512-FFWx5142D8h2Mgr/iPVGH5G7w6jDn4jUSpZTyDnQO0Yn7Ks2Kuz6Pci8H6MPCoUJegd/UZQ3tAvfLCxQSnWWwg==", "dev": true }, "@babel/helper-simple-access": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz", - "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==", - "dev": true, - "requires": { - "@babel/types": "^7.22.5" - } - }, - "@babel/helper-split-export-declaration": { - "version": "7.22.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", - "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.24.7.tgz", + "integrity": "sha512-zBAIvbCMh5Ts+b86r/CjU+4XGYIs+R1j951gxI3KmmxBMhCg4oQMsv6ZXQ64XOm/cvzfU1FmoCyt6+owc5QMYg==", "dev": true, "requires": { - "@babel/types": "^7.22.5" + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7" } }, "@babel/helper-string-parser": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz", - "integrity": "sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==", + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.8.tgz", + "integrity": "sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ==", "dev": true }, "@babel/helper-validator-identifier": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", - "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz", + "integrity": "sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==", "dev": true }, "@babel/helper-validator-option": { - "version": "7.23.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz", - "integrity": "sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==", + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.24.8.tgz", + "integrity": "sha512-xb8t9tD1MHLungh/AIoWYN+gVHaB9kwlu8gffXGSt3FFEIT7RjS+xWbc2vUD1UTZdIpKj/ab3rdqJ7ufngyi2Q==", "dev": true }, "@babel/helpers": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.23.9.tgz", - "integrity": "sha512-87ICKgU5t5SzOT7sBMfCOZQ2rHjRU+Pcb9BoILMYz600W6DkVRLFBPwQ18gwUVvggqXivaUakpnxWQGbpywbBQ==", + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.25.0.tgz", + "integrity": "sha512-MjgLZ42aCm0oGjJj8CtSM3DB8NOOf8h2l7DCTePJs29u+v7yO/RBX9nShlKMgFnRks/Q4tBAe7Hxnov9VkGwLw==", "dev": true, "requires": { - "@babel/template": "^7.23.9", - "@babel/traverse": "^7.23.9", - "@babel/types": "^7.23.9" + "@babel/template": "^7.25.0", + "@babel/types": "^7.25.0" } }, "@babel/highlight": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.23.4.tgz", - "integrity": "sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.7.tgz", + "integrity": "sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw==", "dev": true, "requires": { - "@babel/helper-validator-identifier": "^7.22.20", + "@babel/helper-validator-identifier": "^7.24.7", "chalk": "^2.4.2", - "js-tokens": "^4.0.0" + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" }, "dependencies": { "ansi-styles": { @@ -339,10 +254,13 @@ } }, "@babel/parser": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.9.tgz", - "integrity": "sha512-9tcKgqKbs3xGJ+NtKF2ndOBBLVwPjl1SHxPQkd36r3Dlirw3xWUeGaTbqr7uGZcTaxkVNwc+03SVP7aCdWrTlA==", - "dev": true + "version": "7.25.3", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.25.3.tgz", + "integrity": "sha512-iLTJKDbJ4hMvFPgQwwsVoxtHyWpKKPBrxkANrSYewDPaPpT5py5yeVkgPIJ7XYXhndxJpaA3PyALSXQ7u8e/Dw==", + "dev": true, + "requires": { + "@babel/types": "^7.25.2" + } }, "@babel/plugin-syntax-async-generators": { "version": "7.8.4", @@ -371,6 +289,24 @@ "@babel/helper-plugin-utils": "^7.12.13" } }, + "@babel/plugin-syntax-class-static-block": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", + "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-syntax-import-attributes": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.24.7.tgz", + "integrity": "sha512-hbX+lKKeUMGihnK8nvKqmXBInriT3GVjzXKFriV3YC6APGxMbP8RZNFwy91+hocLXq90Mta+HshoB31802bb8A==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.24.7" + } + }, "@babel/plugin-syntax-import-meta": { "version": "7.10.4", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", @@ -389,15 +325,6 @@ "@babel/helper-plugin-utils": "^7.8.0" } }, - "@babel/plugin-syntax-jsx": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.24.7.tgz", - "integrity": "sha512-6ddciUPe/mpMnOKv/U+RSd2vvVy+Yw/JfBB0ZHYjEZt9NLHmCUylNYlsbqCCS1Bffjlb0fCwC9Vqz+sBz6PsiQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.24.7" - } - }, "@babel/plugin-syntax-logical-assignment-operators": { "version": "7.10.4", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", @@ -452,6 +379,15 @@ "@babel/helper-plugin-utils": "^7.8.0" } }, + "@babel/plugin-syntax-private-property-in-object": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", + "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, "@babel/plugin-syntax-top-level-await": { "version": "7.14.5", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", @@ -462,51 +398,48 @@ } }, "@babel/plugin-syntax-typescript": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.23.3.tgz", - "integrity": "sha512-9EiNjVJOMwCO+43TqoTrgQ8jMwcAd0sWyXi9RPfIsLTj4R2MADDDQXELhffaUx/uJv2AYcxBgPwH6j4TIA4ytQ==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.24.7.tgz", + "integrity": "sha512-c/+fVeJBB0FeKsFvwytYiUD+LBvhHjGSI0g446PRGdSVGZLRNArBUno2PETbAly3tpiNAQR5XaZ+JslxkotsbA==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.7" } }, "@babel/template": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.23.9.tgz", - "integrity": "sha512-+xrD2BWLpvHKNmX2QbpdpsBaWnRxahMwJjO+KZk2JOElj5nSmKezyS1B4u+QbHMTX69t4ukm6hh9lsYQ7GHCKA==", + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.0.tgz", + "integrity": "sha512-aOOgh1/5XzKvg1jvVz7AVrx2piJ2XBi227DHmbY6y+bM9H2FlN+IfecYu4Xl0cNiiVejlsCri89LUsbj8vJD9Q==", "dev": true, "requires": { - "@babel/code-frame": "^7.23.5", - "@babel/parser": "^7.23.9", - "@babel/types": "^7.23.9" + "@babel/code-frame": "^7.24.7", + "@babel/parser": "^7.25.0", + "@babel/types": "^7.25.0" } }, "@babel/traverse": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.9.tgz", - "integrity": "sha512-I/4UJ9vs90OkBtY6iiiTORVMyIhJ4kAVmsKo9KFc8UOxMeUfi2hvtIBsET5u9GizXE6/GFSuKCTNfgCswuEjRg==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.23.5", - "@babel/generator": "^7.23.6", - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-function-name": "^7.23.0", - "@babel/helper-hoist-variables": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/parser": "^7.23.9", - "@babel/types": "^7.23.9", + "version": "7.25.3", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.3.tgz", + "integrity": "sha512-HefgyP1x754oGCsKmV5reSmtV7IXj/kpaE1XYY+D9G5PvKKoFfSbiS4M77MdjuwlZKDIKFCffq9rPU+H/s3ZdQ==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.24.7", + "@babel/generator": "^7.25.0", + "@babel/parser": "^7.25.3", + "@babel/template": "^7.25.0", + "@babel/types": "^7.25.2", "debug": "^4.3.1", "globals": "^11.1.0" } }, "@babel/types": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.9.tgz", - "integrity": "sha512-dQjSq/7HaSjRM43FFGnv5keM2HsxpmyV1PfaSVm0nzzjwwTmjOe6J4bC8e3+pTEIgHaHj+1ZlLThRJ2auc/w1Q==", + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.25.2.tgz", + "integrity": "sha512-YTnYtra7W9e6/oAZEHj0bJehPRUlLH9/fbpT5LfB0NhQXyALCRkRs3zH9v07IYhkgpqX6Z78FnuccZr/l4Fs4Q==", "dev": true, "requires": { - "@babel/helper-string-parser": "^7.23.4", - "@babel/helper-validator-identifier": "^7.22.20", + "@babel/helper-string-parser": "^7.24.8", + "@babel/helper-validator-identifier": "^7.24.7", "to-fast-properties": "^2.0.0" } }, @@ -544,82 +477,26 @@ "safe-buffer": "^5.1.2", "ws": "*", "xtend": "^4.0.0" - } - }, - "@isaacs/cliui": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", - "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", - "dev": true, - "requires": { - "string-width": "^5.1.2", - "string-width-cjs": "npm:string-width@^4.2.0", - "strip-ansi": "^7.0.1", - "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", - "wrap-ansi": "^8.1.0", - "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" }, "dependencies": { - "ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", - "dev": true - }, - "ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", - "dev": true - }, - "emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "dev": true - }, - "string-width": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", - "dev": true, + "@types/node": { + "version": "22.4.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.4.1.tgz", + "integrity": "sha512-1tbpb9325+gPnKK0dMm+/LMriX0vKxf6RnB0SZUqfyVkQ4fMgUSySqhxE/y8Jvs4NyF1yHzTfG9KlnkIODxPKg==", "requires": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" + "undici-types": "~6.19.2" } }, - "strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dev": true, - "requires": { - "ansi-regex": "^6.0.1" - } - }, - "wrap-ansi": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", - "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", - "dev": true, + "@types/ws": { + "version": "8.5.12", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.12.tgz", + "integrity": "sha512-3tPRkv1EtkDpzlgyKyI8pGsGZAGPEaXeu0DOj5DI25Ja91bdAYddYHbADRYVrZMRbfW+1l5YwXVDKohDJNQxkQ==", "requires": { - "ansi-styles": "^6.1.0", - "string-width": "^5.0.1", - "strip-ansi": "^7.0.1" + "@types/node": "*" } } } }, - "@isaacs/fs-minipass": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz", - "integrity": "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==", - "dev": true, - "requires": { - "minipass": "^7.0.4" - } - }, "@istanbuljs/load-nyc-config": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", @@ -687,49 +564,6 @@ "rimraf": "^3.0.0", "slash": "^3.0.0", "strip-ansi": "^6.0.0" - }, - "dependencies": { - "@jest/globals": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-27.5.1.tgz", - "integrity": "sha512-ZEJNB41OBQQgGzgyInAv0UUfDDj3upmHydjieSxFvTRuZElrx7tXg/uVQ5hYVEwiXs3+aMsAeEc9X7xiSKCm4Q==", - "dev": true, - "requires": { - "@jest/environment": "^27.5.1", - "@jest/types": "^27.5.1", - "expect": "^27.5.1" - } - }, - "jest-runtime": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-27.5.1.tgz", - "integrity": "sha512-o7gxw3Gf+H2IGt8fv0RiyE1+r83FJBRruoA+FXrlHw6xEyBsU8ugA6IPfTdVyA0w8HClpbK+DGJxH59UrNMx8A==", - "dev": true, - "requires": { - "@jest/environment": "^27.5.1", - "@jest/fake-timers": "^27.5.1", - "@jest/globals": "^27.5.1", - "@jest/source-map": "^27.5.1", - "@jest/test-result": "^27.5.1", - "@jest/transform": "^27.5.1", - "@jest/types": "^27.5.1", - "chalk": "^4.0.0", - "cjs-module-lexer": "^1.0.0", - "collect-v8-coverage": "^1.0.0", - "execa": "^5.0.0", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^27.5.1", - "jest-message-util": "^27.5.1", - "jest-mock": "^27.5.1", - "jest-regex-util": "^27.5.1", - "jest-resolve": "^27.5.1", - "jest-snapshot": "^27.5.1", - "jest-util": "^27.5.1", - "slash": "^3.0.0", - "strip-bom": "^4.0.0" - } - } } }, "@jest/environment": { @@ -744,275 +578,6 @@ "jest-mock": "^27.5.1" } }, - "@jest/expect": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz", - "integrity": "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==", - "dev": true, - "requires": { - "expect": "^29.7.0", - "jest-snapshot": "^29.7.0" - }, - "dependencies": { - "@jest/transform": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", - "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", - "dev": true, - "requires": { - "@babel/core": "^7.11.6", - "@jest/types": "^29.6.3", - "@jridgewell/trace-mapping": "^0.3.18", - "babel-plugin-istanbul": "^6.1.1", - "chalk": "^4.0.0", - "convert-source-map": "^2.0.0", - "fast-json-stable-stringify": "^2.1.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.7.0", - "jest-regex-util": "^29.6.3", - "jest-util": "^29.7.0", - "micromatch": "^4.0.4", - "pirates": "^4.0.4", - "slash": "^3.0.0", - "write-file-atomic": "^4.0.2" - } - }, - "@jest/types": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", - "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", - "dev": true, - "requires": { - "@jest/schemas": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" - } - }, - "@types/yargs": { - "version": "17.0.32", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.32.tgz", - "integrity": "sha512-xQ67Yc/laOG5uMfX/093MRlGGCIBzZMarVa+gfNKJxWAIgykYpVGkBdbqEzGDDfCrVUj6Hiff4mTZ5BA6TmAog==", - "dev": true, - "requires": { - "@types/yargs-parser": "*" - } - }, - "ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true - }, - "convert-source-map": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", - "dev": true - }, - "diff-sequences": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", - "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", - "dev": true - }, - "expect": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz", - "integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==", - "dev": true, - "requires": { - "@jest/expect-utils": "^29.7.0", - "jest-get-type": "^29.6.3", - "jest-matcher-utils": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-util": "^29.7.0" - } - }, - "jest-diff": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", - "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", - "dev": true, - "requires": { - "chalk": "^4.0.0", - "diff-sequences": "^29.6.3", - "jest-get-type": "^29.6.3", - "pretty-format": "^29.7.0" - } - }, - "jest-get-type": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", - "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", - "dev": true - }, - "jest-haste-map": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz", - "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==", - "dev": true, - "requires": { - "@jest/types": "^29.6.3", - "@types/graceful-fs": "^4.1.3", - "@types/node": "*", - "anymatch": "^3.0.3", - "fb-watchman": "^2.0.0", - "fsevents": "^2.3.2", - "graceful-fs": "^4.2.9", - "jest-regex-util": "^29.6.3", - "jest-util": "^29.7.0", - "jest-worker": "^29.7.0", - "micromatch": "^4.0.4", - "walker": "^1.0.8" - } - }, - "jest-matcher-utils": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz", - "integrity": "sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==", - "dev": true, - "requires": { - "chalk": "^4.0.0", - "jest-diff": "^29.7.0", - "jest-get-type": "^29.6.3", - "pretty-format": "^29.7.0" - } - }, - "jest-message-util": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", - "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.12.13", - "@jest/types": "^29.6.3", - "@types/stack-utils": "^2.0.0", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "micromatch": "^4.0.4", - "pretty-format": "^29.7.0", - "slash": "^3.0.0", - "stack-utils": "^2.0.3" - } - }, - "jest-regex-util": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", - "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", - "dev": true - }, - "jest-snapshot": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.7.0.tgz", - "integrity": "sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==", - "dev": true, - "requires": { - "@babel/core": "^7.11.6", - "@babel/generator": "^7.7.2", - "@babel/plugin-syntax-jsx": "^7.7.2", - "@babel/plugin-syntax-typescript": "^7.7.2", - "@babel/types": "^7.3.3", - "@jest/expect-utils": "^29.7.0", - "@jest/transform": "^29.7.0", - "@jest/types": "^29.6.3", - "babel-preset-current-node-syntax": "^1.0.0", - "chalk": "^4.0.0", - "expect": "^29.7.0", - "graceful-fs": "^4.2.9", - "jest-diff": "^29.7.0", - "jest-get-type": "^29.6.3", - "jest-matcher-utils": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-util": "^29.7.0", - "natural-compare": "^1.4.0", - "pretty-format": "^29.7.0", - "semver": "^7.5.3" - } - }, - "jest-util": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", - "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", - "dev": true, - "requires": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "graceful-fs": "^4.2.9", - "picomatch": "^2.2.3" - } - }, - "jest-worker": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", - "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", - "dev": true, - "requires": { - "@types/node": "*", - "jest-util": "^29.7.0", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" - } - }, - "pretty-format": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", - "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", - "dev": true, - "requires": { - "@jest/schemas": "^29.6.3", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - } - }, - "react-is": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", - "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", - "dev": true - }, - "supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - }, - "write-file-atomic": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", - "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", - "dev": true, - "requires": { - "imurmurhash": "^0.1.4", - "signal-exit": "^3.0.7" - } - } - } - }, - "@jest/expect-utils": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz", - "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==", - "dev": true, - "requires": { - "jest-get-type": "^29.6.3" - }, - "dependencies": { - "jest-get-type": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", - "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", - "dev": true - } - } - }, "@jest/fake-timers": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-27.5.1.tgz", @@ -1028,149 +593,14 @@ } }, "@jest/globals": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz", - "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==", + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-27.5.1.tgz", + "integrity": "sha512-ZEJNB41OBQQgGzgyInAv0UUfDDj3upmHydjieSxFvTRuZElrx7tXg/uVQ5hYVEwiXs3+aMsAeEc9X7xiSKCm4Q==", "dev": true, "requires": { - "@jest/environment": "^29.7.0", - "@jest/expect": "^29.7.0", - "@jest/types": "^29.6.3", - "jest-mock": "^29.7.0" - }, - "dependencies": { - "@jest/environment": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", - "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", - "dev": true, - "requires": { - "@jest/fake-timers": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "jest-mock": "^29.7.0" - } - }, - "@jest/fake-timers": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz", - "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", - "dev": true, - "requires": { - "@jest/types": "^29.6.3", - "@sinonjs/fake-timers": "^10.0.2", - "@types/node": "*", - "jest-message-util": "^29.7.0", - "jest-mock": "^29.7.0", - "jest-util": "^29.7.0" - } - }, - "@jest/types": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", - "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", - "dev": true, - "requires": { - "@jest/schemas": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" - } - }, - "@sinonjs/commons": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", - "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", - "dev": true, - "requires": { - "type-detect": "4.0.8" - } - }, - "@sinonjs/fake-timers": { - "version": "10.3.0", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", - "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", - "dev": true, - "requires": { - "@sinonjs/commons": "^3.0.0" - } - }, - "@types/yargs": { - "version": "17.0.32", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.32.tgz", - "integrity": "sha512-xQ67Yc/laOG5uMfX/093MRlGGCIBzZMarVa+gfNKJxWAIgykYpVGkBdbqEzGDDfCrVUj6Hiff4mTZ5BA6TmAog==", - "dev": true, - "requires": { - "@types/yargs-parser": "*" - } - }, - "ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true - }, - "jest-message-util": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", - "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.12.13", - "@jest/types": "^29.6.3", - "@types/stack-utils": "^2.0.0", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "micromatch": "^4.0.4", - "pretty-format": "^29.7.0", - "slash": "^3.0.0", - "stack-utils": "^2.0.3" - } - }, - "jest-mock": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz", - "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==", - "dev": true, - "requires": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "jest-util": "^29.7.0" - } - }, - "jest-util": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", - "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", - "dev": true, - "requires": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "graceful-fs": "^4.2.9", - "picomatch": "^2.2.3" - } - }, - "pretty-format": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", - "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", - "dev": true, - "requires": { - "@jest/schemas": "^29.6.3", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - } - }, - "react-is": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", - "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", - "dev": true - } + "@jest/environment": "^27.5.1", + "@jest/types": "^27.5.1", + "expect": "^27.5.1" } }, "@jest/reporters": { @@ -1206,15 +636,6 @@ "v8-to-istanbul": "^8.1.0" } }, - "@jest/schemas": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", - "dev": true, - "requires": { - "@sinclair/typebox": "^0.27.8" - } - }, "@jest/source-map": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-27.5.1.tgz", @@ -1248,49 +669,6 @@ "graceful-fs": "^4.2.9", "jest-haste-map": "^27.5.1", "jest-runtime": "^27.5.1" - }, - "dependencies": { - "@jest/globals": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-27.5.1.tgz", - "integrity": "sha512-ZEJNB41OBQQgGzgyInAv0UUfDDj3upmHydjieSxFvTRuZElrx7tXg/uVQ5hYVEwiXs3+aMsAeEc9X7xiSKCm4Q==", - "dev": true, - "requires": { - "@jest/environment": "^27.5.1", - "@jest/types": "^27.5.1", - "expect": "^27.5.1" - } - }, - "jest-runtime": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-27.5.1.tgz", - "integrity": "sha512-o7gxw3Gf+H2IGt8fv0RiyE1+r83FJBRruoA+FXrlHw6xEyBsU8ugA6IPfTdVyA0w8HClpbK+DGJxH59UrNMx8A==", - "dev": true, - "requires": { - "@jest/environment": "^27.5.1", - "@jest/fake-timers": "^27.5.1", - "@jest/globals": "^27.5.1", - "@jest/source-map": "^27.5.1", - "@jest/test-result": "^27.5.1", - "@jest/transform": "^27.5.1", - "@jest/types": "^27.5.1", - "chalk": "^4.0.0", - "cjs-module-lexer": "^1.0.0", - "collect-v8-coverage": "^1.0.0", - "execa": "^5.0.0", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^27.5.1", - "jest-message-util": "^27.5.1", - "jest-mock": "^27.5.1", - "jest-regex-util": "^27.5.1", - "jest-resolve": "^27.5.1", - "jest-snapshot": "^27.5.1", - "jest-util": "^27.5.1", - "slash": "^3.0.0", - "strip-bom": "^4.0.0" - } - } } }, "@jest/transform": { @@ -1330,14 +708,14 @@ } }, "@jridgewell/gen-mapping": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", - "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", "dev": true, "requires": { - "@jridgewell/set-array": "^1.0.1", + "@jridgewell/set-array": "^1.2.1", "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" + "@jridgewell/trace-mapping": "^0.3.24" } }, "@jridgewell/resolve-uri": { @@ -1347,34 +725,27 @@ "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==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", "dev": true }, "@jridgewell/sourcemap-codec": { - "version": "1.4.15", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", - "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", "dev": true }, "@jridgewell/trace-mapping": { - "version": "0.3.22", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.22.tgz", - "integrity": "sha512-Wf963MzWtA2sjrNt+g18IAln9lKnlRp+K2eH4jjIoF1wYeq3aMREpG09xhlhdzS0EjwU7qmUJYangWa+151vZw==", + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", "dev": true, "requires": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, - "@pkgjs/parseargs": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", - "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", - "dev": true, - "optional": true - }, "@sideway/address": { "version": "4.1.5", "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.5.tgz", @@ -1396,12 +767,6 @@ "integrity": "sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==", "dev": true }, - "@sinclair/typebox": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", - "dev": true - }, "@sinonjs/commons": { "version": "1.8.6", "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.6.tgz", @@ -1459,9 +824,9 @@ } }, "@types/babel__traverse": { - "version": "7.20.5", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.5.tgz", - "integrity": "sha512-WXCyOcRtH37HAUkpXhUduaxdm82b4GSlyTqajXviN4EfiuPgNYR109xMCKvpl6zPIpua0DGlMEDCq+g8EdoheQ==", + "version": "7.20.6", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.6.tgz", + "integrity": "sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==", "dev": true, "requires": { "@babel/types": "^7.20.7" @@ -1507,155 +872,25 @@ } }, "@types/jest": { - "version": "29.5.12", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.12.tgz", - "integrity": "sha512-eDC8bTvT/QhYdxJAulQikueigY5AsdBRH2yDKW3yveW7svY3+DzN84/2NUgkw10RTiJbWqZrTtoGVdYlvFJdLw==", + "version": "27.5.2", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-27.5.2.tgz", + "integrity": "sha512-mpT8LJJ4CMeeahobofYWIjFo0xonRS/HfxnVEPMPFSQdGUt1uHCnoPT7Zhb+sjDU2wz0oKV0OLUR0WzrHNgfeA==", "dev": true, "requires": { - "expect": "^29.0.0", - "pretty-format": "^29.0.0" - }, - "dependencies": { - "@jest/types": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", - "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", - "dev": true, - "requires": { - "@jest/schemas": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" - } - }, - "@types/yargs": { - "version": "17.0.32", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.32.tgz", - "integrity": "sha512-xQ67Yc/laOG5uMfX/093MRlGGCIBzZMarVa+gfNKJxWAIgykYpVGkBdbqEzGDDfCrVUj6Hiff4mTZ5BA6TmAog==", - "dev": true, - "requires": { - "@types/yargs-parser": "*" - } - }, - "ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true - }, - "diff-sequences": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", - "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", - "dev": true - }, - "expect": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz", - "integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==", - "dev": true, - "requires": { - "@jest/expect-utils": "^29.7.0", - "jest-get-type": "^29.6.3", - "jest-matcher-utils": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-util": "^29.7.0" - } - }, - "jest-diff": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", - "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", - "dev": true, - "requires": { - "chalk": "^4.0.0", - "diff-sequences": "^29.6.3", - "jest-get-type": "^29.6.3", - "pretty-format": "^29.7.0" - } - }, - "jest-get-type": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", - "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", - "dev": true - }, - "jest-matcher-utils": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz", - "integrity": "sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==", - "dev": true, - "requires": { - "chalk": "^4.0.0", - "jest-diff": "^29.7.0", - "jest-get-type": "^29.6.3", - "pretty-format": "^29.7.0" - } - }, - "jest-message-util": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", - "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.12.13", - "@jest/types": "^29.6.3", - "@types/stack-utils": "^2.0.0", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "micromatch": "^4.0.4", - "pretty-format": "^29.7.0", - "slash": "^3.0.0", - "stack-utils": "^2.0.3" - } - }, - "jest-util": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", - "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", - "dev": true, - "requires": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "graceful-fs": "^4.2.9", - "picomatch": "^2.2.3" - } - }, - "pretty-format": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", - "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", - "dev": true, - "requires": { - "@jest/schemas": "^29.6.3", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - } - }, - "react-is": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", - "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", - "dev": true - } + "jest-matcher-utils": "^27.0.0", + "pretty-format": "^27.0.0" } }, "@types/node": { - "version": "20.14.7", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.7.tgz", - "integrity": "sha512-uTr2m2IbJJucF3KUxgnGOZvYbN0QgkGyWxG6973HCpMYFy2KfcgYuIwkJQMQkt1VbBMlvWRbpshFTLxnxCZjKQ==", - "requires": { - "undici-types": "~5.26.4" - } + "version": "10.17.60", + "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.60.tgz", + "integrity": "sha512-F0KIgDJfy2nA3zMLmWGKxcH2ZVEtCZXHHdOQs2gSaQ27+lNeEfGxzkIw90aXswATX7AZ33tahPbzy6KAfUreVw==", + "dev": true }, "@types/prettier": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.3.tgz", - "integrity": "sha512-+68kP9yzs4LMp7VNh8gdzMSPZFL44MLGqiHWvttYJe+6qnuVr4Ek9wSBQoveqY/r+LwjCcU29kNVkidwim+kYA==", + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.6.0.tgz", + "integrity": "sha512-G/AdOadiZhnJp0jXCaBQU449W2h716OW/EoXeYkCytxKL06X1WCXB4DZpp8TpZ8eyIJVS1cw4lrlkkSYU21cDw==", "dev": true }, "@types/puppeteer": { @@ -1674,15 +909,16 @@ "dev": true }, "@types/uuid": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-10.0.0.tgz", - "integrity": "sha512-7gqG38EyHgyP1S+7+xomFtL+ZNHcKv6DwNaCZmJmo1vgMugyF3TCnXVg4t1uk89mLNwnLtnY3TpOpCOyp1/xHQ==", + "version": "3.4.13", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-3.4.13.tgz", + "integrity": "sha512-pAeZeUbLE4Z9Vi9wsWV2bYPTweEHeJJy0G4pEjOA/FSvy1Ad5U5Km8iDV6TKre1mjBiVNfAdVHKruP8bAh4Q5A==", "dev": true }, "@types/ws": { "version": "7.4.7", "resolved": "https://registry.npmjs.org/@types/ws/-/ws-7.4.7.tgz", "integrity": "sha512-JQbbmxZTZehdc2iszGKs5oC3NFnjeay7mtAWrdt7qNtAVK0g19muApzAy4bm9byz79xa2ZnO/BOBC2R8RC5Lww==", + "dev": true, "requires": { "@types/node": "*" } @@ -1719,9 +955,9 @@ "dev": true }, "acorn": { - "version": "8.11.3", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", - "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", + "version": "8.12.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", + "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", "dev": true }, "acorn-globals": { @@ -1847,15 +1083,18 @@ "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" }, "available-typed-arrays": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.6.tgz", - "integrity": "sha512-j1QzY8iPNPG4o4xmO3ptzpRxTciqD3MgEHtifP/YnJpIo58Xu+ne4BejlbkuaLfXn/nz6HFiw29bLpj2PNMdGg==", - "dev": true + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", + "dev": true, + "requires": { + "possible-typed-array-names": "^1.0.0" + } }, "aws-sdk": { - "version": "2.1646.0", - "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.1646.0.tgz", - "integrity": "sha512-PAvDiR8ow3zjO0T5HMda04kXIzQ5e1zeWxWGSUodRwu9W569gZPBnqzcPX3PJFNAKBZnZBdbNgsci1g2nXCcBg==", + "version": "2.1678.0", + "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.1678.0.tgz", + "integrity": "sha512-7+MNi7hholVrQYBu8bVbfzOBHxKlC63BfuxUwwMaUrFN1hok4pdB0QsEvL6YHwZtF+3Bq5zhONImnT2Q7W15yg==", "dev": true, "requires": { "buffer": "4.9.2", @@ -1881,6 +1120,12 @@ "isarray": "^1.0.0" } }, + "ieee754": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", + "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==", + "dev": true + }, "uuid": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.0.0.tgz", @@ -1890,30 +1135,13 @@ } }, "axios": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.2.tgz", - "integrity": "sha512-2A8QhOMrbomlDuiLeK9XibIBzuHeRcqqNOHp0Cyp5EoJ1IFDh+XZH3A6BkXtv0K4gFGCI0Y4BM7B1wOEi0Rmgw==", + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.4.tgz", + "integrity": "sha512-DukmaFRnY6AzAALSH4J2M3k6PkaC+MfaAGdEERRWcC9q3/TWQwLpHR8ZRLKTdQ3aBDL64EdluRDjJqKw+BPZEw==", "requires": { "follow-redirects": "^1.15.6", "form-data": "^4.0.0", "proxy-from-env": "^1.1.0" - }, - "dependencies": { - "follow-redirects": { - "version": "1.15.6", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", - "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==" - }, - "form-data": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - } - } } }, "babel-jest": { @@ -1958,23 +1186,26 @@ } }, "babel-preset-current-node-syntax": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz", - "integrity": "sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.1.0.tgz", + "integrity": "sha512-ldYss8SbBlWva1bs28q78Ju5Zq1F+8BrqBZZ0VFhLBvhh6lCpC2o3gDJi/5DRLs9FgYZCnmPYIVFU4lRXCkyUw==", "dev": true, "requires": { "@babel/plugin-syntax-async-generators": "^7.8.4", "@babel/plugin-syntax-bigint": "^7.8.3", - "@babel/plugin-syntax-class-properties": "^7.8.3", - "@babel/plugin-syntax-import-meta": "^7.8.3", + "@babel/plugin-syntax-class-properties": "^7.12.13", + "@babel/plugin-syntax-class-static-block": "^7.14.5", + "@babel/plugin-syntax-import-attributes": "^7.24.7", + "@babel/plugin-syntax-import-meta": "^7.10.4", "@babel/plugin-syntax-json-strings": "^7.8.3", - "@babel/plugin-syntax-logical-assignment-operators": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", - "@babel/plugin-syntax-numeric-separator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", "@babel/plugin-syntax-object-rest-spread": "^7.8.3", "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", "@babel/plugin-syntax-optional-chaining": "^7.8.3", - "@babel/plugin-syntax-top-level-await": "^7.8.3" + "@babel/plugin-syntax-private-property-in-object": "^7.14.5", + "@babel/plugin-syntax-top-level-await": "^7.14.5" } }, "babel-preset-jest": { @@ -2044,17 +1275,6 @@ "dev": true, "requires": { "fill-range": "^7.1.1" - }, - "dependencies": { - "fill-range": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", - "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", - "dev": true, - "requires": { - "to-regex-range": "^5.0.1" - } - } } }, "browser-process-hrtime": { @@ -2064,15 +1284,15 @@ "dev": true }, "browserslist": { - "version": "4.23.0", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.0.tgz", - "integrity": "sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==", + "version": "4.23.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.3.tgz", + "integrity": "sha512-btwCFJVjI4YWDNfau8RhZ+B1Q/VLoUITrm3RlP6y1tYGWIOa+InuYiRGXUBXo8nA1qKmHMyLB/iVQg5TT4eFoA==", "dev": true, "requires": { - "caniuse-lite": "^1.0.30001587", - "electron-to-chromium": "^1.4.668", - "node-releases": "^2.0.14", - "update-browserslist-db": "^1.0.13" + "caniuse-lite": "^1.0.30001646", + "electron-to-chromium": "^1.5.4", + "node-releases": "^2.0.18", + "update-browserslist-db": "^1.1.0" } }, "bs-logger": { @@ -2100,13 +1320,6 @@ "requires": { "base64-js": "^1.3.1", "ieee754": "^1.2.1" - }, - "dependencies": { - "ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==" - } } }, "buffer-crc32": { @@ -2146,9 +1359,9 @@ "dev": true }, "caniuse-lite": { - "version": "1.0.30001587", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001587.tgz", - "integrity": "sha512-HMFNotUmLXn71BQxg8cijvqxnIAofforZOwGsxyXJ0qugTdspUF4sPSJ2vhgprHCB996tIDzEq1ubumPDV8ULA==", + "version": "1.0.30001651", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001651.tgz", + "integrity": "sha512-9Cf+Xv1jJNe1xPZLGuUXLNkE1BoDkqRqYyFJ9TDYSqhduqA4hu4oR9HluGoWYQC/aj8WHjsGVV+bwkh0+tegRg==", "dev": true }, "chalk": { @@ -2168,9 +1381,9 @@ "dev": true }, "chownr": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz", - "integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", "dev": true }, "ci-info": { @@ -2180,9 +1393,9 @@ "dev": true }, "cjs-module-lexer": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.3.tgz", - "integrity": "sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.3.1.tgz", + "integrity": "sha512-a3KdPAANPbNE4ZUv9h6LckSl9zLsYOP4MBmhIPkRaeyybt+r4UghLvq+xw/YwUcC1gqylCkL4rdVs3Lwupjm4Q==", "dev": true }, "cliui": { @@ -2228,61 +1441,6 @@ "url-join": "^4.0.1", "which": "^2.0.2", "yargs": "^17.7.2" - }, - "dependencies": { - "chownr": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", - "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", - "dev": true - }, - "minipass": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", - "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", - "dev": true - }, - "minizlib": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", - "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", - "dev": true, - "requires": { - "minipass": "^3.0.0", - "yallist": "^4.0.0" - }, - "dependencies": { - "minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "dev": true, - "requires": { - "yallist": "^4.0.0" - } - } - } - }, - "mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "dev": true - }, - "tar": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", - "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", - "dev": true, - "requires": { - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "minipass": "^5.0.0", - "minizlib": "^2.1.1", - "mkdirp": "^1.0.3", - "yallist": "^4.0.0" - } - } } }, "co": { @@ -2339,13 +1497,6 @@ "requires": { "leven": "^2.1.0", "minimist": "^1.1.0" - }, - "dependencies": { - "leven": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/leven/-/leven-2.1.0.tgz", - "integrity": "sha512-nvVPLpIHUxCUoRLrFqTgSxXJ614d8AgQoWl7zPe/2VadE8+1dpU3LBhowRuBAcuwruWtOdD8oYC9jDNJjXDPyA==" - } } }, "concat-map": { @@ -2454,9 +1605,9 @@ } }, "debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", + "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", "requires": { "ms": "2.1.2" } @@ -2547,16 +1698,10 @@ "stream-shift": "^1.0.0" } }, - "eastasianwidth": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", - "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", - "dev": true - }, "electron-to-chromium": { - "version": "1.4.669", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.669.tgz", - "integrity": "sha512-E2SmpffFPrZhBSgf8ibqanRS2mpuk3FIRDzLDwt7WFpfgJMKDHJs0hmacyP0PS1cWsq0dVkwIIzlscNaterkPg==", + "version": "1.5.12", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.12.tgz", + "integrity": "sha512-tIhPkdlEoCL1Y+PToq3zRNehUaKp3wBX/sr7aclAWdIWjvqAe/Im/H0SiCM4c1Q8BLPHCdoJTol+ZblflydehA==", "dev": true }, "emittery": { @@ -2748,6 +1893,15 @@ "pend": "~1.2.0" } }, + "fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, "find-file-up": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/find-file-up/-/find-file-up-0.1.3.tgz", @@ -2789,10 +1943,9 @@ } }, "follow-redirects": { - "version": "1.15.4", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.4.tgz", - "integrity": "sha512-Cr4D/5wlrb0z9dgERpUL3LrmPKVDsETIJhaCMeDfuFYcqa5bldGV6wBsAN6X/vxlXQtFBMrXdXxdL8CbDTGniw==", - "dev": true + "version": "1.15.6", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", + "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==" }, "for-each": { "version": "0.3.3", @@ -2818,29 +1971,10 @@ "for-in": "^1.0.1" } }, - "foreground-child": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.2.1.tgz", - "integrity": "sha512-PXUUyLqrR2XCWICfv6ukppP96sdFwWbNEnfEMt7jNsISjMsvaLNinAHNDYyvkyU+SZG2BTSbT5NjG+vZslfGTA==", - "dev": true, - "requires": { - "cross-spawn": "^7.0.0", - "signal-exit": "^4.0.1" - }, - "dependencies": { - "signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "dev": true - } - } - }, "form-data": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz", - "integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==", - "dev": true, + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", "requires": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", @@ -3044,9 +2178,9 @@ } }, "has-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", - "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", + "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", "dev": true }, "has-symbols": { @@ -3071,9 +2205,9 @@ "dev": true }, "hasown": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.1.tgz", - "integrity": "sha512-1/th4MHjnwncwXsIW6QMzlvYL9kG5e/CpVvLRZe4XPa8TOUNbCELqmvhDmnkNsAjwaG4+I8gJJL0JBvTTLO9qA==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", "dev": true, "requires": { "function-bind": "^1.1.2" @@ -3136,24 +2270,13 @@ } }, "https-proxy-agent": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.4.tgz", - "integrity": "sha512-wlwpilI7YdjSkWaQ/7omYBMTliDcmCN8OLihO6I9B86g06lMyAoqgoDpV0XqoaPOKj+0DIdAvnsWfyAAhmimcg==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", "dev": true, "requires": { - "agent-base": "^7.0.2", + "agent-base": "6", "debug": "4" - }, - "dependencies": { - "agent-base": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", - "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", - "dev": true, - "requires": { - "debug": "^4.3.4" - } - } } }, "human-signals": { @@ -3172,14 +2295,14 @@ } }, "ieee754": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", - "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==" }, "import-local": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", - "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.2.0.tgz", + "integrity": "sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==", "dev": true, "requires": { "pkg-dir": "^4.2.0", @@ -3241,12 +2364,12 @@ "dev": true }, "is-core-module": { - "version": "2.13.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", - "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", + "version": "2.15.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.0.tgz", + "integrity": "sha512-Dd+Lb2/zvk9SKy1TGCt1wFJFo/MWBPMX5x7KcvLajWTGuomczdQX61PvY5yK6SVACwpoexWo81IfFyoKY2QnTA==", "dev": true, "requires": { - "hasown": "^2.0.0" + "hasown": "^2.0.2" } }, "is-extendable": { @@ -3344,8 +2467,7 @@ "isomorphic-ws": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/isomorphic-ws/-/isomorphic-ws-4.0.1.tgz", - "integrity": "sha512-BhBvN2MBpWTaSHdWRb/bwdZJ1WaehQ2L1KngkCkfLUGF0mAWAT1sQUQacEmQ0jXkFw/czDXPNQSL5u2/Krsz1w==", - "requires": {} + "integrity": "sha512-BhBvN2MBpWTaSHdWRb/bwdZJ1WaehQ2L1KngkCkfLUGF0mAWAT1sQUQacEmQ0jXkFw/czDXPNQSL5u2/Krsz1w==" }, "istanbul-lib-coverage": { "version": "3.2.2", @@ -3397,25 +2519,15 @@ } }, "istanbul-reports": { - "version": "3.1.6", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.6.tgz", - "integrity": "sha512-TLgnMkKg3iTDsQ9PbPTdpfAK2DzjF9mqUG7RMgcQl8oFjad8ob4laGxv5XV5U9MAfx8D6tSJiUyuAwzLicaxlg==", + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.7.tgz", + "integrity": "sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==", "dev": true, "requires": { "html-escaper": "^2.0.0", "istanbul-lib-report": "^3.0.0" } }, - "jackspeak": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.0.tgz", - "integrity": "sha512-JVYhQnN59LVPFCEcVa2C3CrEKYacvjRfqIQl+h8oi91aLYQVWRYbxjPcv1bUiUy/kLmQaANrYfNMCO3kuEDHfw==", - "dev": true, - "requires": { - "@isaacs/cliui": "^8.0.2", - "@pkgjs/parseargs": "^0.11.0" - } - }, "jest": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest/-/jest-27.5.1.tgz", @@ -3517,49 +2629,6 @@ "slash": "^3.0.0", "stack-utils": "^2.0.3", "throat": "^6.0.1" - }, - "dependencies": { - "@jest/globals": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-27.5.1.tgz", - "integrity": "sha512-ZEJNB41OBQQgGzgyInAv0UUfDDj3upmHydjieSxFvTRuZElrx7tXg/uVQ5hYVEwiXs3+aMsAeEc9X7xiSKCm4Q==", - "dev": true, - "requires": { - "@jest/environment": "^27.5.1", - "@jest/types": "^27.5.1", - "expect": "^27.5.1" - } - }, - "jest-runtime": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-27.5.1.tgz", - "integrity": "sha512-o7gxw3Gf+H2IGt8fv0RiyE1+r83FJBRruoA+FXrlHw6xEyBsU8ugA6IPfTdVyA0w8HClpbK+DGJxH59UrNMx8A==", - "dev": true, - "requires": { - "@jest/environment": "^27.5.1", - "@jest/fake-timers": "^27.5.1", - "@jest/globals": "^27.5.1", - "@jest/source-map": "^27.5.1", - "@jest/test-result": "^27.5.1", - "@jest/transform": "^27.5.1", - "@jest/types": "^27.5.1", - "chalk": "^4.0.0", - "cjs-module-lexer": "^1.0.0", - "collect-v8-coverage": "^1.0.0", - "execa": "^5.0.0", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^27.5.1", - "jest-message-util": "^27.5.1", - "jest-mock": "^27.5.1", - "jest-regex-util": "^27.5.1", - "jest-resolve": "^27.5.1", - "jest-snapshot": "^27.5.1", - "jest-util": "^27.5.1", - "slash": "^3.0.0", - "strip-bom": "^4.0.0" - } - } } }, "jest-config": { @@ -3743,49 +2812,6 @@ "jest-util": "^27.5.1", "pretty-format": "^27.5.1", "throat": "^6.0.1" - }, - "dependencies": { - "@jest/globals": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-27.5.1.tgz", - "integrity": "sha512-ZEJNB41OBQQgGzgyInAv0UUfDDj3upmHydjieSxFvTRuZElrx7tXg/uVQ5hYVEwiXs3+aMsAeEc9X7xiSKCm4Q==", - "dev": true, - "requires": { - "@jest/environment": "^27.5.1", - "@jest/types": "^27.5.1", - "expect": "^27.5.1" - } - }, - "jest-runtime": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-27.5.1.tgz", - "integrity": "sha512-o7gxw3Gf+H2IGt8fv0RiyE1+r83FJBRruoA+FXrlHw6xEyBsU8ugA6IPfTdVyA0w8HClpbK+DGJxH59UrNMx8A==", - "dev": true, - "requires": { - "@jest/environment": "^27.5.1", - "@jest/fake-timers": "^27.5.1", - "@jest/globals": "^27.5.1", - "@jest/source-map": "^27.5.1", - "@jest/test-result": "^27.5.1", - "@jest/transform": "^27.5.1", - "@jest/types": "^27.5.1", - "chalk": "^4.0.0", - "cjs-module-lexer": "^1.0.0", - "collect-v8-coverage": "^1.0.0", - "execa": "^5.0.0", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^27.5.1", - "jest-message-util": "^27.5.1", - "jest-mock": "^27.5.1", - "jest-regex-util": "^27.5.1", - "jest-resolve": "^27.5.1", - "jest-snapshot": "^27.5.1", - "jest-util": "^27.5.1", - "slash": "^3.0.0", - "strip-bom": "^4.0.0" - } - } } }, "jest-leak-detector": { @@ -3841,531 +2867,110 @@ "version": "1.2.3", "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", - "dev": true, - "requires": {} - }, - "jest-puppeteer": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/jest-puppeteer/-/jest-puppeteer-5.0.4.tgz", - "integrity": "sha512-IUOVKgHEaKsLqahZy/J/DvXB59SQx4AVpZKTRDvJzCdkvdGc3NVsNwUhovr6SK+HOK1TOiqAiXPTAPiIq3mkrg==", - "dev": true, - "requires": { - "expect-puppeteer": "^5.0.4", - "jest-environment-puppeteer": "^5.0.4" - } - }, - "jest-regex-util": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-27.5.1.tgz", - "integrity": "sha512-4bfKq2zie+x16okqDXjXn9ql2B0dScQu+vcwe4TvFVhkVyuWLqpZrZtXxLLWoXYgn0E87I6r6GRYHF7wFZBUvg==", "dev": true - }, - "jest-resolve": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-27.5.1.tgz", - "integrity": "sha512-FFDy8/9E6CV83IMbDpcjOhumAQPDyETnU2KZ1O98DwTnz8AOBsW/Xv3GySr1mOZdItLR+zDZ7I/UdTFbgSOVCw==", - "dev": true, - "requires": { - "@jest/types": "^27.5.1", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^27.5.1", - "jest-pnp-resolver": "^1.2.2", - "jest-util": "^27.5.1", - "jest-validate": "^27.5.1", - "resolve": "^1.20.0", - "resolve.exports": "^1.1.0", - "slash": "^3.0.0" - } - }, - "jest-resolve-dependencies": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-27.5.1.tgz", - "integrity": "sha512-QQOOdY4PE39iawDn5rzbIePNigfe5B9Z91GDD1ae/xNDlu9kaat8QQ5EKnNmVWPV54hUdxCVwwj6YMgR2O7IOg==", - "dev": true, - "requires": { - "@jest/types": "^27.5.1", - "jest-regex-util": "^27.5.1", - "jest-snapshot": "^27.5.1" - } - }, - "jest-runner": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-27.5.1.tgz", - "integrity": "sha512-g4NPsM4mFCOwFKXO4p/H/kWGdJp9V8kURY2lX8Me2drgXqG7rrZAx5kv+5H7wtt/cdFIjhqYx1HrlqWHaOvDaQ==", - "dev": true, - "requires": { - "@jest/console": "^27.5.1", - "@jest/environment": "^27.5.1", - "@jest/test-result": "^27.5.1", - "@jest/transform": "^27.5.1", - "@jest/types": "^27.5.1", - "@types/node": "*", - "chalk": "^4.0.0", - "emittery": "^0.8.1", - "graceful-fs": "^4.2.9", - "jest-docblock": "^27.5.1", - "jest-environment-jsdom": "^27.5.1", - "jest-environment-node": "^27.5.1", - "jest-haste-map": "^27.5.1", - "jest-leak-detector": "^27.5.1", - "jest-message-util": "^27.5.1", - "jest-resolve": "^27.5.1", - "jest-runtime": "^27.5.1", - "jest-util": "^27.5.1", - "jest-worker": "^27.5.1", - "source-map-support": "^0.5.6", - "throat": "^6.0.1" - }, - "dependencies": { - "@jest/globals": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-27.5.1.tgz", - "integrity": "sha512-ZEJNB41OBQQgGzgyInAv0UUfDDj3upmHydjieSxFvTRuZElrx7tXg/uVQ5hYVEwiXs3+aMsAeEc9X7xiSKCm4Q==", - "dev": true, - "requires": { - "@jest/environment": "^27.5.1", - "@jest/types": "^27.5.1", - "expect": "^27.5.1" - } - }, - "jest-runtime": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-27.5.1.tgz", - "integrity": "sha512-o7gxw3Gf+H2IGt8fv0RiyE1+r83FJBRruoA+FXrlHw6xEyBsU8ugA6IPfTdVyA0w8HClpbK+DGJxH59UrNMx8A==", - "dev": true, - "requires": { - "@jest/environment": "^27.5.1", - "@jest/fake-timers": "^27.5.1", - "@jest/globals": "^27.5.1", - "@jest/source-map": "^27.5.1", - "@jest/test-result": "^27.5.1", - "@jest/transform": "^27.5.1", - "@jest/types": "^27.5.1", - "chalk": "^4.0.0", - "cjs-module-lexer": "^1.0.0", - "collect-v8-coverage": "^1.0.0", - "execa": "^5.0.0", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^27.5.1", - "jest-message-util": "^27.5.1", - "jest-mock": "^27.5.1", - "jest-regex-util": "^27.5.1", - "jest-resolve": "^27.5.1", - "jest-snapshot": "^27.5.1", - "jest-util": "^27.5.1", - "slash": "^3.0.0", - "strip-bom": "^4.0.0" - } - } - } - }, - "jest-runtime": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.7.0.tgz", - "integrity": "sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==", - "dev": true, - "requires": { - "@jest/environment": "^29.7.0", - "@jest/fake-timers": "^29.7.0", - "@jest/globals": "^29.7.0", - "@jest/source-map": "^29.6.3", - "@jest/test-result": "^29.7.0", - "@jest/transform": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "cjs-module-lexer": "^1.0.0", - "collect-v8-coverage": "^1.0.0", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-mock": "^29.7.0", - "jest-regex-util": "^29.6.3", - "jest-resolve": "^29.7.0", - "jest-snapshot": "^29.7.0", - "jest-util": "^29.7.0", - "slash": "^3.0.0", - "strip-bom": "^4.0.0" - }, - "dependencies": { - "@jest/console": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz", - "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==", - "dev": true, - "requires": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "jest-message-util": "^29.7.0", - "jest-util": "^29.7.0", - "slash": "^3.0.0" - } - }, - "@jest/environment": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", - "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", - "dev": true, - "requires": { - "@jest/fake-timers": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "jest-mock": "^29.7.0" - } - }, - "@jest/fake-timers": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz", - "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", - "dev": true, - "requires": { - "@jest/types": "^29.6.3", - "@sinonjs/fake-timers": "^10.0.2", - "@types/node": "*", - "jest-message-util": "^29.7.0", - "jest-mock": "^29.7.0", - "jest-util": "^29.7.0" - } - }, - "@jest/source-map": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz", - "integrity": "sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==", - "dev": true, - "requires": { - "@jridgewell/trace-mapping": "^0.3.18", - "callsites": "^3.0.0", - "graceful-fs": "^4.2.9" - } - }, - "@jest/test-result": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz", - "integrity": "sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==", - "dev": true, - "requires": { - "@jest/console": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "collect-v8-coverage": "^1.0.0" - } - }, - "@jest/transform": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", - "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", - "dev": true, - "requires": { - "@babel/core": "^7.11.6", - "@jest/types": "^29.6.3", - "@jridgewell/trace-mapping": "^0.3.18", - "babel-plugin-istanbul": "^6.1.1", - "chalk": "^4.0.0", - "convert-source-map": "^2.0.0", - "fast-json-stable-stringify": "^2.1.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.7.0", - "jest-regex-util": "^29.6.3", - "jest-util": "^29.7.0", - "micromatch": "^4.0.4", - "pirates": "^4.0.4", - "slash": "^3.0.0", - "write-file-atomic": "^4.0.2" - } - }, - "@jest/types": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", - "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", - "dev": true, - "requires": { - "@jest/schemas": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" - } - }, - "@sinonjs/commons": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", - "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", - "dev": true, - "requires": { - "type-detect": "4.0.8" - } - }, - "@sinonjs/fake-timers": { - "version": "10.3.0", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", - "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", - "dev": true, - "requires": { - "@sinonjs/commons": "^3.0.0" - } - }, - "@types/yargs": { - "version": "17.0.32", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.32.tgz", - "integrity": "sha512-xQ67Yc/laOG5uMfX/093MRlGGCIBzZMarVa+gfNKJxWAIgykYpVGkBdbqEzGDDfCrVUj6Hiff4mTZ5BA6TmAog==", - "dev": true, - "requires": { - "@types/yargs-parser": "*" - } - }, - "ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true - }, - "camelcase": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", - "dev": true - }, - "convert-source-map": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", - "dev": true - }, - "diff-sequences": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", - "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", - "dev": true - }, - "expect": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz", - "integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==", - "dev": true, - "requires": { - "@jest/expect-utils": "^29.7.0", - "jest-get-type": "^29.6.3", - "jest-matcher-utils": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-util": "^29.7.0" - } - }, - "jest-diff": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", - "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", - "dev": true, - "requires": { - "chalk": "^4.0.0", - "diff-sequences": "^29.6.3", - "jest-get-type": "^29.6.3", - "pretty-format": "^29.7.0" - } - }, - "jest-get-type": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", - "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", - "dev": true - }, - "jest-haste-map": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz", - "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==", - "dev": true, - "requires": { - "@jest/types": "^29.6.3", - "@types/graceful-fs": "^4.1.3", - "@types/node": "*", - "anymatch": "^3.0.3", - "fb-watchman": "^2.0.0", - "fsevents": "^2.3.2", - "graceful-fs": "^4.2.9", - "jest-regex-util": "^29.6.3", - "jest-util": "^29.7.0", - "jest-worker": "^29.7.0", - "micromatch": "^4.0.4", - "walker": "^1.0.8" - } - }, - "jest-matcher-utils": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz", - "integrity": "sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==", - "dev": true, - "requires": { - "chalk": "^4.0.0", - "jest-diff": "^29.7.0", - "jest-get-type": "^29.6.3", - "pretty-format": "^29.7.0" - } - }, - "jest-message-util": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", - "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.12.13", - "@jest/types": "^29.6.3", - "@types/stack-utils": "^2.0.0", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "micromatch": "^4.0.4", - "pretty-format": "^29.7.0", - "slash": "^3.0.0", - "stack-utils": "^2.0.3" - } - }, - "jest-mock": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz", - "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==", - "dev": true, - "requires": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "jest-util": "^29.7.0" - } - }, - "jest-regex-util": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", - "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", - "dev": true - }, - "jest-resolve": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.7.0.tgz", - "integrity": "sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==", - "dev": true, - "requires": { - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.7.0", - "jest-pnp-resolver": "^1.2.2", - "jest-util": "^29.7.0", - "jest-validate": "^29.7.0", - "resolve": "^1.20.0", - "resolve.exports": "^2.0.0", - "slash": "^3.0.0" - } - }, - "jest-snapshot": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.7.0.tgz", - "integrity": "sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==", - "dev": true, - "requires": { - "@babel/core": "^7.11.6", - "@babel/generator": "^7.7.2", - "@babel/plugin-syntax-jsx": "^7.7.2", - "@babel/plugin-syntax-typescript": "^7.7.2", - "@babel/types": "^7.3.3", - "@jest/expect-utils": "^29.7.0", - "@jest/transform": "^29.7.0", - "@jest/types": "^29.6.3", - "babel-preset-current-node-syntax": "^1.0.0", - "chalk": "^4.0.0", - "expect": "^29.7.0", - "graceful-fs": "^4.2.9", - "jest-diff": "^29.7.0", - "jest-get-type": "^29.6.3", - "jest-matcher-utils": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-util": "^29.7.0", - "natural-compare": "^1.4.0", - "pretty-format": "^29.7.0", - "semver": "^7.5.3" - } - }, - "jest-util": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", - "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", - "dev": true, - "requires": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "graceful-fs": "^4.2.9", - "picomatch": "^2.2.3" - } - }, - "jest-validate": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz", - "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==", - "dev": true, - "requires": { - "@jest/types": "^29.6.3", - "camelcase": "^6.2.0", - "chalk": "^4.0.0", - "jest-get-type": "^29.6.3", - "leven": "^3.1.0", - "pretty-format": "^29.7.0" - } - }, - "jest-worker": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", - "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", - "dev": true, - "requires": { - "@types/node": "*", - "jest-util": "^29.7.0", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" - } - }, - "pretty-format": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", - "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", - "dev": true, - "requires": { - "@jest/schemas": "^29.6.3", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - } - }, - "react-is": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", - "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", - "dev": true - }, - "resolve.exports": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.2.tgz", - "integrity": "sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==", - "dev": true - }, - "supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - }, - "write-file-atomic": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", - "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", - "dev": true, - "requires": { - "imurmurhash": "^0.1.4", - "signal-exit": "^3.0.7" - } - } + }, + "jest-puppeteer": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/jest-puppeteer/-/jest-puppeteer-5.0.4.tgz", + "integrity": "sha512-IUOVKgHEaKsLqahZy/J/DvXB59SQx4AVpZKTRDvJzCdkvdGc3NVsNwUhovr6SK+HOK1TOiqAiXPTAPiIq3mkrg==", + "dev": true, + "requires": { + "expect-puppeteer": "^5.0.4", + "jest-environment-puppeteer": "^5.0.4" + } + }, + "jest-regex-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-27.5.1.tgz", + "integrity": "sha512-4bfKq2zie+x16okqDXjXn9ql2B0dScQu+vcwe4TvFVhkVyuWLqpZrZtXxLLWoXYgn0E87I6r6GRYHF7wFZBUvg==", + "dev": true + }, + "jest-resolve": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-27.5.1.tgz", + "integrity": "sha512-FFDy8/9E6CV83IMbDpcjOhumAQPDyETnU2KZ1O98DwTnz8AOBsW/Xv3GySr1mOZdItLR+zDZ7I/UdTFbgSOVCw==", + "dev": true, + "requires": { + "@jest/types": "^27.5.1", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^27.5.1", + "jest-pnp-resolver": "^1.2.2", + "jest-util": "^27.5.1", + "jest-validate": "^27.5.1", + "resolve": "^1.20.0", + "resolve.exports": "^1.1.0", + "slash": "^3.0.0" + } + }, + "jest-resolve-dependencies": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-27.5.1.tgz", + "integrity": "sha512-QQOOdY4PE39iawDn5rzbIePNigfe5B9Z91GDD1ae/xNDlu9kaat8QQ5EKnNmVWPV54hUdxCVwwj6YMgR2O7IOg==", + "dev": true, + "requires": { + "@jest/types": "^27.5.1", + "jest-regex-util": "^27.5.1", + "jest-snapshot": "^27.5.1" + } + }, + "jest-runner": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-27.5.1.tgz", + "integrity": "sha512-g4NPsM4mFCOwFKXO4p/H/kWGdJp9V8kURY2lX8Me2drgXqG7rrZAx5kv+5H7wtt/cdFIjhqYx1HrlqWHaOvDaQ==", + "dev": true, + "requires": { + "@jest/console": "^27.5.1", + "@jest/environment": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/transform": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "emittery": "^0.8.1", + "graceful-fs": "^4.2.9", + "jest-docblock": "^27.5.1", + "jest-environment-jsdom": "^27.5.1", + "jest-environment-node": "^27.5.1", + "jest-haste-map": "^27.5.1", + "jest-leak-detector": "^27.5.1", + "jest-message-util": "^27.5.1", + "jest-resolve": "^27.5.1", + "jest-runtime": "^27.5.1", + "jest-util": "^27.5.1", + "jest-worker": "^27.5.1", + "source-map-support": "^0.5.6", + "throat": "^6.0.1" + } + }, + "jest-runtime": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-27.5.1.tgz", + "integrity": "sha512-o7gxw3Gf+H2IGt8fv0RiyE1+r83FJBRruoA+FXrlHw6xEyBsU8ugA6IPfTdVyA0w8HClpbK+DGJxH59UrNMx8A==", + "dev": true, + "requires": { + "@jest/environment": "^27.5.1", + "@jest/fake-timers": "^27.5.1", + "@jest/globals": "^27.5.1", + "@jest/source-map": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/transform": "^27.5.1", + "@jest/types": "^27.5.1", + "chalk": "^4.0.0", + "cjs-module-lexer": "^1.0.0", + "collect-v8-coverage": "^1.0.0", + "execa": "^5.0.0", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^27.5.1", + "jest-message-util": "^27.5.1", + "jest-mock": "^27.5.1", + "jest-regex-util": "^27.5.1", + "jest-resolve": "^27.5.1", + "jest-snapshot": "^27.5.1", + "jest-util": "^27.5.1", + "slash": "^3.0.0", + "strip-bom": "^4.0.0" } }, "jest-serializer": { @@ -4441,6 +3046,12 @@ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", "dev": true + }, + "leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "dev": true } } }, @@ -4488,9 +3099,9 @@ "dev": true }, "joi": { - "version": "17.12.1", - "resolved": "https://registry.npmjs.org/joi/-/joi-17.12.1.tgz", - "integrity": "sha512-vtxmq+Lsc5SlfqotnfVjlViWfOL9nt/avKNbKYizwf6gsCfq9NYY/ceYRMFD8XDdrjJ9abJyScWmhmIiy+XRtQ==", + "version": "17.13.3", + "resolved": "https://registry.npmjs.org/joi/-/joi-17.13.3.tgz", + "integrity": "sha512-otDA4ldcIx+ZXsKHWmp0YizCweVRZG96J10b0FevjfuncLO1oX59THoAmHkNubYJ+9gWsYsp5k8v4ib6oDv1fA==", "dev": true, "requires": { "@hapi/hoek": "^9.3.0", @@ -4556,22 +3167,22 @@ "xml-name-validator": "^3.0.0" }, "dependencies": { - "https-proxy-agent": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", - "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "form-data": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz", + "integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==", "dev": true, "requires": { - "agent-base": "6", - "debug": "4" + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" } }, "ws": { "version": "7.5.10", "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", - "dev": true, - "requires": {} + "dev": true } } }, @@ -4594,9 +3205,9 @@ "dev": true }, "jsonc-parser": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.1.tgz", - "integrity": "sha512-AilxAyFOAcK5wA1+LeaySVBrHsGQvUFCDWXKpZjzaL0PqW+xfBOttn8GNtWKFWqneyMZj41MWF9Kl6iPWLwgOA==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.3.1.tgz", + "integrity": "sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==", "dev": true }, "jsonfile": { @@ -4631,10 +3242,9 @@ "dev": true }, "leven": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", - "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", - "dev": true + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-2.1.0.tgz", + "integrity": "sha512-nvVPLpIHUxCUoRLrFqTgSxXJ614d8AgQoWl7zPe/2VadE8+1dpU3LBhowRuBAcuwruWtOdD8oYC9jDNJjXDPyA==" }, "lines-and-columns": { "version": "1.2.4", @@ -4673,7 +3283,6 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, "requires": { "yallist": "^4.0.0" } @@ -4754,12 +3363,12 @@ "dev": true }, "micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.7.tgz", + "integrity": "sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==", "dev": true, "requires": { - "braces": "^3.0.2", + "braces": "^3.0.3", "picomatch": "^2.3.1" } }, @@ -4802,60 +3411,28 @@ "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==" }, "minipass": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", - "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", "dev": true }, "minizlib": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.0.1.tgz", - "integrity": "sha512-umcy022ILvb5/3Djuu8LWeqUa8D68JaBzlttKeMWen48SjabqS3iY5w/vzeMzMUNhLDifyhbOwKDSznB1vvrwg==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", "dev": true, "requires": { - "minipass": "^7.0.4", - "rimraf": "^5.0.5" + "minipass": "^3.0.0", + "yallist": "^4.0.0" }, "dependencies": { - "brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0" - } - }, - "glob": { - "version": "10.4.2", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.2.tgz", - "integrity": "sha512-GwMlUF6PkPo3Gk21UxkCohOv0PLcIXVtKyLlpEI28R/cO/4eNOdmLk3CMW1wROV/WR/EsZOWAfBbBOqYvs88/w==", - "dev": true, - "requires": { - "foreground-child": "^3.1.0", - "jackspeak": "^3.1.2", - "minimatch": "^9.0.4", - "minipass": "^7.1.2", - "package-json-from-dist": "^1.0.0", - "path-scurry": "^1.11.1" - } - }, - "minimatch": { - "version": "9.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz", - "integrity": "sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==", - "dev": true, - "requires": { - "brace-expansion": "^2.0.1" - } - }, - "rimraf": { - "version": "5.0.7", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.7.tgz", - "integrity": "sha512-nV6YcJo5wbLW77m+8KjH8aB/7/rxQy9SZ0HY5shnwULfS+9nmTtVXAJET5NdZmCzA4fPI/Hm1wo/Po/4mopOdg==", + "minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", "dev": true, "requires": { - "glob": "^10.3.7" + "yallist": "^4.0.0" } } } @@ -4879,9 +3456,15 @@ } }, "mkdirp": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-3.0.1.tgz", - "integrity": "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true + }, + "mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==", "dev": true }, "mqtt": { @@ -4909,22 +3492,14 @@ }, "dependencies": { "duplexify": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.2.tgz", - "integrity": "sha512-fz3OjcNCHmRP12MJoZMPglx8m4rrFP8rovnk4vT8Fs+aonZoCwGg10dSsQsfP/E62eZcPTMSMP6686fu9Qlqtw==", + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.3.tgz", + "integrity": "sha512-M3BmBhwJRZsSx38lZyhE53Csddgzl5R7xGJNk7CVddZD6CcmwMCH8J+7AprIrQKH7TonKxaCjcv27Qmf+sQ+oA==", "requires": { "end-of-stream": "^1.4.1", "inherits": "^2.0.3", "readable-stream": "^3.1.1", - "stream-shift": "^1.0.0" - } - }, - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "requires": { - "yallist": "^4.0.0" + "stream-shift": "^1.0.2" } }, "readable-stream": { @@ -4940,13 +3515,7 @@ "ws": { "version": "7.5.10", "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", - "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", - "requires": {} - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==" } } }, @@ -4972,9 +3541,9 @@ "dev": true }, "node-api-headers": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/node-api-headers/-/node-api-headers-1.1.0.tgz", - "integrity": "sha512-ucQW+SbYCUPfprvmzBsnjT034IGRB2XK8rRc78BgjNKhTdFKgAwAmgW704bKIBmcYW48it0Gkjpkd39Azrwquw==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/node-api-headers/-/node-api-headers-1.2.0.tgz", + "integrity": "sha512-L9AiEkBfgupC0D/LsudLPOhzy/EdObsp+FHyL1zSK0kKv5FDA9rJMoRz8xd+ojxzlqfg0tTZm2h8ot2nS7bgRA==", "dev": true }, "node-int64": { @@ -4984,9 +3553,9 @@ "dev": true }, "node-releases": { - "version": "2.0.14", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", - "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==", + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.18.tgz", + "integrity": "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==", "dev": true }, "normalize-path": { @@ -5026,9 +3595,9 @@ } }, "nwsapi": { - "version": "2.2.7", - "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.7.tgz", - "integrity": "sha512-ub5E4+FBPKwAZx0UwIQOjYWGHTEq5sPqHQNRN8Z9e4A7u3Tj1weLJsL59yH9vmvqEtBHaOmT6cYQKIZOxp35FQ==", + "version": "2.2.12", + "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.12.tgz", + "integrity": "sha512-qXDmcVlZV4XRtKFzddidpfVP4oMSGhga+xdMc25mv8kaLUHtgzCDhUxkrN8exkGdTlLNaXj7CV3GtON7zuGZ+w==", "dev": true }, "once": { @@ -5078,12 +3647,6 @@ "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", "dev": true }, - "package-json-from-dist": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.0.tgz", - "integrity": "sha512-dATvCeZN/8wQsGywez1mzHtTlP22H8OEfPrVMLNr4/eGa+ijtLn/6M5f0dY8UKNrC2O9UCU6SSoG3qRKnt7STw==", - "dev": true - }, "parse-json": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", @@ -5131,24 +3694,6 @@ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", "dev": true }, - "path-scurry": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", - "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", - "dev": true, - "requires": { - "lru-cache": "^10.2.0", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" - }, - "dependencies": { - "lru-cache": { - "version": "10.2.2", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.2.tgz", - "integrity": "sha512-9hp3Vp2/hFQUiIwKo8XCeFVnrg8Pk3TYNPIR7tJADKi5YfcF7vEaK7avFHTlSy3kOKYaJQaalfEo6YuXdceBOQ==", - "dev": true - } - } - }, "pend": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", @@ -5156,9 +3701,9 @@ "dev": true }, "picocolors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz", + "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==", "dev": true }, "picomatch": { @@ -5182,6 +3727,12 @@ "find-up": "^4.0.0" } }, + "possible-typed-array-names": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", + "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==", + "dev": true + }, "pretty-format": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", @@ -5212,9 +3763,9 @@ "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" }, "progress": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.1.tgz", - "integrity": "sha512-OE+a6vzqazc+K6LxJrX5UPyKFvGnL5CYmq2jFGNIBWHpc4QyE49/YOumcrpQFJpfejmvRtbJzgO1zPmMCqlbBg==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", "dev": true }, "prompts": { @@ -5291,8 +3842,7 @@ "version": "7.5.10", "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", - "dev": true, - "requires": {} + "dev": true } } }, @@ -5407,9 +3957,9 @@ "dev": true }, "rfdc": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.1.tgz", - "integrity": "sha512-r5a3l5HzYlIC68TpmYKlxWjmOP6wiPJ1vWv2HeLhNsRZMrCkxeqxiHlQ21oXmQ4F3SiryXBHhAD7JZqvOJjFmg==" + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz", + "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==" }, "rimraf": { "version": "3.0.2", @@ -5464,13 +4014,10 @@ } }, "semver": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", - "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - } + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "dev": true }, "set-blocking": { "version": "2.0.0", @@ -5479,17 +4026,17 @@ "dev": true }, "set-function-length": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.1.tgz", - "integrity": "sha512-j4t6ccc+VsKwYHso+kElc5neZpjtq9EnRICFZtWyBsLojhmeF/ZBd/elqm22WJh/BziDe/SBiOeAt0m2mfLD0g==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", "dev": true, "requires": { - "define-data-property": "^1.1.2", + "define-data-property": "^1.1.4", "es-errors": "^1.3.0", "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.3", + "get-intrinsic": "^1.2.4", "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.1" + "has-property-descriptors": "^1.0.2" } }, "shallow-clone": { @@ -5642,21 +4189,6 @@ "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.3.tgz", "integrity": "sha512-76ORR0DO1o1hlKwTbi/DM3EXWGf3ZJYO8cXX5RJwnul2DEg2oyoZyjLNoQM8WsvZiFKCRfC1O0J7iCvie3RZmQ==" }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - }, - "dependencies": { - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - } - } - }, "string-length": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", @@ -5678,15 +4210,19 @@ "strip-ansi": "^6.0.1" } }, - "string-width-cjs": { - "version": "npm:string-width@4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" + "safe-buffer": "~5.1.0" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + } } }, "strip-ansi": { @@ -5698,15 +4234,6 @@ "ansi-regex": "^5.0.1" } }, - "strip-ansi-cjs": { - "version": "npm:strip-ansi@6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "requires": { - "ansi-regex": "^5.0.1" - } - }, "strip-bom": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", @@ -5757,37 +4284,29 @@ "dev": true }, "tar": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/tar/-/tar-7.4.0.tgz", - "integrity": "sha512-XQs0S8fuAkQWuqhDeCdMlJXDX80D7EOVLDPVFkna9yQfzS+PHKgfxcei0jf6/+QAWcjqrnC8uM3fSAnrQl+XYg==", + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", + "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", "dev": true, "requires": { - "@isaacs/fs-minipass": "^4.0.0", - "chownr": "^3.0.0", - "minipass": "^7.1.2", - "minizlib": "^3.0.1", - "mkdirp": "^3.0.1", - "yallist": "^5.0.0" - }, - "dependencies": { - "yallist": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz", - "integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==", - "dev": true - } + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" } }, "tar-fs": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.0.0.tgz", - "integrity": "sha512-vaY0obB6Om/fso8a8vakQBzwholQ7v5+uy+tF3Ozvxv1KNezmVQAiWtcNmMHFSFPqL3dJA8ha6gdtFbfX9mcxA==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", + "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", "dev": true, "requires": { "chownr": "^1.1.1", - "mkdirp": "^0.5.1", + "mkdirp-classic": "^0.5.2", "pump": "^3.0.0", - "tar-stream": "^2.0.0" + "tar-stream": "^2.1.4" }, "dependencies": { "chownr": { @@ -5795,15 +4314,6 @@ "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", "dev": true - }, - "mkdirp": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", - "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", - "dev": true, - "requires": { - "minimist": "^1.2.6" - } } } }, @@ -5888,9 +4398,9 @@ } }, "tough-cookie": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.3.tgz", - "integrity": "sha512-aX/y5pVRkfRnfmuX+OdbSdXvPe6ieKX/G2s7e98f4poJHnqH3281gDPm/metm6E/WRamfx7WC4HUqkWHfQHprw==", + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.4.tgz", + "integrity": "sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag==", "dev": true, "requires": { "psl": "^1.1.33", @@ -5961,9 +4471,9 @@ } }, "tslib": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", - "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz", + "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==" }, "type-detect": { "version": "4.0.8", @@ -5992,15 +4502,15 @@ } }, "typedoc": { - "version": "0.25.13", - "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.25.13.tgz", - "integrity": "sha512-pQqiwiJ+Z4pigfOnnysObszLiU3mVLWAExSPf+Mu06G/qsc3wzbuM56SZQvONhHLncLUhYzOVkjFFpFfL5AzhQ==", + "version": "0.24.8", + "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.24.8.tgz", + "integrity": "sha512-ahJ6Cpcvxwaxfu4KtjA8qZNqS43wYt6JL27wYiIgl1vd38WW/KWX11YuAeZhuz9v+ttrutSsgK+XO1CjL1kA3w==", "dev": true, "requires": { "lunr": "^2.3.9", "marked": "^4.3.0", - "minimatch": "^9.0.3", - "shiki": "^0.14.7" + "minimatch": "^9.0.0", + "shiki": "^0.14.1" }, "dependencies": { "brace-expansion": { @@ -6013,9 +4523,9 @@ } }, "minimatch": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", - "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", "dev": true, "requires": { "brace-expansion": "^2.0.1" @@ -6027,19 +4537,18 @@ "version": "5.1.0", "resolved": "https://registry.npmjs.org/typedoc-plugin-merge-modules/-/typedoc-plugin-merge-modules-5.1.0.tgz", "integrity": "sha512-jXH27L/wlxFjErgBXleh3opVgjVTXFEuBo68Yfl18S9Oh/IqxK6NV94jlEJ9hl4TXc9Zm2l7Rfk41CEkcCyvFQ==", - "dev": true, - "requires": {} + "dev": true }, "typescript": { - "version": "5.4.5", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz", - "integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==", + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", + "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", "dev": true }, "unbzip2-stream": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.3.3.tgz", - "integrity": "sha512-fUlAF7U9Ah1Q6EieQ4x4zLNejrRvDWUYmxXUpN3uziFYCHapjWFaCAnreY9bGgxzaMCFAPPpYNng57CypwJVhg==", + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz", + "integrity": "sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==", "dev": true, "requires": { "buffer": "^5.2.1", @@ -6059,9 +4568,9 @@ } }, "undici-types": { - "version": "5.26.5", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", - "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" + "version": "6.19.8", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", + "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==" }, "universalify": { "version": "2.0.1", @@ -6070,13 +4579,13 @@ "dev": true }, "update-browserslist-db": { - "version": "1.0.13", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", - "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz", + "integrity": "sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ==", "dev": true, "requires": { - "escalade": "^3.1.1", - "picocolors": "^1.0.0" + "escalade": "^3.1.2", + "picocolors": "^1.0.1" } }, "url": { @@ -6124,9 +4633,9 @@ "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" }, "uuid": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-10.0.0.tgz", - "integrity": "sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==", + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", "dev": true }, "v8-to-istanbul": { @@ -6322,16 +4831,16 @@ } }, "which-typed-array": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.14.tgz", - "integrity": "sha512-VnXFiIW8yNn9kIHN88xvZ4yOWchftKDsRJ8fEPacX/wl1lOvBrhsJ/OeJCXq7B0AaijRuqgzSKalJoPk+D8MPg==", + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.15.tgz", + "integrity": "sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==", "dev": true, "requires": { - "available-typed-arrays": "^1.0.6", - "call-bind": "^1.0.5", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", "for-each": "^0.3.3", "gopd": "^1.0.1", - "has-tostringtag": "^1.0.1" + "has-tostringtag": "^1.0.2" } }, "wide-align": { @@ -6354,17 +4863,6 @@ "strip-ansi": "^6.0.0" } }, - "wrap-ansi-cjs": { - "version": "npm:wrap-ansi@7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "requires": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - } - }, "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", @@ -6383,10 +4881,9 @@ } }, "ws": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", - "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", - "requires": {} + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", + "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==" }, "xml-name-validator": { "version": "3.0.0", @@ -6430,8 +4927,7 @@ "yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" }, "yargs": { "version": "17.7.2", diff --git a/package.json b/package.json index c80e6b957..a3753627f 100644 --- a/package.json +++ b/package.json @@ -27,31 +27,31 @@ }, "devDependencies": { "@types/crypto-js": "^3.1.43", - "@types/jest": "^29.5.12", - "@types/node": "^20.14.7", - "@types/prettier": "2.7.3", + "@types/jest": "^27.0.1", + "@types/node": "^10.17.54", + "@types/prettier": "2.6.0", "@types/puppeteer": "^5.4.7", - "@types/uuid": "^10.0.0", + "@types/uuid": "^3.4.13", "@types/ws": "^7.4.7", - "aws-sdk": "^2.1646.0", + "aws-sdk": "^2.1537.0", "cmake-js": "^7.3.0", - "https-proxy-agent": "^7.0.4", + "https-proxy-agent": "^5.0.1", "jest": "^27.2.1", "jest-puppeteer": "^5.0.4", - "jest-runtime": "^29.7.0", + "jest-runtime": "^27.2.1", "puppeteer": "^3.3.0", - "tar": "^7.4.0", + "tar": "^6.2.1", "ts-jest": "^27.0.5", - "typedoc": "^0.25.13", + "typedoc": "^0.24.8", "typedoc-plugin-merge-modules": "^5.1.0", - "typescript": "^5.4.5", - "uuid": "^10.0.0", - "yargs": "^17.7.2" + "typescript": "^4.9.5", + "uuid": "^8.3.2", + "yargs": "^17.2.1" }, "dependencies": { "@aws-sdk/util-utf8-browser": "^3.259.0", "@httptoolkit/websocket-stream": "^6.0.1", - "axios": "^1.7.2", + "axios": "^1.7.4", "buffer": "^6.0.3", "crypto-js": "^4.2.0", "mqtt": "^4.3.8",