From cf102b33ecf987749e692d1550448eab8efa7afd Mon Sep 17 00:00:00 2001 From: Sebastian Klose Date: Wed, 21 Oct 2020 11:53:03 -0400 Subject: [PATCH] Stabilize 1.3 (#202) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * parent 598250b089f6ad64cf3655c110b6756dc0ef3302 author sklose 1574703790 -0500 committer sklose 1579188453 -0500 parent 598250b089f6ad64cf3655c110b6756dc0ef3302 author sklose 1574703790 -0500 committer sklose 1579188394 -0500 initial commit develop * Bump up the versions for google cloud NPM packages (#11) * Integration command exits with jest exit code (#40) * Integration command exits with jest exit code [full ci] * revert version bumps [full ci] * Fix failing Kafka integration test (#43) * Remove Deprecated new Buffer usage (#46) * #12 remove deprecated new Buffer usage * Support Changes in Metrics Tags for Prometheus (#38) * Support Changes in Metrics Tags for Prometheus * add integration test to .travis.yml [full ci] * set jestTimeout to a larger value [full ci] * testing change to integrate always returning 0 * [full ci] * increasing time to wait for Prometheus to scrape * [full ci] * increase wait to 120 sec [full ci] * adding localhost so Docker/Prom works for linux * [full ci] * look for ports starting with 300 [full ci] * show all results from netstat [full ci] * File service discovery for Prometheus targets [full ci] * moving targets.json generation to integration file * [full ci] * [full ci] * slimming down docker-compose.yml file * [full ci] * addressing comments * [full ci] * Clean up for review * Fix IMetricsTags to ILabelValues conversion * Addressing comments * kubernetes: adjust logic for creating a watch (#48) kubernetes: adjust logic for creating a watch * update kubernetes-client to latest version on master that contains various internal fixes for creation and handling of a watch * adjust logic for startWatch to wrap watch function inside of a promise and handle timeouts differently * change callback for watch to not be async azure: fix build error to take in correct BufferEncoding and update kb calculations * Revert commit of incorrect yarn.lock from #48 (#50) yarn.lock was committed with private registry information. rebuild yarn.lock in order to fix deployment issues from #48. * kubernetes: fix kubernetes-client package build issue with Node 8 (#51) kubernetes-client package requires use of node version greater than 8 but we require 8 in the travis ci build pipeline. as a temporary solution till we deprecate Node 8 completely as part of #52 update the build pipeline to use a separate package.v8.json which doesn't build it. * build: fix grep check to only match if we're using node 8 (#53) * kubernetes: update @kubernetes/client-node package to 0.11.1 (#54) * kubernetes: add in additional logging details for watch errors (#56) * improve timeout of k8s watch (#59) * Allow opt-in to creating Azure queues dynamically on write (#55) * core: update ConsoleLogger to correctly log out nested objects (#60) core: update ConsoleLogger to correctly log out nested objects The console logger renders out `[object Object]` if a field is an object so destructure it into `.` delimited nested fields (e.g. foo.bar.baz) * Update ConsoleLogger to take in options letting users select a maxDepth for log outputs * kubernetes: create k8sPollSource that periodically polls for resources instead of using a watch (#61) * Create `KubernetesBase` class that both poll and watch sources extend from * Add in tests for `KubernetesPollSource` * Add preprocessor concept for Azure Queues to support messages not following the envelope format (#65) * fix missing bind when creating new azure queues (#63) * fix lint errors (#67) * refactor queue client to avoid exporting type from azure library as p… (#68) * refactor queue client to avoid exporting type from azure library as part of public api * kubernetes: add in timeout to poll request in case request to k8s hangs (#70) * Fix bug when options are ignored in QueueClient (#69) * Decorator returning class with empty string name (#73) * Decorator returning class with empty string name [full cli] * remove export, add link to TS issue [full cli] * bump version [full ci] * core: do not overwrite pending promises for the backlog of queued items (#76) It's possible to get into a state where we've hit our limit on items that we can add to the bounded priority queue and a large backlog of items are accumulated. Once we can begin to process that backlog after a `whenNotFull` promise resolves, the first item in the backlog will create a new `whenNotFull` and proceed to await it. Subsequent items in backlog queue will do the same but overwrite the promise of the first item leading to a chain of promises for backlogged items that are unresolvable. This PR ensures that we never overwrite the `whenNotFull` promise for backlogged queue items and we can resolve them all eventually. * core: version bump to 1.2.0-beta.11 (#77) * Update Cookie Cutter Dependencies (#75) * better throughput in RPC mode while guaranteeing correctness of state (#83) * Update dependencies for Node 8 (#86) * Update dependencies for Node 8 * add white space [full ci] * remove white space [full ci] * A few more deps updates [full ci] Co-authored-by: Plamen Ivanov * Reveal Azure Blob & Queue Service URL params, to allow for pointing at a local emulator. (#89) * Way to Inspect 'Invalid' Messages (#82) * Way to Inspect 'Invalid' Messages * unit test * remove annotator from unit test * allow publishing from inside the invalid handler * Updating docs * impoving clarity of doc entry * actual change of doc * add failSpan if input validation fails for Serial * Use custom error to signal no invalid msg handler * Missed files * Do not propagate NoInvalidHandlerError * Remove custom error and add hasInvalid function * add case in unit test * more tests for ConventionBasedMessageDispatcher * refactoring to simplify code * addressing comments Co-authored-by: Plamen Ivanov * Better Log Message when a Message Fails to Process and fix to upsertSproc SeqConErr details (#91) * Better Log Message when a Message Fails to Process * upsertSproc SeqConErr details fix * use context's logger Co-authored-by: Plamen Ivanov * Update CHANGELOG.md (#98) * bump develop to 1.3 (#106) * Add Dead Letter Queue to QueueInputSource (#93) * Add Dead Letter Queue to QueueInputSource * Addressing comments * pass in a modified config to dead letter queue * addressing comment * changing API to expect values in milliseconds * Updating docs * Docs update with example dead letter queue config * update package.jsoon * doc nit Co-authored-by: Plamen Ivanov * merge release/1.2 into develop (#112) * upgrade dependencies due to vulnerabilities (#111) * Remove support for node 8 (#113) * core: unable to close bounded priority queue (#116) core: fix issue with bounded priority queue not correctly supporting closing of queues immediately after it was drained leading to potential Cannot read property 'resolve' of undefined errors due to whenNotFull being undefined. * ConcurrentMessageProcessor suppresses error details (#124) * ConcurrentMessageProcessor suppresses error details When message handling fails outside of the message handler the ConcurrentMessageHandler currently throws a generic Error that hides the underlying root cause error. This PR changes it to re-throw the original error, similar to what the SerialMessageProcessor is doing. * Fix breaking API change in Azure Queues (#122) * Fix breaking API change in Azure Queues (#121) * Adding source unit to Config's timespanOf function * Adding Azure Queue change and other fixes Co-authored-by: Plamen Ivanov * DeadLetterQueue fixes * bump versions * rebase and bump version Co-authored-by: Plamen Ivanov * Add RedisStreamSink & RedisStreamSource (#126) * Add GCP PubSub Sink (#125) * Bump Redis version to publish new package (#127) do version bump missing in PR #126 * prometheus module should not throw an error when incrementing by 0 (#130) merge back from master * Prevent config.parse() output from being used as input (#134) * multi cosmos collections (#81) (#117) * fix MsSqlSink throws wrong error (#140) * fix MsSqlSink throws wrong error * Update package.json * Update MssqlSink.ts * Add AMQP Sink + Source (#136) * Add AMQP Sink + Source * add the actual Sink/Source files * properly close the sink's connection * Adding initialization and disposal to source * Basic producer and consumer scripts. * replace AsyncPipe with BoundedPriorityQueue * Refactor to get correct produce/consume behavior * improve connection call and add port as optional * fix yaml.lock file * Adding integration test * add new line at end of yml file * Add Copyright text and set "--passWithNoTest" * add msg release listener [full ci] * add AMQP integration to travis build * fix .travis.yml [full ci] * addressing comments * Fix integration test/setup [full ci] * Adding tracing [full ci] * minor corrections Co-authored-by: Plamen Ivanov * Add metrics to AMQP (#144) * Add metrics to AMQP * bump version * switch to this.channel * trigger [full ci] * Adding periodic metrics * Add metadata [full ci] * Lint and style fix [full ci] * Addressing comments Co-authored-by: Plamen Ivanov * Add docs to AMQP package (#147) * Add docs to AMQP package * correcting module name * Addressing comments * Adding example files * minor nits * rename * Simplify config Co-authored-by: Plamen Ivanov * Add cookie-cutter-jaeger (#151) * Add cookie-cutter-jaeger * remove interface * add lock * update per comments Co-authored-by: Marco Garcia * cookie-cutter-redis: add support for multiple streams (#155) * cc-redis: add support for multiple streams * fix test * update spanLogAndSetTags * update getPendingMessagesForConsumerGroup * update RedisStreamSink * rename test * add tests * add more tests * update per feedback * update xReadGroup * full ci Co-authored-by: Marco Garcia * cookie-cutter-redis: add metrics (#156) * cookie-cutter-redis: add metrics * full ci * update docs * update docs * full ci * remove array tag Co-authored-by: Marco Garcia * Have separate queue capacity per priority level (#160) * Have separate queue capacity per priority level * Fix memory leak likely caused by promise chaining * fixing floating promises * white space change [full ci] Co-authored-by: Plamen Ivanov Co-authored-by: Sebastian Klose * Fix lz4 error by adding resolution (#161) * Fix lz4 error by adding resolution * yarn.lock file change Co-authored-by: Plamen Ivanov * Add new Jaeger package to README (#158) * fix broken metrics, reclaim PEL messages less often (#163) * fix pending list not fully drained on startup, added password config (#164) * fix messages are acked on error (#168) * check for failed acks to redis (#169) * fix xReadGroup ignores all but first message from batch (#170) * Implement IEncodedMessageEmbedder for ProtoMessageEncoder (#174) * Implement IEncodedMessageEmbedder for ProtoMessageEncoder * version change * unit tests Co-authored-by: Plamen Ivanov * cleanup redis stream implementation (#171) * make some redis options nullable so the default value can be overwrit… (#177) * troubleshoot redis stream issue (#179) * Allow negative values in Prometheus histogram (#181) Co-authored-by: Plamen Ivanov * Prevent BoundedPriorityQueue from deprioritizing waiting enqueue calls (#180) * Prevent BoundedPriorityQueue from deprioritizing waiting enqueue calls * versioon bump * handle floating promises Co-authored-by: Plamen Ivanov * Fix backwards compatibility for ProtoMessageEncoder (#182) * Version bump for Proto change (#183) Co-authored-by: Plamen Ivanov * Change LogLevel from Error -> Warn when retrieving Kafka watermarks (#184) * fix 'yarn audit' issues [full ci] (#187) * fix sec vuln in node-fetch (#189) * Add auth for amqp source and sink (#192) * Add auth for amqp source and sink * trigger [full ci] * do not overwrite default creds [full ci] * do not overwrite default creds [full ci] * do not overwrite default creds [full ci] * do not overwrite default creds [full ci] * add missing new line [full ci] * lint fix * trigger ci [full ci] * trigger ci Co-authored-by: prachi.tandon@jet.computer * Add AMQP package to README (#193) Co-authored-by: Plamen Ivanov * Add vhost support for amqp (#194) * Add vhost support for amqp * Add vhost support for amqp * Add vhost support for amqp [full ci] * Add vhost support for amqp * Add vhost support for amqp * Add vhost support for amqp * version bump Co-authored-by: prachi.tandon@jet.computer * kubernetes: adjust logging to be less verbose (#195) * detect when kafkajs is stuck with stale broker metadata (#186) * detect when kafkajs is stuck with stale broker metadata and terminate application * lint * Ensure RedisClient's "type" metric label is always a string (#196) * Ensure metrics type label is always a string * Bump cookie-cutter-redis version to 1.3.0-beta.13 * Fix wrong string function in Kafka (#197) * Fix wrong string function in Kafka * proper conversion of object to string Co-authored-by: Plamen Ivanov * address vulnerability in node-forge package [full ci] (#200) * create 1.3-rc [full ci] * bump version, add missing license headers * fix code dupe * update changelog Co-authored-by: Kshitiz Gupta Co-authored-by: plameniv <47831130+plameniv@users.noreply.github.com> Co-authored-by: Connor Ross Co-authored-by: Tanvir Alam Co-authored-by: Chris Pinola Co-authored-by: Ilya Butorine Co-authored-by: Plamen Ivanov Co-authored-by: Sean Halpin Co-authored-by: Emma Lynch Co-authored-by: Dillon Mulroy Co-authored-by: Kshitiz Gupta Co-authored-by: Chris Pinola Co-authored-by: Marco Garcia Co-authored-by: Marco Garcia Co-authored-by: prachi30 <51481988+prachi30@users.noreply.github.com> Co-authored-by: prachi.tandon@jet.computer --- .travis.yml | 38 +- CHANGELOG.md | 43 + README.md | 4 +- docs/docs/Module_Amqp.md | 141 + docs/docs/Module_Azure.md | 51 +- docs/docs/Module_Redis.md | 113 +- docs/website/i18n/en.json | 3 + docs/website/package.json | 2 +- docs/website/sidebars.json | 1 + examples/amqp-messages/README.md | 25 + examples/amqp-messages/package.json | 18 + examples/amqp-messages/src/consumer.ts | 38 + examples/amqp-messages/src/model.ts | 10 + examples/amqp-messages/src/producer.ts | 53 + examples/amqp-messages/tsconfig.json | 9 + examples/azure-queue/package.json | 6 +- examples/custom-sink/package.json | 2 +- examples/custom-source/package.json | 2 +- examples/grpc-chat/package.json | 4 +- examples/grpc-echo-service/package.json | 4 +- examples/hello-world/package.json | 2 +- examples/integration-tests/package.json | 4 +- examples/kafka-events/package.json | 4 +- examples/kafka-projector/package.json | 4 +- examples/metrics/package.json | 2 +- examples/redis-service/package.json | 4 +- examples/state-event-sourced/package.json | 2 +- package.json | 15 +- packages/amqp/docker-compose.yml | 10 + packages/amqp/package.json | 29 + packages/amqp/src/AmqpSink.ts | 96 + packages/amqp/src/AmqpSource.ts | 175 ++ .../src/__test__/amqp.integration.test.ts | 120 + packages/amqp/src/config.ts | 117 + packages/amqp/src/index.ts | 70 + packages/amqp/tsconfig.json | 9 + packages/azure/package.json | 12 +- .../CosmosStateAggregationSource.test.ts | 2 +- .../MaterializedView.integration.test.ts | 95 + .../azure/src/__test__/utils/helpers.test.ts | 42 + packages/azure/src/index.ts | 2 +- .../internal/CosmosStateProvider.ts | 17 +- packages/azure/src/streaming/index.ts | 21 + .../streaming/internal/QueueInputSource.ts | 49 + .../src/streaming/internal/QueueOutputSink.ts | 12 +- .../azure/src/streaming/internal/config.ts | 76 +- packages/azure/src/utils/CosmosClient.ts | 67 +- packages/azure/src/utils/QueueClient.ts | 33 +- packages/azure/src/utils/helpers.ts | 36 + packages/core/package.json | 6 +- packages/core/src/__test__/config.test.ts | 5 + .../utils/BoundedPriorityQueue.test.ts | 20 + packages/core/src/config.ts | 13 +- .../processor/ConcurrentMessageProcessor.ts | 7 +- .../internal/processor/RpcMessageProcessor.ts | 9 - .../core/src/utils/BoundedPriorityQueue.ts | 2 +- packages/gcp/package.json | 11 +- packages/gcp/src/PubSubSink.ts | 183 ++ packages/gcp/src/__test__/PubSubSink.test.ts | 163 + packages/gcp/src/config.ts | 80 +- packages/gcp/src/index.ts | 29 +- packages/grpc/package.json | 8 +- packages/instana/package.json | 8 +- packages/jaeger/package.json | 33 + packages/jaeger/src/__test__/jaeger.test.ts | 13 + packages/jaeger/src/index.ts | 114 + packages/jaeger/tsconfig.json | 9 + packages/kafka/package.json | 6 +- packages/kafka/src/KafkaConsumer.ts | 27 +- packages/kubernetes/package.json | 10 +- .../kubernetes/src/KubernetesPollSource.ts | 4 +- .../kubernetes/src/KubernetesWatchSource.ts | 4 +- packages/lightstep/package.json | 6 +- packages/mssql/package.json | 8 +- packages/mssql/src/MssqlSink.ts | 9 +- packages/prometheus/package.json | 10 +- .../src/__test__/prometheus.test.ts | 32 +- packages/prometheus/src/index.ts | 7 +- packages/proto/package.json | 6 +- packages/proto/src/ProtoMessageEncoder.ts | 22 +- .../src/__test__/ProtoMessageEncoder.test.ts | 79 +- packages/redis/package.json | 11 +- packages/redis/src/RedisClient.ts | 460 ++- packages/redis/src/RedisProxy.ts | 130 +- packages/redis/src/RedisStreamSink.ts | 97 + packages/redis/src/RedisStreamSource.ts | 312 ++ .../src/__test__/client.integration.test.ts | 37 + packages/redis/src/__test__/protocol.test.ts | 35 + .../redis/src/__test__/redisClient.test.ts | 171 - .../redis/src/__test__/redisProxy.test.ts | 123 - .../src/__test__/stream.integration.test.ts | 331 ++ packages/redis/src/__test__/utils.ts | 40 + packages/redis/src/config.ts | 117 + packages/redis/src/index.ts | 134 +- packages/s3/package.json | 10 +- packages/statsd/package.json | 8 +- packages/timer/package.json | 6 +- packages/validatejs/package.json | 6 +- yarn.lock | 2796 ++++++++++------- 99 files changed, 5696 insertions(+), 1765 deletions(-) create mode 100644 docs/docs/Module_Amqp.md create mode 100644 examples/amqp-messages/README.md create mode 100644 examples/amqp-messages/package.json create mode 100644 examples/amqp-messages/src/consumer.ts create mode 100644 examples/amqp-messages/src/model.ts create mode 100644 examples/amqp-messages/src/producer.ts create mode 100644 examples/amqp-messages/tsconfig.json create mode 100644 packages/amqp/docker-compose.yml create mode 100644 packages/amqp/package.json create mode 100644 packages/amqp/src/AmqpSink.ts create mode 100644 packages/amqp/src/AmqpSource.ts create mode 100644 packages/amqp/src/__test__/amqp.integration.test.ts create mode 100644 packages/amqp/src/config.ts create mode 100644 packages/amqp/src/index.ts create mode 100644 packages/amqp/tsconfig.json create mode 100644 packages/azure/src/__test__/utils/helpers.test.ts create mode 100644 packages/azure/src/utils/helpers.ts create mode 100644 packages/gcp/src/PubSubSink.ts create mode 100644 packages/gcp/src/__test__/PubSubSink.test.ts create mode 100644 packages/jaeger/package.json create mode 100644 packages/jaeger/src/__test__/jaeger.test.ts create mode 100644 packages/jaeger/src/index.ts create mode 100644 packages/jaeger/tsconfig.json create mode 100644 packages/redis/src/RedisStreamSink.ts create mode 100644 packages/redis/src/RedisStreamSource.ts create mode 100644 packages/redis/src/__test__/client.integration.test.ts create mode 100644 packages/redis/src/__test__/protocol.test.ts delete mode 100644 packages/redis/src/__test__/redisClient.test.ts delete mode 100644 packages/redis/src/__test__/redisProxy.test.ts create mode 100644 packages/redis/src/__test__/stream.integration.test.ts create mode 100644 packages/redis/src/__test__/utils.ts diff --git a/.travis.yml b/.travis.yml index 8be4213a..71fa72e5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -21,10 +21,13 @@ matrix: stage: smoke script: yarn build && yarn lint && yarn test - - name: "Linux Node 8" + - name: "Audit Dependencies" os: linux - node_js: 8 - stage: test + node_js: 10 + stage: smoke + if: type = cron + script: yarn audit + - name: "Linux Node 12" os: linux node_js: 12 @@ -39,18 +42,26 @@ matrix: stage: test env: - YARN_GPG=no # Windows build agent will hang without this - + - name: "MSSQL" os: linux - node_js: 8 + node_js: 10 stage: integrate services: - docker script: yarn build && cd packages/mssql && yarn integrate + - name: "AMQP" + os: linux + node_js: 10 + stage: integrate + services: + - docker + script: yarn build && cd packages/amqp && yarn integrate + - name: "Kafka" os: linux - node_js: 8 + node_js: 10 stage: integrate services: - docker @@ -58,7 +69,7 @@ matrix: - name: "Prometheus" os: linux - node_js: 8 + node_js: 10 stage: integrate services: - docker @@ -66,7 +77,7 @@ matrix: - name: "S3" os: linux - node_js: 8 + node_js: 10 stage: integrate services: - docker @@ -74,7 +85,7 @@ matrix: - name: "Redis" os: linux - node_js: 8 + node_js: 10 stage: integrate services: - docker @@ -93,7 +104,7 @@ matrix: - name: "Publish to GitHub Pages" if: branch = master os: linux - node_js: 8 + node_js: 10 stage: deploy env: - GH_NAME=sklose @@ -110,11 +121,6 @@ before_install: - export PATH="$HOME/.yarn/bin:$PATH" install: - # https://github.com/walmartlabs/cookie-cutter/pull/51 - # the kubernetes-client package currently doesn't support node 8 so as a workaround - # create a special package.json that doesn't try to yarn install it. Rely on other stages - # to build and test it. - - if node --version | grep -q v8\.* ; then cp package.v8.json package.json && echo copied package.v8.json into package.json ; fi - - yarn install + - yarn install --frozen-lockfile script: yarn build && yarn test diff --git a/CHANGELOG.md b/CHANGELOG.md index 3ecf3a07..9f884d03 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,46 @@ +# 1.3 + +## core + +- fixed bug where BoundedPriorityQueue could de-prioritize elements under certain circumstances which could lead to out-of-order processing +- deprecated support for Node v8 + +## kafka + +- detect stale broker metadata and crash kafkajs client; this seems to be a bug in kafkajs where the metadata can get stale and all reconnect attempts of kafkajs will fail. + +## prometheus + +- allow negative values for histograms + +## kubernetes + +- less verbose logging + +## amqp + +- new module with sink and source for AMQP compatible message buses + +## protobuf + +- support embedding encoded protobuf data as base64 in JSON documents + +## redis + +- support multiple streams for source and sink +- added missing metrics +- fix messages getting lost when receiving in batches + +## azure + +- support accessing multiple cosmos collection from within the same service +- added support for dead letter queues for Azure Queues + +## mssql + +- fixed sink swallows actual error message when a transaction fails to commit + + # 1.2 ## core diff --git a/README.md b/README.md index 95de75e5..a9994b16 100644 --- a/README.md +++ b/README.md @@ -24,10 +24,12 @@ The documentation is available [here](https://walmartlabs.github.io/cookie-cutte | Package | Stable | Beta | |---------|--------|------| | core | [![npm version](https://badgen.net/npm/v/@walmartlabs/cookie-cutter-core)](https://www.npmjs.com/package/@walmartlabs/cookie-cutter-core) | [![npm version](https://badgen.net/npm/v/@walmartlabs/cookie-cutter-core/next)](https://www.npmjs.com/package/@walmartlabs/cookie-cutter-core/v/next) | +| amqp | [![npm version](https://badgen.net/npm/v/@walmartlabs/cookie-cutter-amqp)](https://www.npmjs.com/package/@walmartlabs/cookie-cutter-amqp) | [![npm version](https://badgen.net/npm/v/@walmartlabs/cookie-cutter-amqp/next)](https://www.npmjs.com/package/@walmartlabs/cookie-cutter-amqp/v/next) | | azure | [![npm version](https://badgen.net/npm/v/@walmartlabs/cookie-cutter-azure)](https://www.npmjs.com/package/@walmartlabs/cookie-cutter-azure) | [![npm version](https://badgen.net/npm/v/@walmartlabs/cookie-cutter-azure/next)](https://www.npmjs.com/package/@walmartlabs/cookie-cutter-azure/v/next) | | gcp | [![npm version](https://badgen.net/npm/v/@walmartlabs/cookie-cutter-gcp)](https://www.npmjs.com/package/@walmartlabs/cookie-cutter-gcp) | [![npm version](https://badgen.net/npm/v/@walmartlabs/cookie-cutter-gcp/next)](https://www.npmjs.com/package/@walmartlabs/cookie-cutter-gcp/v/next) | | grpc | [![npm version](https://badgen.net/npm/v/@walmartlabs/cookie-cutter-grpc)](https://www.npmjs.com/package/@walmartlabs/cookie-cutter-grpc) | [![npm version](https://badgen.net/npm/v/@walmartlabs/cookie-cutter-grpc/next)](https://www.npmjs.com/package/@walmartlabs/cookie-cutter-grpc/v/next) | | instana | [![npm version](https://badgen.net/npm/v/@walmartlabs/cookie-cutter-instana)](https://www.npmjs.com/package/@walmartlabs/cookie-cutter-instana) | [![npm version](https://badgen.net/npm/v/@walmartlabs/cookie-cutter-instana/next)](https://www.npmjs.com/package/@walmartlabs/cookie-cutter-instana/v/next) | +| jaeger | [![npm version](https://badgen.net/npm/v/@walmartlabs/cookie-cutter-jaeger)](https://www.npmjs.com/package/@walmartlabs/cookie-cutter-jaeger) | [![npm version](https://badgen.net/npm/v/@walmartlabs/cookie-cutter-jaeger/next)](https://www.npmjs.com/package/@walmartlabs/cookie-cutter-jaeger/v/next) | | kafka | [![npm version](https://badgen.net/npm/v/@walmartlabs/cookie-cutter-kafka)](https://www.npmjs.com/package/@walmartlabs/cookie-cutter-kafka) | [![npm version](https://badgen.net/npm/v/@walmartlabs/cookie-cutter-kafka/next)](https://www.npmjs.com/package/@walmartlabs/cookie-cutter-kafka/v/next) | | kubernetes | [![npm version](https://badgen.net/npm/v/@walmartlabs/cookie-cutter-kubernetes)](https://www.npmjs.com/package/@walmartlabs/cookie-cutter-kubernetes) | [![npm version](https://badgen.net/npm/v/@walmartlabs/cookie-cutter-kubernetes/next)](https://www.npmjs.com/package/@walmartlabs/cookie-cutter-kubernetes/v/next) | | lightstep | [![npm version](https://badgen.net/npm/v/@walmartlabs/cookie-cutter-lightstep)](https://www.npmjs.com/package/@walmartlabs/cookie-cutter-lightstep) | [![npm version](https://badgen.net/npm/v/@walmartlabs/cookie-cutter-lightstep/next)](https://www.npmjs.com/package/@walmartlabs/cookie-cutter-lightstep/v/next) | @@ -42,4 +44,4 @@ The documentation is available [here](https://walmartlabs.github.io/cookie-cutte # License -See [LICENSE](LICENSE) and [LICENSE-DOCS](LICENSE-DOCS) for more details. +See [LICENSE](LICENSE.md) and [LICENSE-DOCS](LICENSE-DOCS) for more details. diff --git a/docs/docs/Module_Amqp.md b/docs/docs/Module_Amqp.md new file mode 100644 index 00000000..24e656b5 --- /dev/null +++ b/docs/docs/Module_Amqp.md @@ -0,0 +1,141 @@ +--- +id: module-amqp +title: AMQP +--- + +## amqpSource + +The `amqpSource` function creates a new input source that receives messages from `RabbitMQ` or another message broker following the `AMQP 0-9-1` protocol. +The example below starts consuming JSON encoded messages from queue `defaultQueueName`. + +```typescript +Application.create() + .input() + .add(amqpSource({ + server: { + host: "localhost", + }, + queue: { + name: "defaultQueueName", + }, + encoder: new JsonMessageEncoder(), + })) + .done() + // ... + .run(); +``` + +### Configuration + +The available configuration options are + +| name | description | +| ---- | ----------- | +| server.host | host name to connect to | +| _server.port_ | port to connect to (default `5672`) | +| queue.name | name of queue to connect to | +| _queque.durable_ | if `true` (default), queue survives restarts of broker, messages are as persistent as their queue | +| _message.expiration_ | time to live per message in milliseconds (default is no expiration) | +| encoder | defines how the raw data received from AMQP Broker should be converted into message objects | + +### Consuming from AMQP Broker + +```typescript +Application.create() + .input() + .add(amqpSource({ + server: { + host: "localhost", + }, + queue: { + name: "defaultQueueName", + }, + encoder: new JsonMessageEncoder(), + })) + .done() + .dispatch({ + onSomeInputMessage(msg: ISomeInputMessage, ctx: IDispatchContext) { + ctx.publish(SomeInputMessage, msg); + }, + }) + // ... + .run(); +``` + +### Metadata + +The following metadata is available in the message handler via `ctx.metadata(key)` + +| name | description | +| ---- | ----------- | +| AmqpMetadata.name | name of queue this message came from | +| AmqpMetadata.Redelivered | indicates that the message has been previously delivered to this or another client. | +| AmqpMetadata.Expiration | message expiration in milliseconds as specified when publishing the message | + +### Metrics + +| name | description | Type | Tags | +| ---- | ----------- | ---- | ---- | +| cookie_cutter.amqp_consumer.input_msg_received | number of messages received from the broker | `increment` | `host`, `queueName`, `event_type`, `result` | +| cookie_cutter.amqp_consumer.input_msg_processed | number of messages consumed successfully/unsuccessfully | `increment` | `host`, `queueName`, `event_type`, `result` | +| cookie_cutter.amqp_consumer.unassigned_message_count | number of messages in the queue still not assigned to a consumer | `gauge` | `host`, `queueName` | +| cookie_cutter.amqp_consumer.consumer_count | number of consumers for this queue | `gauge` | `host`, `queueName` | + +## amqpSink + +The `amqpSink` function creates an output sink that handles published messages. The example below starts publishing JSON encoded messages to queue `defaultQueueName`. + +```typescript +Application.create() + // ... + .output() + .published(amqpSink({ + server: { + host: "localhost", + }, + queue: { + name: "defaultQueueName", + }, + encoder: new JsonMessageEncoder(), + })) + .done() + // ... + .run(); +``` + +### Configuration + +The available configuration options are + +| name | description | +| ---- | ----------- | +| server.host | host name to connect to | +| _server.port_ | port to connect to (default `5672`) | +| queue.name | name of queue to connect to | +| _queque.durable_ | if `true` (default), queue survives restarts of broker, messages are as persistent as their queue | +| _message.expiration_ | time to live per message in milliseconds (default is no expiration) | +| encoder | defines how the raw data received from AMQP Broker should be converted into message objects | + +### Publishing to AMQP Broker + +```typescript +Application.create() + .dispatch({ + onSomeInputMessage(msg: ISomeInputMessage, ctx: IDispatchContext) { + ctx.publish(SomeInputMessage, msg); + } + }) + .output() + .published(amqpSink({ + server: { + host: "localhost", + }, + queue: { + name: "defaultQueueName", + }, + encoder: new JsonMessageEncoder(), + })) + .done() + // ... + .run(); +``` diff --git a/docs/docs/Module_Azure.md b/docs/docs/Module_Azure.md index 1192ee85..e90c02bf 100644 --- a/docs/docs/Module_Azure.md +++ b/docs/docs/Module_Azure.md @@ -287,8 +287,8 @@ Application.create() storageAccessKey: "[SOME_KEY]", queueName: "[QUEUE_NAME]", encoder: new JsonMessageEncoder(), - visibilityTimeout: 30, // default 30 seconds - numOfMessages: 32, // default 32 + visibilityTimeout: 30, // seconds, Azure default: 30 seconds + numOfMessages: 32, // Azure default: 1 })) .done() .dispatch({ @@ -305,3 +305,50 @@ Application.create() It is recommended to run the service in Serial mode with `queueSource` because once the message is received from Azure Queues its visibility timeout window starts and running the service in serial mode will decrease the chance of hitting the window timeout as messages are queued up internally in Cookie Cutter in Concurrent mode. Queues items will be reprocessed if you throw an error in the message handler function. The `DequeueCount` metadata can be used to detect reprocessed messages and skip over those if appropriate. + +### Dead Letter Queue + +It is possible to designate a queue to serve as a dead letter queue. `maxDequeueCount` specifies how many times a message can be dequeued before it is sent to the dead letter queue. The visibility timeout and message time to live will default to the values of the main queue unless the values are explicitly overwritten. + +```typescript +Application.create() + .input() + .add(Streaming.queueSource({ + storageAccount: "[SOME_ACCOUNT]", + storageAccessKey: "[SOME_KEY]", + queueName: "[QUEUE_NAME]", + encoder: new JsonMessageEncoder(), + deadLetterQueue: { + queueName: "[OTHER_QUEUE_NAME]", + maxDequeueCount: 10, + visibilityTimeout: 30, // seconds, Azure default: 30 seconds + messageTimeToLive: 120, // seconds, Azure default: 7 days + } + })) + .done() + .dispatch({ + onSomeTask: (_msg: ISomeTask, _ctx: IDispatchContext) => { + // ... + }, + }) + .run(ErrorHandlingMode.LogAndContinue, ParallelismMode.Serial); +``` + +### Metadata + +The following metadata is available + +| Name | Description | +|------|-------------| +| GrpcMetadata.Peer | the host and port of the client sending the request | +| QueueMetadata.QueueName | Queue name | +| QueueMetadata.VisibilityTimeout | When passed into msg metadata via `publish`/`store`: Specifies the new visibility timeout value, in seconds, relative to server time | +| QueueMetadata.VisibilityTimeoutMs | When passed into msg metadata via `publish`/`store`: Specifies the new visibility timeout value, in milliseconds, relative to server time | +| QueueMetadata.VisibilityTimeout | When read from the MessageRef metadata: Returns the date when the message will next be visible in string format: "Tue, 21 Apr 2020 16:33:23 GMT" | +| QueueMetadata.TimeToLive | When passed into msg metadata via `publish`/`store`: The time-to-live interval for the message, in seconds. | +| QueueMetadata.TimeToLiveMs | When passed into msg metadata via `publish`/`store`: The time-to-live interval for the message, in milliseconds. | +| QueueMetadata.TimeToLive | When read from the MessageRef metadata: Returns the date when the message will expire in string format: "Tue, 21 Apr 2020 16:33:23 GMT" | +| QueueMetadata.DequeueCount | Number of times a message has been dequeued | +| QueueMetadata.TimeToNextVisible | not used | +| QueueMetadata.MessageId | The message identifier of the message | +| QueueMetadata.PopReceipt | A valid pop receipt value returned from an earlier call to the Get Messages or Update Message operation | diff --git a/docs/docs/Module_Redis.md b/docs/docs/Module_Redis.md index f32ace8f..c64d8344 100644 --- a/docs/docs/Module_Redis.md +++ b/docs/docs/Module_Redis.md @@ -34,14 +34,121 @@ Application.create() | Name | Description | |------|-------------| | host | the HTTP endpoint to connect to | -| port | the port to connect to. Default is 6379 | -| db | index of the database to connect to | +| _port_ | the port to connect to. Default is 6379 | +| _db_ | index of the database to connect to. Default is 0 | +| _password_ | the password to use to connect to Redis. Default is no password | | _encoder_ | the encoder to use when converting the payload to a byte array. This defaults to the `NullMessageEncoder` which only supports Buffers (=byte arrays) being published | | _typeMapper_ | only required if correct type information needs to be emitted | +| _base64Encode_ | determines if buffers should be stored in base64 encoding. Default is true | ### Metrics | Name | Description | Type | Tags | | ------------------------------------------- | ----------- | ---- | ---- | | cookie_cutter.redis_client.get | A call to get a value | `increment` | `type`, `db`, `result` -| cookie_cutter.redis_client.set | A call to set a value | `increment` | `type`, `db`, `result` \ No newline at end of file +| cookie_cutter.redis_client.set | A call to set a value | `increment` | `type`, `db`, `result` +| cookie_cutter.redis_client.xadd | A call to add a value to a stream | `increment` | `type`, `db`, `result` +| cookie_cutter.redis_client.xread | A call to read from a stream | `increment` | `type`, `db`, `result` +| cookie_cutter.redis_client.xreadgroup | A call to read from a a stream as part of a consumer group | `increment` | `type`, `db`, `result` +| cookie_cutter.redis_client.xgroup | A call to create a consumer group | `increment` | `type`, `db`, `result` +| cookie_cutter.redis_client.xack | A call to acknowledge a message in a stream | `increment` | `type`, `db`, `result` +| cookie_cutter.redis_client.xpending | A call to query pending messages list of a stream | `increment` | `type`, `db`, `result` +| cookie_cutter.redis_client.xclaim | A call to claim a pending message of a stream | `increment` | `type`, `db`, `result` + +## redisStreamSource + +The `redisStreamSource` function creates a new input source that receives messages from Redis. The example below joins the consumer group `consumer-group-1` and receives JSON encoded messages from streams `stream1`, `stream2` and `stream3`. + +```typescript + Application.create() + .input() + .add(redisStreamSource({ + host: "localhost", + streams: ["stream1", "stream2", "stream3"], + consumerGroup: "consumer-group-1", + })) + .done() + // ... + .run(); +``` + +### Configuration + +| Name | Description | +|------|-------------| +| host | the HTTP endpoint to connect to | +| _port_ | the port to connect to. Default is 6379 | +| _db_ | index of the database to connect to | +| _password_ | the password to use to connect to Redis. Default is no password | +| _typeMapper_ | only required if correct type information needs to be emitted | +| encoder | the encoder to use when converting the payload to a byte array. | +| streams | a list of stream names to consume from | +| consumerGroup | the name of the consumer group to join | +| _consumerId_ | the id of consumer to use, the default value is a generated guid | +| _consumerGroupStartId_ | the ID of the last item in the stream to consider already delivered, the default value is `$` (the ID of the last item in the stream) | +| _blockTimeout_ | the number of milliseconds we want to block before timing out, the default values is 100 ms | +| _idleTimeout_ | the minimum number of milliseconds of idle time a pending message should have before we try to claim it, the default value is 30000 ms (30s) | +| _batchSize_ | the number of messages receive at a time when consuming streams, the default values is 10 | +| _reclaimMessageInterval_ | defines how often a client is checking for pending messages from dead consumers and tries to reclaim then | +| _base64Encode_ | determines if buffers should be stored in base64 encoding. Default is true | + +### Metadata + +The following metadata is available in the message handler via `ctx.metadata(key)` + +| name | description | +|--------------------------|-------------| +| RedisMetadata.Stream | the name of the stream the messages was received from | +| RedisMetadata.MessageId | the id of the message that was received | +| RedisMetadata.ConsumerId | the id of the consumer group | + +### Metrics + +| Name | Description | Type | Tags | +| ------------------------------------------- | ----------- | ---- | ---- | +| cookie_cutter.redis_consumer.input_msg_received | number of messages received from redis server | `increment` | `stream_name`, `consumer_group` +| cookie_cutter.redis_consumer.input_msg_processed | number of messages processed | `increment` | `stream_name`, `consumer_group`, `result` +| cookie_cutter.redis_consumer.input_msgs_claimed | number of pending messages claimed | `increment` | `stream_name`, `consumer_group` +| cookie_cutter.redis_consumer.pending_msg_size | number of pending messages found | `gauge` | `stream_name`, `consumer_group` +| cookie_cutter.redis_consumer.incoming_batch_size | number of messages received from redis server in a single fetch request | `gauge` + +## redisStreamSink + +The 'redisStreamSink' function creates an output sink that handles published messages. + +```typescript +Application.create() + .output() + .published(redisStreamSink({ + host: "localhost", + stream: "streamName", + })) + .done() + // ... + .run(); +``` +### Configuration + +| Name | Description | +|------|-------------| +| host | the HTTP endpoint to connect to | +| _port_ | the port to connect to. Default is 6379 | +| _db_ | index of the database to connect to | +| encoder | the encoder to use when converting the payload to a byte array. | +| _typeMapper_ | only required if correct type information needs to be emitted | +| stream | the name of the stream to publish to if no other stream name was specified in the message handler | +| maxStreamLength | if defined will limit the length of a stream by truncating it when new messages are published. Default is off | + +### Metadata + +The following metadata is available in the message handler via `ctx.publish` + +| name | description | +|--------------------------|-------------| +| RedisStreamMetadata.Stream | the name of the stream to publish to | + +### Metrics + +| Name | Description | Type | Tags | +| ------------------------------------------- | ----------- | ---- | ---- | +| cookie_cutter.redis_producer.msg_published | the number of messages sent to redis server | `increment` | `stream_name`, `result` | diff --git a/docs/website/i18n/en.json b/docs/website/i18n/en.json index a23761fd..9927c8fe 100644 --- a/docs/website/i18n/en.json +++ b/docs/website/i18n/en.json @@ -44,6 +44,9 @@ "intro-outputs": { "title": "Outputs" }, + "module-amqp": { + "title": "AMQP" + }, "module-azure": { "title": "Azure" }, diff --git a/docs/website/package.json b/docs/website/package.json index 2ff14873..6b599ed7 100644 --- a/docs/website/package.json +++ b/docs/website/package.json @@ -1,6 +1,6 @@ { "name": "@walmartlabs/cookie-cutter-docs", - "version": "1.2.0", + "version": "1.3.0", "private": true, "scripts": { "start": "docusaurus-start", diff --git a/docs/website/sidebars.json b/docs/website/sidebars.json index 782c1a33..85c21716 100644 --- a/docs/website/sidebars.json +++ b/docs/website/sidebars.json @@ -21,6 +21,7 @@ "Modules": [ "module-kafka", "module-azure", + "module-amqp", "module-grpc", "module-validatejs", "module-mssql", diff --git a/examples/amqp-messages/README.md b/examples/amqp-messages/README.md new file mode 100644 index 00000000..deaad7b2 --- /dev/null +++ b/examples/amqp-messages/README.md @@ -0,0 +1,25 @@ +# AMQP Messages + +This example demonstrates how to produce and consume messages from a specified queue in an AMQP Broker (RabbitMQ). + +## How to Run + +Before running this example, please adjust the code to include your AMQP Broker (RabbitMQ) connection details. + +```bash +yarn start:producer +``` + +then + +```bash +yarn start:consumer +``` + +## Output (consumer) + +``` +2020-06-30T21:40:09.956Z | INFO | starting Cookie Cutter service | version=1.3.0-beta.5 | serviceName=@examples/amqp-messages | serviceVersion=0.0.0 +2020-06-30T21:40:10.002Z | INFO | Source | amqp.queue_name=defaultQueueName | payload=Message #1 +2020-06-30T21:40:10.004Z | INFO | Source | amqp.queue_name=defaultQueueName | payload=Message #2 +``` \ No newline at end of file diff --git a/examples/amqp-messages/package.json b/examples/amqp-messages/package.json new file mode 100644 index 00000000..eadacc24 --- /dev/null +++ b/examples/amqp-messages/package.json @@ -0,0 +1,18 @@ +{ + "name": "@examples/amqp-messages", + "private": true, + "version": "0.0.0", + "license": "Apache-2.0", + "dependencies": { + "@walmartlabs/cookie-cutter-core": "^1.3.0", + "@walmartlabs/cookie-cutter-amqp": "^1.3.0" + }, + "scripts": { + "build": "tsc", + "start:producer": "node dist/producer", + "start:consumer": "node dist/consumer", + "test": "echo '- no tests -'", + "lint": "tslint --project tsconfig.json", + "lint:fix": "yarn run lint --fix" + } +} diff --git a/examples/amqp-messages/src/consumer.ts b/examples/amqp-messages/src/consumer.ts new file mode 100644 index 00000000..f6dc292b --- /dev/null +++ b/examples/amqp-messages/src/consumer.ts @@ -0,0 +1,38 @@ +/* +Copyright (c) Walmart Inc. + +This source code is licensed under the Apache 2.0 license found in the +LICENSE file in the root directory of this source tree. +*/ + +import { + Application, + ConsoleLogger, + IDispatchContext, + JsonMessageEncoder, +} from "@walmartlabs/cookie-cutter-core"; +import { amqpSource } from "@walmartlabs/cookie-cutter-amqp"; +import { MessageClass } from "./model"; + +// Before running this example, please adjust the code to include your AMQP Broker (RabbitMQ) connection details. +const AMQP_CONFIG = { + server: { + host: "localhost", + }, + queue: { + name: "defaultQueueName", + }, + encoder: new JsonMessageEncoder(), +}; + +Application.create() + .input() + .add(amqpSource(AMQP_CONFIG)) + .done() + .logger(new ConsoleLogger()) + .dispatch({ + onMessageClass(msg: MessageClass, ctx: IDispatchContext) { + ctx.logger.info("Source", { payload: msg.contents }); + }, + }) + .run(); diff --git a/examples/amqp-messages/src/model.ts b/examples/amqp-messages/src/model.ts new file mode 100644 index 00000000..85145df0 --- /dev/null +++ b/examples/amqp-messages/src/model.ts @@ -0,0 +1,10 @@ +/* +Copyright (c) Walmart Inc. + +This source code is licensed under the Apache 2.0 license found in the +LICENSE file in the root directory of this source tree. +*/ + +export class MessageClass { + public constructor(public contents: string) {} +} diff --git a/examples/amqp-messages/src/producer.ts b/examples/amqp-messages/src/producer.ts new file mode 100644 index 00000000..18a10360 --- /dev/null +++ b/examples/amqp-messages/src/producer.ts @@ -0,0 +1,53 @@ +/* +Copyright (c) Walmart Inc. + +This source code is licensed under the Apache 2.0 license found in the +LICENSE file in the root directory of this source tree. +*/ + +import { + Application, + ConsoleLogger, + StaticInputSource, + IDispatchContext, + JsonMessageEncoder, +} from "@walmartlabs/cookie-cutter-core"; +import { amqpSink } from "@walmartlabs/cookie-cutter-amqp"; +import { MessageClass } from "./model"; + +// Before running this example, please adjust the code to include your AMQP Broker (RabbitMQ) connection details. +const AMQP_CONFIG = { + server: { + host: "localhost", + }, + queue: { + name: "defaultQueueName", + }, + encoder: new JsonMessageEncoder(), +}; + +Application.create() + .input() + .add( + new StaticInputSource([ + { + type: MessageClass.name, + payload: new MessageClass("Message #1"), + }, + { + type: MessageClass.name, + payload: new MessageClass("Message #2"), + }, + ]) + ) + .done() + .logger(new ConsoleLogger()) + .dispatch({ + async onMessageClass(msg: MessageClass, ctx: IDispatchContext) { + ctx.publish(MessageClass, msg); + }, + }) + .output() + .published(amqpSink(AMQP_CONFIG)) + .done() + .run(); diff --git a/examples/amqp-messages/tsconfig.json b/examples/amqp-messages/tsconfig.json new file mode 100644 index 00000000..d70b99d5 --- /dev/null +++ b/examples/amqp-messages/tsconfig.json @@ -0,0 +1,9 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "outDir": "./dist", + "rootDir": "./src" + }, + "exclude": ["node_modules", "dist"], + "include": ["src/**/*.ts"] +} diff --git a/examples/azure-queue/package.json b/examples/azure-queue/package.json index deaa3bc5..00ca3036 100644 --- a/examples/azure-queue/package.json +++ b/examples/azure-queue/package.json @@ -4,9 +4,9 @@ "version": "0.0.0", "license": "Apache-2.0", "dependencies": { - "@walmartlabs/cookie-cutter-core": "^1.2.0", - "@walmartlabs/cookie-cutter-azure": "^1.2.0", - "@walmartlabs/cookie-cutter-timer": "^1.2.0", + "@walmartlabs/cookie-cutter-core": "^1.3.0", + "@walmartlabs/cookie-cutter-azure": "^1.3.0", + "@walmartlabs/cookie-cutter-timer": "^1.3.0", "config": "3.3.1" }, "scripts": { diff --git a/examples/custom-sink/package.json b/examples/custom-sink/package.json index 953622a6..f11c994e 100644 --- a/examples/custom-sink/package.json +++ b/examples/custom-sink/package.json @@ -4,7 +4,7 @@ "version": "0.0.0", "license": "Apache-2.0", "dependencies": { - "@walmartlabs/cookie-cutter-core": "^1.2.0" + "@walmartlabs/cookie-cutter-core": "^1.3.0" }, "scripts": { "build": "tsc", diff --git a/examples/custom-source/package.json b/examples/custom-source/package.json index 754402b9..6114a03b 100644 --- a/examples/custom-source/package.json +++ b/examples/custom-source/package.json @@ -4,7 +4,7 @@ "version": "0.0.0", "license": "Apache-2.0", "dependencies": { - "@walmartlabs/cookie-cutter-core": "^1.2.0" + "@walmartlabs/cookie-cutter-core": "^1.3.0" }, "scripts": { "build": "tsc", diff --git a/examples/grpc-chat/package.json b/examples/grpc-chat/package.json index eb07c766..8421ba80 100644 --- a/examples/grpc-chat/package.json +++ b/examples/grpc-chat/package.json @@ -4,8 +4,8 @@ "version": "0.0.0", "license": "Apache-2.0", "dependencies": { - "@walmartlabs/cookie-cutter-core": "^1.2.0", - "@walmartlabs/cookie-cutter-grpc": "^1.2.0", + "@walmartlabs/cookie-cutter-core": "^1.3.0", + "@walmartlabs/cookie-cutter-grpc": "^1.3.0", "inquirer": "7.1.0" }, "devDependencies": { diff --git a/examples/grpc-echo-service/package.json b/examples/grpc-echo-service/package.json index e3d7fa74..4b628d96 100644 --- a/examples/grpc-echo-service/package.json +++ b/examples/grpc-echo-service/package.json @@ -4,8 +4,8 @@ "version": "0.0.0", "license": "Apache-2.0", "dependencies": { - "@walmartlabs/cookie-cutter-core": "^1.2.0", - "@walmartlabs/cookie-cutter-grpc": "^1.2.0", + "@walmartlabs/cookie-cutter-core": "^1.3.0", + "@walmartlabs/cookie-cutter-grpc": "^1.3.0", "inquirer": "7.1.0" }, "devDependencies": { diff --git a/examples/hello-world/package.json b/examples/hello-world/package.json index da4e3130..a3e8f866 100644 --- a/examples/hello-world/package.json +++ b/examples/hello-world/package.json @@ -4,7 +4,7 @@ "version": "0.0.0", "license": "Apache-2.0", "dependencies": { - "@walmartlabs/cookie-cutter-core": "^1.2.0" + "@walmartlabs/cookie-cutter-core": "^1.3.0" }, "scripts": { "build": "tsc", diff --git a/examples/integration-tests/package.json b/examples/integration-tests/package.json index 23421f62..3afd556b 100644 --- a/examples/integration-tests/package.json +++ b/examples/integration-tests/package.json @@ -4,8 +4,8 @@ "version": "0.0.0", "license": "Apache-2.0", "dependencies": { - "@walmartlabs/cookie-cutter-core": "^1.2.0", - "@walmartlabs/cookie-cutter-grpc": "^1.2.0" + "@walmartlabs/cookie-cutter-core": "^1.3.0", + "@walmartlabs/cookie-cutter-grpc": "^1.3.0" }, "devDependencies": { "protobufjs": "6.9.0" diff --git a/examples/kafka-events/package.json b/examples/kafka-events/package.json index fb6574de..11625fa2 100644 --- a/examples/kafka-events/package.json +++ b/examples/kafka-events/package.json @@ -4,8 +4,8 @@ "version": "0.0.0", "license": "Apache-2.0", "dependencies": { - "@walmartlabs/cookie-cutter-core": "^1.2.0", - "@walmartlabs/cookie-cutter-kafka": "^1.2.0" + "@walmartlabs/cookie-cutter-core": "^1.3.0", + "@walmartlabs/cookie-cutter-kafka": "^1.3.0" }, "scripts": { "build": "tsc", diff --git a/examples/kafka-projector/package.json b/examples/kafka-projector/package.json index b3cfef84..b56cb979 100644 --- a/examples/kafka-projector/package.json +++ b/examples/kafka-projector/package.json @@ -4,8 +4,8 @@ "version": "0.0.0", "license": "Apache-2.0", "dependencies": { - "@walmartlabs/cookie-cutter-core": "^1.2.0", - "@walmartlabs/cookie-cutter-kafka": "^1.2.0" + "@walmartlabs/cookie-cutter-core": "^1.3.0", + "@walmartlabs/cookie-cutter-kafka": "^1.3.0" }, "scripts": { "build": "tsc", diff --git a/examples/metrics/package.json b/examples/metrics/package.json index 91d6e4bd..63a1f81b 100644 --- a/examples/metrics/package.json +++ b/examples/metrics/package.json @@ -4,7 +4,7 @@ "version": "0.0.0", "license": "Apache-2.0", "dependencies": { - "@walmartlabs/cookie-cutter-core": "^1.2.0" + "@walmartlabs/cookie-cutter-core": "^1.3.0" }, "scripts": { "build": "tsc", diff --git a/examples/redis-service/package.json b/examples/redis-service/package.json index c248731a..f04c688f 100644 --- a/examples/redis-service/package.json +++ b/examples/redis-service/package.json @@ -4,8 +4,8 @@ "version": "0.0.0", "license": "Apache-2.0", "dependencies": { - "@walmartlabs/cookie-cutter-core": "^1.2.0", - "@walmartlabs/cookie-cutter-redis": "^1.2.0", + "@walmartlabs/cookie-cutter-core": "^1.3.0", + "@walmartlabs/cookie-cutter-redis": "^1.3.0", "config": "3.3.1" }, "scripts": { diff --git a/examples/state-event-sourced/package.json b/examples/state-event-sourced/package.json index 49d41dc4..a04be105 100644 --- a/examples/state-event-sourced/package.json +++ b/examples/state-event-sourced/package.json @@ -4,7 +4,7 @@ "version": "0.0.0", "license": "Apache-2.0", "dependencies": { - "@walmartlabs/cookie-cutter-core": "^1.2.0" + "@walmartlabs/cookie-cutter-core": "^1.3.0" }, "scripts": { "build": "tsc", diff --git a/package.json b/package.json index e2b42e2d..60566b83 100644 --- a/package.json +++ b/package.json @@ -7,23 +7,30 @@ "examples/*" ], "resolutions": { - "marked": "^0.7.0" + "lz4": "0.6.3", + "marked": "^0.7.0", + "bl": "^4.0.3", + "node-fetch": "^2.6.1", + "node-forge": "^0.10" + }, + "engines": { + "node": ">=10.0.0" }, "devDependencies": { "@types/expect": "24.3.0", "@types/jest": "25.2.1", "@types/long": "4.0.1", - "@types/node": "8.10.59", + "@types/node": "10.17.30", "glob": "7.1.6", "jest": "25.5.4", "jest-junit": "10.0.0", "prettier": "1.19.1", "semver": "7.3.2", "ts-jest": "25.5.1", - "tslint": "6.1.2", + "tslint": "6.1.3", "tslint-config-prettier": "1.18.0", "tslint-plugin-prettier": "2.3.0", - "typescript": "3.8.3" + "typescript": "3.9.4" }, "scripts": { "build": "yarn workspaces run build", diff --git a/packages/amqp/docker-compose.yml b/packages/amqp/docker-compose.yml new file mode 100644 index 00000000..8f4770e6 --- /dev/null +++ b/packages/amqp/docker-compose.yml @@ -0,0 +1,10 @@ +version: "3" +services: + rabbitmq: + image: rabbitmq:latest + ports: + - "5672:5672" + environment: + - RABBITMQ_DEFAULT_USER=test + - RABBITMQ_DEFAULT_PASS=test + - RABBITMQ_DEFAULT_VHOST=test diff --git a/packages/amqp/package.json b/packages/amqp/package.json new file mode 100644 index 00000000..d98474c1 --- /dev/null +++ b/packages/amqp/package.json @@ -0,0 +1,29 @@ +{ + "name": "@walmartlabs/cookie-cutter-amqp", + "version": "1.3.0", + "license": "Apache-2.0", + "main": "dist/index.js", + "types": "dist/index.d.ts", + "homepage": "https://walmartlabs.github.io/cookie-cutter", + "repository": { + "type": "git", + "url": "https://github.com/walmartlabs/cookie-cutter.git" + }, + "bugs": { + "url": "https://github.com/walmartlabs/cookie-cutter/issues" + }, + "dependencies": { + "amqplib": "^0.5.6" + }, + "devDependencies": { + "@types/amqplib": "^0.5.13", + "@walmartlabs/cookie-cutter-core": "^1.3.0" + }, + "scripts": { + "build": "tsc", + "test": "jest --passWithNoTests --config=../../jest.unit.config.js --rootDir=.", + "integrate": "docker-compose up -d && jest --config=../../jest.integration.config.js --rootDir=.; R=$?; docker-compose down; bash -c \"exit $R\"", + "lint": "tslint --project tsconfig.json", + "lint:fix": "yarn run lint --fix" + } +} diff --git a/packages/amqp/src/AmqpSink.ts b/packages/amqp/src/AmqpSink.ts new file mode 100644 index 00000000..2b95ce9b --- /dev/null +++ b/packages/amqp/src/AmqpSink.ts @@ -0,0 +1,96 @@ +/* +Copyright (c) Walmart Inc. + +This source code is licensed under the Apache 2.0 license found in the +LICENSE file in the root directory of this source tree. +*/ + +import { + IOutputSink, + IOutputSinkGuarantees, + IPublishedMessage, + OutputSinkConsistencyLevel, + IRequireInitialization, + IDisposable, + IComponentContext, + DefaultComponentContext, + failSpan, + OpenTracingTagKeys, +} from "@walmartlabs/cookie-cutter-core"; +import { AmqpOpenTracingTagKeys, IAmqpConfiguration } from "."; +import * as amqp from "amqplib"; +import { Span, Tags, Tracer } from "opentracing"; + +export class AmqpSink + implements IOutputSink, IRequireInitialization, IDisposable { + private tracer: Tracer; + private conn: amqp.Connection; + private channel: amqp.Channel; + + constructor(private config: IAmqpConfiguration) { + this.tracer = DefaultComponentContext.tracer; + } + + public async initialize(context: IComponentContext): Promise { + this.tracer = context.tracer; + // note: username and password are set to default amqp credentials(guest) by underlying library if not set or set to undefined + const options: amqp.Options.Connect = { + protocol: "amqp", + hostname: this.config.server.host, + port: this.config.server.port, + username: this.config.server.username, + password: this.config.server.password, + vhost: this.config.server.vhost, + }; + this.conn = await amqp.connect(options); + this.channel = await this.conn.createChannel(); + const queueName = this.config.queue.name; + const durable = this.config.queue.durable; + await this.channel.assertQueue(queueName, { durable }); + } + + public async sink(output: IterableIterator): Promise { + for (const msg of output) { + const span = this.tracer.startSpan("Producing Message For AMQP", { + childOf: msg.spanContext, + }); + this.spanLogAndSetTags(span, this.sink.name); + const payload = Buffer.from(this.config.encoder.encode(msg.message)); + try { + this.channel.sendToQueue(this.config.queue.name, payload, { + persistent: true, + type: msg.message.type, + contentType: this.config.encoder.mimeType, + expiration: this.config.message ? this.config.message.expiration : undefined, + }); + } catch (e) { + failSpan(span, e); + throw e; + } finally { + span.finish(); + } + } + } + + private spanLogAndSetTags(span: Span, funcName: string): void { + span.setTag(Tags.SPAN_KIND, Tags.SPAN_KIND_MESSAGING_PRODUCER); + span.setTag(Tags.COMPONENT, "cookie-cutter-amqp"); + span.setTag(Tags.PEER_SERVICE, "RabbitMQ"); + span.setTag(Tags.SAMPLING_PRIORITY, 1); + span.setTag(OpenTracingTagKeys.FunctionName, funcName); + span.setTag(AmqpOpenTracingTagKeys.QueueName, this.config.queue.name); + } + + public get guarantees(): IOutputSinkGuarantees { + return { + consistency: OutputSinkConsistencyLevel.None, + idempotent: false, + }; + } + + public async dispose(): Promise { + if (this.conn) { + await this.conn.close(); // also closes channel + } + } +} diff --git a/packages/amqp/src/AmqpSource.ts b/packages/amqp/src/AmqpSource.ts new file mode 100644 index 00000000..5600cae9 --- /dev/null +++ b/packages/amqp/src/AmqpSource.ts @@ -0,0 +1,175 @@ +/* +Copyright (c) Walmart Inc. + +This source code is licensed under the Apache 2.0 license found in the +LICENSE file in the root directory of this source tree. +*/ + +import { + IInputSource, + MessageRef, + IMetadata, + IComponentContext, + IRequireInitialization, + IDisposable, + BoundedPriorityQueue, + ILogger, + DefaultComponentContext, + EncodedMessage, + IMessage, + failSpan, + IMetrics, +} from "@walmartlabs/cookie-cutter-core"; +import { AmqpMetadata, AmqpOpenTracingTagKeys, IAmqpConfiguration } from "."; +import { Span, SpanContext, Tags, Tracer } from "opentracing"; +import * as amqp from "amqplib"; + +enum AmqpMetrics { + UnassignedMessageCount = "cookie_cutter.amqp_consumer.unassigned_message_count", + ConsumerCount = "cookie_cutter.amqp_consumer.consumer_count", + MsgReceived = "cookie_cutter.amqp_consumer.input_msg_received", + MsgProcessed = "cookie_cutter.amqp_consumer.input_msg_processed", +} +enum AmqpMetricResult { + Success = "success", + Error = "error", +} + +export class AmqpSource implements IInputSource, IRequireInitialization, IDisposable { + private pipe = new BoundedPriorityQueue(100); + private logger: ILogger; + private metrics: IMetrics; + private tracer: Tracer; + private conn: amqp.Connection; + private channel: amqp.Channel; + private running: boolean; + private loop: NodeJS.Timer; + + constructor(private config: IAmqpConfiguration) { + this.logger = DefaultComponentContext.logger; + this.metrics = DefaultComponentContext.metrics; + this.tracer = DefaultComponentContext.tracer; + } + + public async initialize(context: IComponentContext): Promise { + this.logger = context.logger; + this.metrics = context.metrics; + this.tracer = context.tracer; + const options: amqp.Options.Connect = { + protocol: "amqp", + hostname: this.config.server.host, + port: this.config.server.port, + username: this.config.server.username, + password: this.config.server.password, + vhost: this.config.server.vhost, + }; + this.conn = await amqp.connect(options); + this.channel = await this.conn.createChannel(); + const queueName = this.config.queue.name; + const durable = this.config.queue.durable; + await this.channel.assertQueue(queueName, { durable }); + this.channel.prefetch(50); + } + + public async *start(): AsyncIterableIterator { + this.running = true; + // tslint:disable-next-line:no-floating-promises + this.loopAmqpQueueUnassignedMessageCount(); + const queueName = this.config.queue.name; + const host = this.config.server.host; + const onMessage = async (msg: amqp.ConsumeMessage) => { + const event_type = msg.properties.type; + const span = this.tracer.startSpan("Consuming Message For AMQP", { + childOf: undefined, + }); + this.spanLogAndSetTags(span, queueName); + if (msg !== null) { + this.metrics.increment(AmqpMetrics.MsgReceived, { + host, + queueName, + event_type, + }); + const metadata: IMetadata = { + [AmqpMetadata.QueueName]: queueName, + [AmqpMetadata.Redelivered]: msg.fields.redelivered, + [AmqpMetadata.Expiration]: msg.properties.expiration, + }; + const codedMessage: IMessage = new EncodedMessage( + this.config.encoder, + event_type, + msg.content + ); + const msgRef = new MessageRef(metadata, codedMessage, new SpanContext()); + await this.pipe.enqueue(msgRef); + let result = AmqpMetricResult.Error; + msgRef.once("released", async (_, err) => { + try { + if (!err) { + this.channel.ack(msg); + result = AmqpMetricResult.Success; + } else { + failSpan(span, err); + } + } catch (e) { + failSpan(span, e); + throw e; + } finally { + span.finish(); + this.metrics.increment(AmqpMetrics.MsgProcessed, { + host, + queueName, + event_type, + result, + }); + } + }); + } + }; + await this.channel.consume(this.config.queue.name, onMessage, { noAck: false }); + yield* this.pipe.iterate(); + } + + private spanLogAndSetTags(span: Span, queueName): void { + span.setTag(Tags.SPAN_KIND, Tags.SPAN_KIND_MESSAGING_CONSUMER); + span.setTag(Tags.COMPONENT, "cookie-cutter-amqp"); + span.setTag(Tags.PEER_SERVICE, "RabbitMQ"); + span.setTag(Tags.SAMPLING_PRIORITY, 1); + span.setTag(AmqpOpenTracingTagKeys.QueueName, queueName); + } + + private loopAmqpQueueUnassignedMessageCount = async () => { + if (this.running) { + const queueName = this.config.queue.name; + try { + const queueMetadata = await this.channel.checkQueue(queueName); + this.metrics.gauge(AmqpMetrics.UnassignedMessageCount, queueMetadata.messageCount, { + host: this.config.server.host, + queueName, + }); + this.metrics.gauge(AmqpMetrics.ConsumerCount, queueMetadata.consumerCount, { + host: this.config.server.host, + queueName, + }); + } catch (e) { + this.logger.warn("AmqpSource|Failed to checkQueue", { queueName }); + } + if (this.running) { + this.loop = setTimeout(this.loopAmqpQueueUnassignedMessageCount, 1000); + } + } + }; + + public async dispose(): Promise { + if (this.conn) { + await this.conn.close(); // also closes channel + } + } + + public async stop(): Promise { + this.running = false; + if (this.loop) { + clearTimeout(this.loop); + } + this.pipe.close(); + } +} diff --git a/packages/amqp/src/__test__/amqp.integration.test.ts b/packages/amqp/src/__test__/amqp.integration.test.ts new file mode 100644 index 00000000..8e631cc3 --- /dev/null +++ b/packages/amqp/src/__test__/amqp.integration.test.ts @@ -0,0 +1,120 @@ +/* +Copyright (c) Walmart Inc. + +This source code is licensed under the Apache 2.0 license found in the +LICENSE file in the root directory of this source tree. +*/ + +import { + Application, + ConsoleLogger, + StaticInputSource, + IMessage, + IDispatchContext, + CapturingOutputSink, + ParallelismMode, + ErrorHandlingMode, + sleep, + JsonMessageEncoder, +} from "@walmartlabs/cookie-cutter-core"; +import { IAmqpConfiguration, amqpSink, amqpSource } from ".."; +import * as amqp from "amqplib"; + +jest.setTimeout(10000); + +async function waitForServer() { + const options: amqp.Options.Connect = { + protocol: "amqp", + hostname: "localhost", + username: "test", + password: "test", + vhost: "test", + }; + while (true) { + try { + const conn = await amqp.connect(options); + await conn.close(); + break; + } catch (e) { + await sleep(500); + } + } +} + +describe("AmqpSink and AmqpSource", () => { + beforeAll(async () => { + await waitForServer(); + }); + class MessageClass { + public constructor(public payload: string) {} + } + + function inputGen(num: number): IMessage[] { + const input: IMessage[] = []; + for (let ii = 1; ii <= num; ii++) { + input.push({ + type: MessageClass.name, + payload: new MessageClass(`Message #${ii}`), + }); + } + return input; + } + + const numMessages = 200; + const config: IAmqpConfiguration = { + server: { + host: "localhost", + username: "test", + password: "test", + vhost: "test", + }, + queue: { + name: "defaultQueueName", + }, + encoder: new JsonMessageEncoder(), + }; + + it("produces messages with AmqpSink", async () => { + await expect( + Application.create() + .logger(new ConsoleLogger()) + .input() + .add(new StaticInputSource(inputGen(numMessages))) + .done() + .dispatch({ + async onMessageClass(msg: MessageClass, ctx: IDispatchContext) { + ctx.publish(MessageClass, msg); + }, + }) + .output() + .published(amqpSink(config)) + .done() + .run() + ).resolves.toBe(undefined); + }); + + it("consumes messages with AmqpSource", async () => { + const output = []; + const consumer = Application.create() + .logger(new ConsoleLogger()) + .input() + .add(amqpSource(config)) + .done() + .dispatch({ + onMessageClass(msg: MessageClass, ctx: IDispatchContext) { + ctx.publish(MessageClass, msg); + }, + }) + .output() + .published(new CapturingOutputSink(output)) + .done() + .run(ErrorHandlingMode.LogAndContinue, ParallelismMode.Serial); + + while (output.length < numMessages) { + await sleep(50); + } + consumer.cancel(); + await consumer; + expect(output.length).toBe(numMessages); + }); +}); diff --git a/packages/amqp/src/config.ts b/packages/amqp/src/config.ts new file mode 100644 index 00000000..d488af41 --- /dev/null +++ b/packages/amqp/src/config.ts @@ -0,0 +1,117 @@ +/* +Copyright (c) Walmart Inc. + +This source code is licensed under the Apache 2.0 license found in the +LICENSE file in the root directory of this source tree. +*/ + +import { config, IMessageEncoder } from "@walmartlabs/cookie-cutter-core"; +import { IAmqpConfiguration, IAmqpQueueConfig, IAmqpMessageConfig, IAmqpServerConfig } from "."; + +@config.section +export class AmqpServerConfig implements IAmqpServerConfig { + @config.field(config.converters.string) + public set host(_: string) { + config.noop(); + } + public get host(): string { + return config.noop(); + } + + @config.field(config.converters.number) + public set port(_: number) { + config.noop(); + } + public get port(): number { + return config.noop(); + } + + @config.field(config.converters.string) + public set username(_: string) { + config.noop(); + } + public get username(): string { + return config.noop(); + } + + @config.field(config.converters.string) + public set password(_: string) { + config.noop(); + } + public get password(): string { + return config.noop(); + } + + @config.field(config.converters.string) + public set vhost(_: string) { + config.noop(); + } + public get vhost(): string { + return config.noop(); + } +} + +@config.section +export class AmqpQueueConfig implements IAmqpQueueConfig { + @config.field(config.converters.string) + public set name(_: string) { + config.noop(); + } + public get name(): string { + return config.noop(); + } + + @config.field(config.converters.boolean) + public set durable(_: boolean) { + config.noop(); + } + public get durable(): boolean { + return config.noop(); + } +} + +@config.section +export class AmqpMessageConfig implements IAmqpMessageConfig { + @config.field(config.converters.timespan) + public set expiration(_: number) { + config.noop(); + } + public get expiration(): number { + return config.noop(); + } +} + +@config.section +export class AmqpConfiguration implements IAmqpConfiguration { + @config.field(AmqpServerConfig) + public set server(_: IAmqpServerConfig) { + config.noop(); + } + public get server(): IAmqpServerConfig { + return config.noop(); + } + + @config.field(AmqpQueueConfig) + public set queue(_: IAmqpQueueConfig) { + config.noop(); + } + public get queue(): IAmqpQueueConfig { + return config.noop(); + } + + @config.field(AmqpMessageConfig) + public set message(_: IAmqpMessageConfig) { + config.noop(); + } + public get message(): IAmqpMessageConfig { + return config.noop(); + } + + @config.field(config.converters.none) + public set encoder(_: IMessageEncoder) { + config.noop(); + } + public get encoder(): IMessageEncoder { + return config.noop(); + } +} diff --git a/packages/amqp/src/index.ts b/packages/amqp/src/index.ts new file mode 100644 index 00000000..8e77dda4 --- /dev/null +++ b/packages/amqp/src/index.ts @@ -0,0 +1,70 @@ +/* +Copyright (c) Walmart Inc. + +This source code is licensed under the Apache 2.0 license found in the +LICENSE file in the root directory of this source tree. +*/ + +import { + IInputSource, + IOutputSink, + IPublishedMessage, + IMessageEncoder, + JsonMessageEncoder, +} from "@walmartlabs/cookie-cutter-core"; +import { AmqpConfiguration } from "./config"; +import { config } from "@walmartlabs/cookie-cutter-core"; +import { AmqpSource } from "./AmqpSource"; +import { AmqpSink } from "./AmqpSink"; + +export enum AmqpMetadata { + QueueName = "amqp.queue_name", + Redelivered = "amqp.redelivered", + Expiration = "amqp.expiration", +} + +export enum AmqpOpenTracingTagKeys { + QueueName = "amqp.queue_name", +} + +export interface IAmqpServerConfig { + readonly host: string; + readonly port?: number; + readonly username?: string; + readonly password?: string; + readonly vhost?: string; +} + +export interface IAmqpQueueConfig { + readonly name: string; + readonly durable?: boolean; +} + +export interface IAmqpMessageConfig { + readonly expiration?: number; +} + +export interface IAmqpConfiguration { + readonly server: IAmqpServerConfig; + readonly queue: IAmqpQueueConfig; + readonly message?: IAmqpMessageConfig; + readonly encoder: IMessageEncoder; +} + +export function amqpSource(configuration: IAmqpConfiguration): IInputSource { + configuration = config.parse(AmqpConfiguration, configuration, { + queue: { name: "defaultQueueName", durable: true }, + encoder: new JsonMessageEncoder(), + }); + + return new AmqpSource(configuration); +} + +export function amqpSink(configuration: IAmqpConfiguration): IOutputSink { + configuration = config.parse(AmqpConfiguration, configuration, { + queue: { name: "defaultQueueName", durable: true }, + encoder: new JsonMessageEncoder(), + }); + + return new AmqpSink(configuration); +} diff --git a/packages/amqp/tsconfig.json b/packages/amqp/tsconfig.json new file mode 100644 index 00000000..d70b99d5 --- /dev/null +++ b/packages/amqp/tsconfig.json @@ -0,0 +1,9 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "outDir": "./dist", + "rootDir": "./src" + }, + "exclude": ["node_modules", "dist"], + "include": ["src/**/*.ts"] +} diff --git a/packages/azure/package.json b/packages/azure/package.json index ca2436a4..da0ecb66 100644 --- a/packages/azure/package.json +++ b/packages/azure/package.json @@ -1,6 +1,6 @@ { "name": "@walmartlabs/cookie-cutter-azure", - "version": "1.2.1", + "version": "1.3.0", "license": "Apache-2.0", "main": "dist/index.js", "types": "dist/index.d.ts", @@ -13,18 +13,18 @@ "url": "https://github.com/walmartlabs/cookie-cutter/issues" }, "dependencies": { - "@azure/cosmos": "3.6.3", + "@azure/cosmos": "3.9.1", "azure-storage": "2.10.3", - "lodash": "4.17.15", + "lodash": "4.17.20", "opentracing": "0.14.4", "tunnel": "0.0.6", - "uuid": "8.0.0" + "uuid": "8.3.0" }, "peerDependencies": { - "@walmartlabs/cookie-cutter-core": "^1.2.0" + "@walmartlabs/cookie-cutter-core": "^1.3.0" }, "devDependencies": { - "@walmartlabs/cookie-cutter-core": "^1.2.0" + "@walmartlabs/cookie-cutter-core": "^1.3.0" }, "scripts": { "build": "tsc", diff --git a/packages/azure/src/__test__/event-sourced/internal/CosmosStateAggregationSource.test.ts b/packages/azure/src/__test__/event-sourced/internal/CosmosStateAggregationSource.test.ts index 994a176b..47e56e7e 100644 --- a/packages/azure/src/__test__/event-sourced/internal/CosmosStateAggregationSource.test.ts +++ b/packages/azure/src/__test__/event-sourced/internal/CosmosStateAggregationSource.test.ts @@ -22,7 +22,7 @@ describe("CosmosStateAggregationSource", () => { interface ITestSetup { readonly source: CosmosStateAggregationSource; readonly logSpy: jest.SpyInstance; - readonly querySpy: jest.SpyInstance, [SpanContext, ICosmosQuery]>; + readonly querySpy: jest.SpyInstance, [SpanContext, ICosmosQuery, string?]>; readonly snapshotSpy: jest.SpyInstance< Promise<[number, any]>, [SpanContext, string, number?] diff --git a/packages/azure/src/__test__/materialized/internal/MaterializedView.integration.test.ts b/packages/azure/src/__test__/materialized/internal/MaterializedView.integration.test.ts index db66c957..3979fab8 100644 --- a/packages/azure/src/__test__/materialized/internal/MaterializedView.integration.test.ts +++ b/packages/azure/src/__test__/materialized/internal/MaterializedView.integration.test.ts @@ -20,9 +20,17 @@ const url = "https://carrot.documents.azure.com:443/"; const key = process.env.COSMOS_SECRET_KEY; const databaseId = "tanvir-test-occ"; const collectionId = "occ"; +const newCollectedId = "occ2"; const encoder = new JsonMessageEncoder(); const sink = new CosmosOutputSink({ url, key, databaseId, collectionId, encoder }); const client = new CosmosClient({ url, key, databaseId, collectionId, encoder }); +const newSink = new CosmosOutputSink({ + url, + key, + databaseId, + collectionId: newCollectedId, + encoder, +}); describe.skip("Materialized Views", () => { const spanContext = {}; @@ -137,6 +145,93 @@ describe.skip("Materialized Views", () => { seqNum: 0, }); }); + + it("retrieves a document in the default collection", async () => { + const currentTime = new Date(); + const currentSn = 0; + const streamId = `default-collection-stream-${currentTime.getTime()}`; + const payload = { value: "foo" }; + await sink.sink( + iterate([ + { + state: new StateRef({}, streamId, currentSn), + message: { + type: DummyState.name, + payload, + }, + spanContext, + original: new MessageRef({}, null), + }, + ]), + undefined + ); + + const state = new CosmosStateProvider(DummyState, client, new JsonMessageEncoder()); + const stateRef = await state.get(undefined, streamId); + expect(stateRef).toMatchObject({ + state: new DummyState({ value: "foo" }), + key: streamId, + seqNum: currentSn + 1, + }); + }); + + it("retrieves a document in an unknown collection", async () => { + const currentTime = new Date(); + const currentSn = 0; + const streamId = `non-default-collection-stream-${currentTime.getTime()}`; + const payload = { value: "foo" }; + await newSink.sink( + iterate([ + { + state: new StateRef({}, streamId, currentSn), + message: { + type: DummyState.name, + payload, + }, + spanContext, + original: new MessageRef({}, null), + }, + ]), + undefined + ); + + const state = new CosmosStateProvider(DummyState, client, new JsonMessageEncoder()); + const stateRef = await state.get(undefined, `@unknown/${streamId}`); + expect(stateRef).toMatchObject({ + state: new DummyState(), + key: streamId, + seqNum: 0, + }); + }); + + it("retrieves a document in a given collection", async () => { + const currentTime = new Date(); + const currentSn = 0; + const streamId = `non-default-collection-stream-${currentTime.getTime()}`; + const payload = { value: "foo" }; + await newSink.sink( + iterate([ + { + state: new StateRef({}, streamId, currentSn), + message: { + type: DummyState.name, + payload, + }, + spanContext, + original: new MessageRef({}, null), + }, + ]), + undefined + ); + + const state = new CosmosStateProvider(DummyState, client, new JsonMessageEncoder()); + const stateRef = await state.get(undefined, `occ2/${streamId}`); + expect(stateRef).toMatchObject({ + state: new DummyState({ value: "foo" }), + key: streamId, + seqNum: currentSn + 1, + }); + }); }); describe("CosmosOutputSink", () => { it("deletes a non-existent document", async () => { diff --git a/packages/azure/src/__test__/utils/helpers.test.ts b/packages/azure/src/__test__/utils/helpers.test.ts new file mode 100644 index 00000000..0d95b98d --- /dev/null +++ b/packages/azure/src/__test__/utils/helpers.test.ts @@ -0,0 +1,42 @@ +/* +Copyright (c) Walmart Inc. + +This source code is licensed under the Apache 2.0 license found in the +LICENSE file in the root directory of this source tree. +*/ + +import { getCollectionInfo } from "../../utils/helpers"; + +describe("State Key Parsing", () => { + it("parses a state key with a collectionId overwrite", () => { + const inputKey = "@collection/key"; + const { collectionId, partitionKey } = getCollectionInfo(inputKey); + + expect(collectionId).toBe("collection"); + expect(partitionKey).toBe("key"); + }); + + it("parses a state key with no collectionId overwrite", () => { + const inputKey = "key"; + const { collectionId, partitionKey } = getCollectionInfo(inputKey); + + expect(collectionId).toBe(undefined); + expect(partitionKey).toBe("key"); + }); + + it("parses a state key with a state key in the @key format ", () => { + const inputKey = "@key"; + const { collectionId, partitionKey } = getCollectionInfo(inputKey); + + expect(collectionId).toBe(undefined); + expect(partitionKey).toBe("@key"); + }); + + it("parses a state key with an incorrectly formatted collectionId overwrite", () => { + const inputKey = "collection/key"; + const { collectionId, partitionKey } = getCollectionInfo(inputKey); + + expect(collectionId).toBe(undefined); + expect(partitionKey).toBe(undefined); + }); +}); diff --git a/packages/azure/src/index.ts b/packages/azure/src/index.ts index 9c3255d4..78711d90 100644 --- a/packages/azure/src/index.ts +++ b/packages/azure/src/index.ts @@ -42,7 +42,7 @@ export interface ICosmosQuery { } export interface ICosmosQueryClient { - query(spanContext: SpanContext, query: ICosmosQuery): Promise; + query(spanContext: SpanContext, query: ICosmosQuery, collectionId?: string): Promise; } export function cosmosQueryClient(configuration: ICosmosConfiguration): ICosmosQueryClient { diff --git a/packages/azure/src/materialized/internal/CosmosStateProvider.ts b/packages/azure/src/materialized/internal/CosmosStateProvider.ts index 99ade9d4..a11c75f7 100644 --- a/packages/azure/src/materialized/internal/CosmosStateProvider.ts +++ b/packages/azure/src/materialized/internal/CosmosStateProvider.ts @@ -24,6 +24,7 @@ import { SpanContext } from "opentracing"; import { isNullOrUndefined } from "util"; import { ICosmosQueryClient } from "../.."; import { ICosmosDocument } from "../../utils"; +import { getCollectionInfo } from "../../utils/helpers"; export class CosmosStateProvider, TSnapshot> extends MaterializedViewStateProvider @@ -47,11 +48,17 @@ export class CosmosStateProvider, TSnapshot> } public async get(spanContext: SpanContext, key: string): Promise> { - const result = await this.client.query(spanContext, { - query: `SELECT c.data, c.event_type, c.sn FROM c - WHERE c.stream_id=@stream_id`, - parameters: [{ name: "@stream_id", value: key }], - }); + const { collectionId, partitionKey } = getCollectionInfo(key); + + const result = await this.client.query( + spanContext, + { + query: `SELECT c.data, c.event_type, c.sn FROM c + WHERE c.stream_id=@stream_id`, + parameters: [{ name: "@stream_id", value: partitionKey }], + }, + collectionId + ); if (result.length > 1) { throw new Error(`found multiple documents for key '${key}', this is not expected`); diff --git a/packages/azure/src/streaming/index.ts b/packages/azure/src/streaming/index.ts index f3f2865f..c0c2392c 100644 --- a/packages/azure/src/streaming/index.ts +++ b/packages/azure/src/streaming/index.ts @@ -29,6 +29,24 @@ export interface IQueueMessagePreprocessor { process(payload: string): IQueueMessage; } +export interface IDeadLetterQueueConfiguration { + readonly queueName: string; + readonly maxDequeueCount: number; + /** + * The time-to-live interval for the message, in seconds. The maximum time-to-live allowed is 7 days. If this parameter + * is omitted, the default time-to-live is 7 days (604800 seconds) + */ + messageTimeToLive?: number; + /** + * Specifies the new visibility timeout value, in seconds, relative to server time. The new value must be larger than or + * equal to 0, and cannot be larger than 7 days (604800 seconds). The visibility timeout of a message cannot be set to a value later than + * the expiry time (calculated based on time-to-live when updating message). visibilitytimeout should be set to a value smaller than the time-to-live value. + */ + visibilityTimeout?: number; + readonly retryCount?: number; + readonly retryInterval?: number; +} + export interface IQueueConfiguration { readonly url?: string; readonly storageAccount: string; @@ -61,12 +79,15 @@ export interface IQueueSourceConfiguration { * The visibility timeout of a message can be set to a value later than the expiry time. */ visibilityTimeout?: number; + readonly deadLetterQueue?: IDeadLetterQueueConfiguration; } export enum QueueMetadata { QueueName = "queue.name", VisibilityTimeout = "queue.visibility_timeout", + VisibilityTimeoutMs = "queue.visibility_timeout_ms", TimeToLive = "queue.time_to_live", + TimeToLiveMs = "queue.time_to_live_ms", DequeueCount = "queue.dequeue_count", TimeToNextVisible = "queue.time_to_next_visible", MessageId = "queue.message_id", diff --git a/packages/azure/src/streaming/internal/QueueInputSource.ts b/packages/azure/src/streaming/internal/QueueInputSource.ts index d13d1724..290d0c18 100644 --- a/packages/azure/src/streaming/internal/QueueInputSource.ts +++ b/packages/azure/src/streaming/internal/QueueInputSource.ts @@ -40,6 +40,7 @@ interface IBufferToJSON { export class QueueInputSource implements IInputSource, IRequireInitialization { private readonly client: QueueClient & IRequireInitialization; + private readonly deadLetterClient: (QueueClient & IRequireInitialization) | undefined; private readonly readOptions: IQueueReadOptions; private readonly encoder: IMessageEncoder; private metrics: IMetrics; @@ -57,6 +58,21 @@ export class QueueInputSource implements IInputSource, IRequireInitialization { this.metrics = DefaultComponentContext.metrics; this.tracer = DefaultComponentContext.tracer; this.logger = DefaultComponentContext.logger; + if (config.deadLetterQueue) { + const deadLetterConfig: IQueueConfiguration = { + createQueueIfNotExists: config.createQueueIfNotExists, + encoder: config.encoder, + queueName: config.deadLetterQueue.queueName, + storageAccessKey: config.storageAccessKey, + storageAccount: config.storageAccount, + largeItemBlobContainer: config.largeItemBlobContainer, + preprocessor: config.preprocessor, + retryCount: config.deadLetterQueue.retryCount || config.retryCount, + retryInterval: config.deadLetterQueue.retryInterval || config.retryInterval, + url: config.url, + }; + this.deadLetterClient = QueueClientWithLargeItemSupport.create(deadLetterConfig); + } } public async initialize(context: IComponentContext): Promise { @@ -64,6 +80,9 @@ export class QueueInputSource implements IInputSource, IRequireInitialization { this.logger = context.logger; this.tracer = context.tracer; await this.client.initialize(context); + if (this.deadLetterClient) { + await this.deadLetterClient.initialize(context); + } } public async *start(): AsyncIterableIterator { @@ -107,6 +126,36 @@ export class QueueInputSource implements IInputSource, IRequireInitialization { [QueueMetadata.PopReceipt]: message.headers[QueueMetadata.PopReceipt], }; + if ( + this.deadLetterClient && + metadata[QueueMetadata.DequeueCount] > + this.config.deadLetterQueue.maxDequeueCount + ) { + try { + await this.deadLetterClient.write( + spanContext, + payload, + { [EventSourcedMetadata.EventType]: event_type }, + { + visibilityTimeout: this.config.deadLetterQueue.visibilityTimeout, + messageTimeToLive: this.config.deadLetterQueue.messageTimeToLive, + } + ); + await this.client.markAsProcessed( + spanContext, + message.headers[QueueMetadata.MessageId], + message.headers[QueueMetadata.PopReceipt], + message.headers[QueueMetadata.QueueName] + ); + } catch (e) { + span.log({ reprocess: true }); + failSpan(span, e); + } finally { + span.finish(); + } + continue; + } + const msgRef = new MessageRef(metadata, msg, span.context()); msgRef.once("released", async (_msg: MessageRef, _value?: any, error?: Error) => { try { diff --git a/packages/azure/src/streaming/internal/QueueOutputSink.ts b/packages/azure/src/streaming/internal/QueueOutputSink.ts index de584b29..1a5d4b03 100644 --- a/packages/azure/src/streaming/internal/QueueOutputSink.ts +++ b/packages/azure/src/streaming/internal/QueueOutputSink.ts @@ -41,8 +41,16 @@ export class QueueOutputSink implements IOutputSink, IRequire public async sink(output: IterableIterator): Promise { for (const msg of output) { const queueName = msg.metadata[QueueMetadata.QueueName]; - const visibilityTimeout = msg.metadata[QueueMetadata.VisibilityTimeout]; - const messageTimeToLive = msg.metadata[QueueMetadata.TimeToLive]; + const visibilityTimeoutSeconds = msg.metadata[QueueMetadata.VisibilityTimeout]; + const messageTimeToLiveSeconds = msg.metadata[QueueMetadata.TimeToLive]; + const visibilityTimeoutMs = msg.metadata[QueueMetadata.VisibilityTimeoutMs]; + const messageTimeToLiveMs = msg.metadata[QueueMetadata.TimeToLiveMs]; + const visibilityTimeout = visibilityTimeoutMs + ? Math.floor(visibilityTimeoutMs / 1000) + : visibilityTimeoutSeconds; + const messageTimeToLive = messageTimeToLiveMs + ? Math.floor(messageTimeToLiveMs / 1000) + : messageTimeToLiveSeconds; const headers = { [EventSourcedMetadata.EventType]: msg.message.type, }; diff --git a/packages/azure/src/streaming/internal/config.ts b/packages/azure/src/streaming/internal/config.ts index 1b39606a..f23ac855 100644 --- a/packages/azure/src/streaming/internal/config.ts +++ b/packages/azure/src/streaming/internal/config.ts @@ -6,7 +6,73 @@ LICENSE file in the root directory of this source tree. */ import { config, IMessageEncoder } from "@walmartlabs/cookie-cutter-core"; -import { IQueueConfiguration, IQueueMessagePreprocessor, IQueueSourceConfiguration } from ".."; +import { + IQueueConfiguration, + IQueueMessagePreprocessor, + IQueueSourceConfiguration, + IDeadLetterQueueConfiguration, +} from ".."; + +@config.section +export class DeadLetterQueueConfiguration implements IDeadLetterQueueConfiguration { + @config.field(config.converters.string) + public set queueName(_: string) { + config.noop(); + } + public get queueName(): string { + return config.noop(); + } + + @config.field(config.converters.number) + public set maxDequeueCount(_: number) { + config.noop(); + } + public get maxDequeueCount(): number { + return config.noop(); + } + + @config.field( + config.converters.timespanOf( + config.TimeSpanTargetUnit.Seconds, + config.TimeSpanTargetUnit.Seconds + ) + ) + public set visibilityTimeout(_: number) { + config.noop(); + } + public get visibilityTimeout(): number { + return config.noop(); + } + + @config.field( + config.converters.timespanOf( + config.TimeSpanTargetUnit.Seconds, + config.TimeSpanTargetUnit.Seconds + ) + ) + public set messageTimeToLive(_: number) { + config.noop(); + } + public get messageTimeToLive(): number { + return config.noop(); + } + + @config.field(config.converters.number) + public set retryCount(_: number) { + config.noop(); + } + public get retryCount(): number { + return config.noop(); + } + + @config.field(config.converters.timespan) + public set retryInterval(_: number) { + config.noop(); + } + public get retryInterval(): number { + return config.noop(); + } +} @config.section export class QueueConfiguration implements IQueueConfiguration { @@ -114,4 +180,12 @@ export class QueueSourceConfiguration extends QueueConfiguration public get visibilityTimeout(): number { return config.noop(); } + + @config.field(DeadLetterQueueConfiguration) + public set deadLetterQueue(_: IDeadLetterQueueConfiguration) { + config.noop(); + } + public get deadLetterQueue(): IDeadLetterQueueConfiguration { + return config.noop(); + } } diff --git a/packages/azure/src/utils/CosmosClient.ts b/packages/azure/src/utils/CosmosClient.ts index 97e46864..ba29013d 100644 --- a/packages/azure/src/utils/CosmosClient.ts +++ b/packages/azure/src/utils/CosmosClient.ts @@ -31,10 +31,21 @@ import * as url from "url"; import * as uuid from "uuid"; import { isSequenceConflict } from "."; import { ICosmosConfiguration, ICosmosQuery, ICosmosQueryClient } from ".."; +import { getCollectionInfo } from "./helpers"; export interface ICosmosWriteClient { - upsert(document: any, partitionKey: string, currentSn: number): Promise; - bulkInsert(documents: any[], partitionKey: string, validateSn: boolean): Promise; + upsert( + document: any, + partitionKey: string, + currentSn: number, + collectionId?: string + ): Promise; + bulkInsert( + documents: any[], + partitionKey: string, + validateSn: boolean, + collectionId?: string + ): Promise; } enum CosmosMetrics { @@ -133,13 +144,13 @@ export class CosmosClient } } - private async container(): Promise { + private async container(collectionId?: string): Promise { return await this.client .database(this.config.databaseId) - .container(this.config.collectionId); + .container(collectionId ?? this.config.collectionId); } - private async initializeStoredProcedure(sprocID: string): Promise { + private async initializeStoredProcedure(sprocID: string, collectionId?: string): Promise { const sprocPath = SPROCS.get(sprocID); if (!sprocPath) { throw new Error( @@ -149,7 +160,7 @@ export class CosmosClient const file = fs.readFileSync(path.resolve(__dirname, sprocPath)); const sprocBody = file.toString(); - const container = await this.container(); + const container = await this.container(collectionId); const query = { query: "SELECT * FROM collection c WHERE c.id = @id", parameters: [{ name: "@id", value: sprocID }], @@ -219,14 +230,15 @@ export class CosmosClient sprocID: string, partitionKey: string, documents: any[], - parameters: any[] + parameters: any[], + collectionId?: string ): Promise { const spans: Span[] = []; let requestCharge = 0; try { - const container = await this.container(); + const container = await this.container(collectionId); if (!this.spInitialized.get(sprocID)) { - throw new Error(`Stored Procedure wasn't correctly registered - id: ${sprocID}`); + await this.initializeStoredProcedure(sprocID, collectionId); } let docTraceId = uuid.v4(); for (const doc of documents) { @@ -279,29 +291,42 @@ export class CosmosClient } } - public async upsert(document: any, partitionKey: string, currentSn: number): Promise { - await this.executeSproc(UPSERT_SPROC_ID, partitionKey, [document], [document, currentSn]); + public async upsert(document: any, key: string, currentSn: number): Promise { + const { collectionId, partitionKey } = getCollectionInfo(key); + + await this.executeSproc( + UPSERT_SPROC_ID, + partitionKey, + [document], + [document, currentSn], + collectionId + ); } - public async bulkInsert( - documents: any[], - partitionKey: string, - validateSn: boolean - ): Promise { + public async bulkInsert(documents: any[], key: string, validateSn: boolean): Promise { + const { collectionId, partitionKey } = getCollectionInfo(key); + if (documents && documents.length >= 1) { - await this.executeSproc(BULK_INSERT_SPROC_ID, partitionKey, documents, [ + await this.executeSproc( + BULK_INSERT_SPROC_ID, + partitionKey, documents, - validateSn, - ]); + [documents, validateSn], + collectionId + ); } } - public async query(spanContext: SpanContext, query: ICosmosQuery): Promise { + public async query( + spanContext: SpanContext, + query: ICosmosQuery, + collectionId?: string + ): Promise { const span = this.tracer.startSpan(this.spanOperationName, { childOf: spanContext }); this.spanLogAndSetTags(span, this.query.name, undefined, query.query); let requestCharge = 0; try { - const container = await this.container(); + const container = await this.container(collectionId); const iterator = container.items.query(query, { populateQueryMetrics: true, }); diff --git a/packages/azure/src/utils/QueueClient.ts b/packages/azure/src/utils/QueueClient.ts index b550ad84..b24480eb 100644 --- a/packages/azure/src/utils/QueueClient.ts +++ b/packages/azure/src/utils/QueueClient.ts @@ -49,6 +49,12 @@ export enum QueueOpenTracingTagKeys { QueueName = "queue.name", } +export interface IDeadLetterQueueOptions extends IQueueCreateMessageOptions { + readonly maxDequeueCount: number; + readonly retryCount?: number; + readonly retryInterval?: number; +} + export interface IQueueCreateMessageOptions extends IQueueRequestOptions { /** * (FROM AZURE DOCS) @@ -80,6 +86,12 @@ export interface IQueueReadOptions extends IQueueRequestOptions { * The visibility timeout of a message can be set to a value later than the expiry time. */ visibilityTimeout?: number; + readonly deadLetterQueue?: IDeadLetterQueueOptions; +} + +export interface IQueueMessage { + headers: Record; + payload: unknown; } export interface IQueueMessage { @@ -337,13 +349,13 @@ export class QueueClient implements IRequireInitialization { ); resolve( results.reduce((messages, result) => { - const mesageObj = this.config.preprocessor.process( + const messageObj = this.config.preprocessor.process( result.messageText ); if ( - !mesageObj.headers || - !mesageObj.headers[EventSourcedMetadata.EventType] + !messageObj.headers || + !messageObj.headers[EventSourcedMetadata.EventType] ) { span.log({ messageId: result.messageId }); failSpan( @@ -360,17 +372,18 @@ export class QueueClient implements IRequireInitialization { return messages; } - mesageObj.headers[QueueMetadata.DequeueCount] = ( + messageObj.headers[QueueMetadata.DequeueCount] = ( result.dequeueCount || 1 ).toString(); - mesageObj.headers[QueueMetadata.QueueName] = result.queue; - mesageObj.headers[QueueMetadata.TimeToLive] = result.expirationTime; - mesageObj.headers[QueueMetadata.VisibilityTimeout] = + messageObj.headers[QueueMetadata.QueueName] = result.queue; + messageObj.headers[QueueMetadata.TimeToLive] = + result.expirationTime; + messageObj.headers[QueueMetadata.VisibilityTimeout] = result.timeNextVisible; - mesageObj.headers[QueueMetadata.MessageId] = result.messageId; - mesageObj.headers[QueueMetadata.PopReceipt] = result.popReceipt; + messageObj.headers[QueueMetadata.MessageId] = result.messageId; + messageObj.headers[QueueMetadata.PopReceipt] = result.popReceipt; - messages.push(mesageObj); + messages.push(messageObj); return messages; }, []) diff --git a/packages/azure/src/utils/helpers.ts b/packages/azure/src/utils/helpers.ts new file mode 100644 index 00000000..a64b2f65 --- /dev/null +++ b/packages/azure/src/utils/helpers.ts @@ -0,0 +1,36 @@ +/* +Copyright (c) Walmart Inc. + +This source code is licensed under the Apache 2.0 license found in the +LICENSE file in the root directory of this source tree. +*/ + +/** + * Returns a collectionId and partitionKey from a provided state key. If the input is not in the expected format, + * undefined is returned. + * + * Only the following inputs are acceptable: + * - "partitionKey" + * - "@collection/partitionKey" + * + * @param inputKey A state key in the format @collectionId/partitionKey + */ +export function getCollectionInfo(key: string): { collectionId?: string; partitionKey: string } { + const collectionInfo: string[] = key.split("/"); + + let collectionId: string; + let partitionKey: string; + + if (collectionInfo.length === 1) { + partitionKey = collectionInfo[0]; + return { collectionId, partitionKey }; + } + + if (collectionInfo.length !== 2 || !collectionInfo[0].startsWith("@")) { + return { collectionId, partitionKey }; + } else { + collectionId = collectionInfo[0].replace("@", ""); + partitionKey = collectionInfo[1]; + return { collectionId, partitionKey }; + } +} diff --git a/packages/core/package.json b/packages/core/package.json index 6986d866..6d59e003 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -1,6 +1,6 @@ { "name": "@walmartlabs/cookie-cutter-core", - "version": "1.2.2", + "version": "1.3.0", "license": "Apache-2.0", "main": "dist/index.js", "types": "dist/index.d.ts", @@ -13,11 +13,11 @@ "url": "https://github.com/walmartlabs/cookie-cutter/issues" }, "dependencies": { - "lodash": "4.17.15", + "lodash": "4.17.20", "lru-cache": "5.1.1", "ms": "2.1.2", "opentracing": "0.14.4", - "wtfnode": "0.8.1" + "wtfnode": "0.8.3" }, "devDependencies": { "@types/lru-cache": "5.1.0", diff --git a/packages/core/src/__test__/config.test.ts b/packages/core/src/__test__/config.test.ts index d8051fb9..ddb8f5ef 100644 --- a/packages/core/src/__test__/config.test.ts +++ b/packages/core/src/__test__/config.test.ts @@ -230,6 +230,11 @@ describe("Primitive Values", () => { expect(actual.mode).toBe(Mode.Advanced); }); + it("allows overwriting default values with ", () => { + const actual = config.parse(Config, { num: null }, { num: 5 }); + expect(actual.num).toBeNull(); + }); + it("converts string -> number", () => { const actual = config.parse( Config, diff --git a/packages/core/src/__test__/utils/BoundedPriorityQueue.test.ts b/packages/core/src/__test__/utils/BoundedPriorityQueue.test.ts index 7436304b..3ae0a0bd 100644 --- a/packages/core/src/__test__/utils/BoundedPriorityQueue.test.ts +++ b/packages/core/src/__test__/utils/BoundedPriorityQueue.test.ts @@ -144,4 +144,24 @@ describe("BoundedPriorityQueue", () => { await enqueuePromise; await dequeuePromise; }); + + it("keeps priority through subsequent attempts to enqueue", async () => { + const queue = new BoundedPriorityQueue(1); + await queue.enqueue(1, 0); + await queue.enqueue(2, 1); + // tslint:disable-next-line:no-floating-promises + queue.enqueue(3, 1); + // tslint:disable-next-line:no-floating-promises + queue.enqueue(4, 1); + + const buffer = []; + for await (const item of queue.iterate()) { + buffer.push(item); + if (buffer.length === 4) { + queue.close(); + } + } + + expect(buffer).toMatchObject([2, 3, 4, 1]); + }); }); diff --git a/packages/core/src/config.ts b/packages/core/src/config.ts index 886a355f..fd43aaf5 100644 --- a/packages/core/src/config.ts +++ b/packages/core/src/config.ts @@ -66,6 +66,13 @@ export function parse(TRoot: IClassType, actual: any, base?: Partial): } } + if (isSection(actual)) { + throw new Error( + "The value of `actual` has no enumerable properties. Make sure the object being " + + "passed is not the output of `config.parse()` (i.e. does not have the '@section' decorator)." + ); + } + const instance = new TRoot(); if (verifyIsSection(instance)) { const config: T & ISection = new TRoot() as any; @@ -303,8 +310,12 @@ interface ISection { readonly __extensible?: boolean; } +function isSection(obj: any): obj is ISection { + return obj && obj.__assignedProperties; +} + function verifyIsSection(obj: any): obj is ISection { - if (obj && obj.__assignedProperties) { + if (isSection(obj)) { return true; } diff --git a/packages/core/src/internal/processor/ConcurrentMessageProcessor.ts b/packages/core/src/internal/processor/ConcurrentMessageProcessor.ts index 80e3f02c..be31ddc6 100644 --- a/packages/core/src/internal/processor/ConcurrentMessageProcessor.ts +++ b/packages/core/src/internal/processor/ConcurrentMessageProcessor.ts @@ -59,9 +59,10 @@ export class ConcurrentMessageProcessor extends BaseMessageProcessor implements } protected reportStatistics() { + this.metrics.gauge(MessageProcessingMetrics.InputQueue, this.inputQueue.length); this.metrics.gauge( - MessageProcessingMetrics.InputQueue, - this.inputQueue.length + super.currentlyInflight.length + MessageProcessingMetrics.ConcurrentHandlers, + super.currentlyInflight.length ); this.metrics.gauge(MessageProcessingMetrics.OutputQueue, this.outputQueue.length); } @@ -252,8 +253,6 @@ export class ConcurrentMessageProcessor extends BaseMessageProcessor implements if (sequence % this.config.yieldForIOMessageCount === 0) { await waitForPendingIO(); } - } catch (e) { - throw new Error("failed to process message"); } finally { if (dispatchError) { if (handlingInputSpan) { diff --git a/packages/core/src/internal/processor/RpcMessageProcessor.ts b/packages/core/src/internal/processor/RpcMessageProcessor.ts index ec020611..9e942c39 100644 --- a/packages/core/src/internal/processor/RpcMessageProcessor.ts +++ b/packages/core/src/internal/processor/RpcMessageProcessor.ts @@ -10,7 +10,6 @@ import { IMessageEnricher, IMessageMetricAnnotator, IServiceRegistry, - MessageProcessingMetrics, MessageRef, } from "../../model"; import { IRetrier, sleep } from "../../utils"; @@ -30,14 +29,6 @@ export class RpcMessageProcessor extends ConcurrentMessageProcessor { return RpcMessageProcessor.name; } - protected reportStatistics() { - super.reportStatistics(); - this.metrics.gauge( - MessageProcessingMetrics.ConcurrentHandlers, - super.currentlyInflight.length - ); - } - protected async processingLoop( enricher: IMessageEnricher, msgMetricsAnnotator: IMessageMetricAnnotator, diff --git a/packages/core/src/utils/BoundedPriorityQueue.ts b/packages/core/src/utils/BoundedPriorityQueue.ts index ab379be5..351232bb 100644 --- a/packages/core/src/utils/BoundedPriorityQueue.ts +++ b/packages/core/src/utils/BoundedPriorityQueue.ts @@ -64,7 +64,7 @@ export class BoundedPriorityQueue { if (isNullOrUndefined(whenNotFull)) { this.whenNotFullList.set(priority, new Future()); } - return this.enqueue(item); + return this.enqueue(item, priority); } public async dequeue(): Promise { diff --git a/packages/gcp/package.json b/packages/gcp/package.json index de51b4b0..face4868 100644 --- a/packages/gcp/package.json +++ b/packages/gcp/package.json @@ -1,6 +1,6 @@ { "name": "@walmartlabs/cookie-cutter-gcp", - "version": "1.2.0", + "version": "1.3.0", "license": "Apache-2.0", "main": "dist/index.js", "types": "dist/index.d.ts", @@ -13,14 +13,15 @@ "url": "https://github.com/walmartlabs/cookie-cutter/issues" }, "dependencies": { - "@google-cloud/storage": "4.4.0", - "@google-cloud/bigquery": "4.7.0" + "@google-cloud/bigquery": "4.7.0", + "@google-cloud/pubsub": "2.0.0", + "@google-cloud/storage": "4.4.0" }, "peerDependencies": { - "@walmartlabs/cookie-cutter-core": "^1.2.0" + "@walmartlabs/cookie-cutter-core": "^1.3.0" }, "devDependencies": { - "@walmartlabs/cookie-cutter-core": "^1.2.0" + "@walmartlabs/cookie-cutter-core": "^1.3.0" }, "scripts": { "build": "tsc", diff --git a/packages/gcp/src/PubSubSink.ts b/packages/gcp/src/PubSubSink.ts new file mode 100644 index 00000000..4b10b1b8 --- /dev/null +++ b/packages/gcp/src/PubSubSink.ts @@ -0,0 +1,183 @@ +/* +Copyright (c) Walmart Inc. + +This source code is licensed under the Apache 2.0 license found in the +LICENSE file in the root directory of this source tree. +*/ + +import { + DefaultComponentContext, + IComponentContext, + IDisposable, + ILogger, + IOutputSink, + IOutputSinkGuarantees, + IPublishedMessage, + IRequireInitialization, + OutputSinkConsistencyLevel, + IMetrics, + OpenTracingTagKeys, + failSpan, +} from "@walmartlabs/cookie-cutter-core"; +import { Span, SpanContext, Tags, Tracer } from "opentracing"; +import { PubSub, Attributes } from "@google-cloud/pubsub"; +import { IGcpAuthConfiguration, IPubSubPublisherConfiguration } from "."; + +interface IPayloadWithAttributes { + payload: Buffer; + attributes: Attributes; + spanContext: SpanContext; +} + +enum PubSubMetricResults { + Success = "success", + Error = "error", +} + +enum PubSubMetrics { + MsgPublished = "cookie_cutter.pubsub_sink.msg_published", +} + +export enum PubSubMetadata { + Topic = "topic", +} + +enum PubSubOpenTracingTagKeys { + TopicName = "pubSub.topic", +} + +export const AttributeNames = { + eventType: "eventType", + timestamp: "dt", + contentType: "mimeType", +}; + +/* + * Output sink to produce to Google's PubSub topics. + */ +export class PubSubSink + implements IOutputSink, IRequireInitialization, IDisposable { + private readonly producer: PubSub; + private logger: ILogger; + private tracer: Tracer; + private metrics: IMetrics; + private spanOperationName: string = "Write to Google PubSub"; + + constructor(private readonly config: IGcpAuthConfiguration & IPubSubPublisherConfiguration) { + this.logger = DefaultComponentContext.logger; + this.tracer = DefaultComponentContext.tracer; + this.producer = new PubSub({ + projectId: this.config.projectId, + credentials: { + client_email: this.config.clientEmail, + private_key: this.config.privateKey, + }, + }); + } + + public async initialize(ctx: IComponentContext): Promise { + this.logger = ctx.logger; + this.tracer = ctx.tracer; + this.metrics = ctx.metrics; + } + + public async sink(output: IterableIterator): Promise { + const messagesByTopic: Map = new Map(); + for (const msg of output) { + const topic = msg.metadata[PubSubMetadata.Topic] || this.config.defaultTopic; + if (!messagesByTopic.has(topic)) { + messagesByTopic.set(topic, []); + } + + const formattedMsg = this.formatMessage(msg); + messagesByTopic.get(topic).push(formattedMsg); + } + for (const [topic, messages] of messagesByTopic) { + const batchPublisher = this.producer.topic(topic, { + batching: { + maxBytes: this.config.maxPayloadSize, + maxMessages: this.config.maximumBatchSize, + maxMilliseconds: this.config.maximumBatchWaitTime, + }, + }); + for (const message of messages) { + const span = this.tracer.startSpan(this.spanOperationName, { + childOf: message.spanContext, + }); + this.spanLogAndSetTags(span, this.sink.name, topic); + try { + const messageId = await batchPublisher.publish( + message.payload, + message.attributes + ); + span.log({ messageId }); + this.emitMetrics( + topic, + message.attributes[AttributeNames.eventType], + PubSubMetricResults.Success + ); + this.logger.debug("Message published to PubSub", { topic, messageId }); + } catch (e) { + failSpan(span, e); + messages.forEach((message) => + this.emitMetrics( + topic, + message.attributes[AttributeNames.eventType], + PubSubMetricResults.Error + ) + ); + throw e; + } finally { + span.finish(); + } + } + } + } + + public async dispose(): Promise { + if (this.producer) { + await this.producer.close(); + } + } + + public get guarantees(): IOutputSinkGuarantees { + return { + consistency: OutputSinkConsistencyLevel.None, + idempotent: false, + maxBatchSize: this.config.maximumBatchSize, + }; + } + + private spanLogAndSetTags(span: Span, funcName: string, topic: string): void { + span.log({ topic }); + span.setTag(Tags.SPAN_KIND, Tags.SPAN_KIND_RPC_CLIENT); + span.setTag(Tags.COMPONENT, "cookie-cutter-pubSub"); + span.setTag(OpenTracingTagKeys.FunctionName, funcName); + span.setTag(PubSubOpenTracingTagKeys.TopicName, topic); + } + + private emitMetrics(topic: string, eventType: string, result: PubSubMetricResults) { + this.metrics.increment(PubSubMetrics.MsgPublished, { + topic, + event_type: eventType, + result, + }); + } + + private formatMessage(msg: IPublishedMessage): IPayloadWithAttributes { + const timestamp = Date.now().toString(); + const payload: Buffer = Buffer.from(this.config.encoder.encode(msg.message)); + + const attributes: Attributes = { + [AttributeNames.timestamp]: timestamp, + [AttributeNames.eventType]: msg.message.type, + [AttributeNames.contentType]: this.config.encoder.mimeType, + }; + + return { + payload, + attributes, + spanContext: msg.spanContext, + }; + } +} diff --git a/packages/gcp/src/__test__/PubSubSink.test.ts b/packages/gcp/src/__test__/PubSubSink.test.ts new file mode 100644 index 00000000..3b621702 --- /dev/null +++ b/packages/gcp/src/__test__/PubSubSink.test.ts @@ -0,0 +1,163 @@ +/* +Copyright (c) Walmart Inc. + +This source code is licensed under the Apache 2.0 license found in the +LICENSE file in the root directory of this source tree. +*/ + +import { PubSub } from "@google-cloud/pubsub"; +import { + IMessage, + MessageRef, + JsonMessageEncoder, + IPublishedMessage, + StaticInputSourceType, + ErrorHandlingMode, + CancelablePromise, + IDispatchContext, + Application, + ConsoleLogger, + StaticInputSource, + IOutputSink, +} from "@walmartlabs/cookie-cutter-core"; +import { IPubSubPublisherConfiguration, IGcpAuthConfiguration, pubSubSink } from ".."; +import { PubSubMetadata, AttributeNames } from "../PubSubSink"; + +jest.mock("@google-cloud/pubsub", () => { + return { + PubSub: jest.fn(), + }; +}); + +class TestEvent { + constructor(public value: string, public topic?: string) {} +} + +function createTestApp( + inputs: StaticInputSourceType, + sink: IOutputSink, + retryMode: ErrorHandlingMode +): CancelablePromise { + const handler = { + onTestEvent: (msg: TestEvent, ctx: IDispatchContext) => { + const metadata = {}; + if (msg.topic) { + metadata[PubSubMetadata.Topic] = msg.topic; + } + ctx.publish(TestEvent, new TestEvent(msg.value), metadata); + }, + }; + + return Application.create() + .logger(new ConsoleLogger()) + .input() + .add(new StaticInputSource(inputs)) + .done() + .output() + .published(sink) + .done() + .dispatch(handler) + .run(retryMode); +} + +describe("PubSubSink Tests", () => { + const gcsAuthConfig: IGcpAuthConfiguration = { + projectId: "projectId", + clientEmail: "clinetEmail", + privateKey: "key", + }; + const pubSubPublisherConfigurationWithDefaultTopic: IPubSubPublisherConfiguration = { + defaultTopic: "defaultTopic", + encoder: new JsonMessageEncoder(), + }; + const err = new Error("Test Error"); + const messagesWithoutTopic: IMessage[] = [ + { + type: TestEvent.name, + payload: new TestEvent("A"), + }, + { + type: TestEvent.name, + payload: new TestEvent("B"), + }, + ]; + const mockPubSub: jest.Mock = PubSub as any; + const mockPublishFn = jest.fn(); + const mockTopic = jest.fn(); + let sink; + + beforeEach(() => { + const mockFns = { + topic: mockTopic, + publish: mockPublishFn, + close: jest.fn(), + }; + mockPublishFn.mockResolvedValue("messageId"); + mockTopic.mockImplementation(() => mockFns); + mockPubSub.mockImplementation(() => mockFns); + sink = pubSubSink({ + ...gcsAuthConfig, + ...pubSubPublisherConfigurationWithDefaultTopic, + }); + }); + + it("writes to default topic in pubsub", async () => { + const testApp = createTestApp(messagesWithoutTopic, sink, ErrorHandlingMode.LogAndContinue); + await testApp; + expect(mockPubSub).toBeCalledTimes(1); + expect(mockTopic).toBeCalledTimes(1); + expect(mockTopic.mock.calls[0]).toContain( + pubSubPublisherConfigurationWithDefaultTopic.defaultTopic + ); + expect(mockPublishFn).toBeCalledTimes(messagesWithoutTopic.length); + messagesWithoutTopic.forEach((message, idx) => { + expect(mockPublishFn.mock.calls[idx][1][AttributeNames.eventType]).toBe(message.type); + expect(mockPublishFn.mock.calls[idx][1][AttributeNames.contentType]).toBe( + pubSubPublisherConfigurationWithDefaultTopic.encoder.mimeType + ); + }); + }); + + it("writes to topic specified in metadata", async () => { + const messagesWithTopic: IMessage[] = [ + { + type: TestEvent.name, + payload: new TestEvent("A", "TopicA"), + }, + { + type: TestEvent.name, + payload: new TestEvent("B", "TopicB"), + }, + ]; + const testApp = createTestApp(messagesWithTopic, sink, ErrorHandlingMode.LogAndContinue); + await testApp; + expect(mockPubSub).toBeCalledTimes(1); + expect(mockTopic).toBeCalledTimes(messagesWithTopic.length); + messagesWithTopic.forEach((message, idx) => { + expect(mockTopic.mock.calls[idx]).toContain(message.payload.topic); + }); + expect(mockPublishFn).toBeCalledTimes(messagesWithTopic.length); + messagesWithTopic.forEach((message, idx) => { + expect(mockPublishFn.mock.calls[idx][1][AttributeNames.eventType]).toBe(message.type); + expect(mockPublishFn.mock.calls[idx][1][AttributeNames.contentType]).toBe( + pubSubPublisherConfigurationWithDefaultTopic.encoder.mimeType + ); + }); + }); + + it("rejects on error from PubSub topic", async () => { + const testApp = createTestApp(messagesWithoutTopic, sink, ErrorHandlingMode.LogAndFail); + mockTopic.mockImplementation(() => { + throw err; + }); + await expect(testApp).rejects.toThrowError(); + }); + + it("rejects on error from PubSub topic", async () => { + const testApp = createTestApp(messagesWithoutTopic, sink, ErrorHandlingMode.LogAndFail); + mockPublishFn.mockImplementation(() => { + throw err; + }); + await expect(testApp).rejects.toThrowError(); + }); +}); diff --git a/packages/gcp/src/config.ts b/packages/gcp/src/config.ts index 43959ea7..c995d5db 100644 --- a/packages/gcp/src/config.ts +++ b/packages/gcp/src/config.ts @@ -5,8 +5,13 @@ This source code is licensed under the Apache 2.0 license found in the LICENSE file in the root directory of this source tree. */ -import { config } from "@walmartlabs/cookie-cutter-core"; -import { IBigQueryConfiguration, IGCSConfiguration } from "."; +import { config, IMessageEncoder } from "@walmartlabs/cookie-cutter-core"; +import { + IBigQueryConfiguration, + IGCSConfiguration, + IGcpAuthConfiguration, + IPubSubPublisherConfiguration, +} from "."; @config.section export class GCSConfiguration implements IGCSConfiguration { @@ -77,3 +82,74 @@ export class BigQueryConfiguration implements IBigQueryConfiguration { return config.noop(); } } + +@config.section +export class GcpAuthConfiguration implements IGcpAuthConfiguration { + @config.field(config.converters.string) + public set projectId(_: string) { + config.noop(); + } + public get projectId(): string { + return config.noop(); + } + + @config.field(config.converters.string) + public set clientEmail(_: string) { + config.noop(); + } + public get clientEmail(): string { + return config.noop(); + } + + @config.field(config.converters.string) + public set privateKey(_: string) { + config.noop(); + } + public get privateKey(): string { + return config.noop(); + } +} + +@config.section +export class PubSubPublisherConfiguration extends GcpAuthConfiguration + implements IPubSubPublisherConfiguration { + @config.field(config.converters.none) + public set encoder(_: IMessageEncoder) { + config.noop(); + } + public get encoder(): IMessageEncoder { + return config.noop(); + } + + @config.field(config.converters.string) + public set defaultTopic(_: string) { + config.noop(); + } + public get defaultTopic(): string { + return config.noop(); + } + + @config.field(config.converters.number) + public set maximumBatchSize(_: number) { + config.noop(); + } + public get maximumBatchSize(): number { + return config.noop(); + } + + @config.field(config.converters.timespan) + public set maximumBatchWaitTime(_: number) { + config.noop(); + } + public get maximumBatchWaitTime(): number { + return config.noop(); + } + + @config.field(config.converters.bytes) + public set maxPayloadSize(_: number) { + config.noop(); + } + public get maxPayloadSize(): number { + return config.noop(); + } +} diff --git a/packages/gcp/src/index.ts b/packages/gcp/src/index.ts index a0b2beea..2b208acc 100644 --- a/packages/gcp/src/index.ts +++ b/packages/gcp/src/index.ts @@ -11,14 +11,16 @@ import { IPublishedMessage, IRequireInitialization, IStoredMessage, + IMessageEncoder, } from "@walmartlabs/cookie-cutter-core"; import { SpanContext } from "opentracing"; import { BigQueryClient } from "./BigQueryClient"; import { BigQuerySink } from "./BigQuerySink"; export { BigQueryMetadata } from "./BigQuerySink"; -import { BigQueryConfiguration, GCSConfiguration } from "./config"; +import { BigQueryConfiguration, GCSConfiguration, PubSubPublisherConfiguration } from "./config"; import { GcsClient } from "./GcsClient"; import { GcsSink } from "./GcsSink"; +import { PubSubSink } from "./PubSubSink"; export interface IGCSConfiguration { readonly projectId: string; @@ -34,6 +36,20 @@ export interface IBigQueryConfiguration { readonly privateKey: string; } +export interface IGcpAuthConfiguration { + readonly projectId: string; + readonly clientEmail: string; + readonly privateKey: string; +} + +export interface IPubSubPublisherConfiguration { + readonly encoder: IMessageEncoder; + readonly defaultTopic?: string; + readonly maximumBatchSize?: number; + readonly maximumBatchWaitTime?: number; + readonly maxPayloadSize?: number; +} + export interface IGcsClient { putObject(spanContext: SpanContext, body: Buffer, key: string): Promise; } @@ -76,3 +92,14 @@ export function bigQuerySink( }; return new BigQuerySink(bigQueryClient(config), maxBatchSize); } + +export function pubSubSink( + configuration: IGcpAuthConfiguration & IPubSubPublisherConfiguration +): IOutputSink { + configuration = config.parse(PubSubPublisherConfiguration, configuration, { + maximumBatchSize: 1000, + maximumBatchWaitTime: 100, + maxPayloadSize: 5242880, + }); + return new PubSubSink(configuration); +} diff --git a/packages/grpc/package.json b/packages/grpc/package.json index e86e16e8..7f0174cc 100644 --- a/packages/grpc/package.json +++ b/packages/grpc/package.json @@ -1,6 +1,6 @@ { "name": "@walmartlabs/cookie-cutter-grpc", - "version": "1.2.0", + "version": "1.3.0", "license": "Apache-2.0", "main": "dist/index.js", "types": "dist/index.d.ts", @@ -14,14 +14,14 @@ }, "dependencies": { "change-case": "4.1.1", - "grpc": "1.24.2", + "grpc": "1.24.3", "opentracing": "0.14.4" }, "peerDependencies": { - "@walmartlabs/cookie-cutter-core": "^1.2.0" + "@walmartlabs/cookie-cutter-core": "^1.3.0" }, "devDependencies": { - "@walmartlabs/cookie-cutter-core": "^1.2.0", + "@walmartlabs/cookie-cutter-core": "^1.3.0", "protobufjs": "6.9.0" }, "scripts": { diff --git a/packages/instana/package.json b/packages/instana/package.json index 65628247..dd80a475 100644 --- a/packages/instana/package.json +++ b/packages/instana/package.json @@ -1,6 +1,6 @@ { "name": "@walmartlabs/cookie-cutter-instana", - "version": "1.2.0", + "version": "1.3.0", "license": "Apache-2.0", "main": "dist/index.js", "types": "dist/index.d.ts", @@ -13,14 +13,14 @@ "url": "https://github.com/walmartlabs/cookie-cutter/issues" }, "dependencies": { - "@instana/collector": "1.97.0", + "@instana/collector": "1.106.2", "opentracing": "0.14.4" }, "peerDependencies": { - "@walmartlabs/cookie-cutter-core": "^1.2.0" + "@walmartlabs/cookie-cutter-core": "^1.3.0" }, "devDependencies": { - "@walmartlabs/cookie-cutter-core": "^1.2.0" + "@walmartlabs/cookie-cutter-core": "^1.3.0" }, "scripts": { "build": "tsc", diff --git a/packages/jaeger/package.json b/packages/jaeger/package.json new file mode 100644 index 00000000..436d74d5 --- /dev/null +++ b/packages/jaeger/package.json @@ -0,0 +1,33 @@ +{ + "name": "@walmartlabs/cookie-cutter-jaeger", + "version": "1.3.0-alpha.0", + "license": "Apache-2.0", + "main": "dist/index.js", + "types": "dist/index.d.ts", + "homepage": "https://walmartlabs.github.io/cookie-cutter", + "repository": { + "type": "git", + "url": "https://github.com/walmartlabs/cookie-cutter.git" + }, + "bugs": { + "url": "https://github.com/walmartlabs/cookie-cutter/issues" + }, + "dependencies": { + "jaeger-client": "^3.18.1", + "opentracing": "0.14.4", + "prom-client": "~11.3.0" + }, + "peerDependencies": { + "@walmartlabs/cookie-cutter-core": "^1.3.0" + }, + "devDependencies": { + "@walmartlabs/cookie-cutter-core": "^1.3.0", + "@types/jaeger-client": "3.15.4" + }, + "scripts": { + "build": "tsc", + "test": "jest --config=../../jest.unit.config.js --rootDir=.", + "lint": "tslint --project tsconfig.json", + "lint:fix": "yarn run lint --fix" + } +} diff --git a/packages/jaeger/src/__test__/jaeger.test.ts b/packages/jaeger/src/__test__/jaeger.test.ts new file mode 100644 index 00000000..86677bd2 --- /dev/null +++ b/packages/jaeger/src/__test__/jaeger.test.ts @@ -0,0 +1,13 @@ +/* +Copyright (c) Walmart Inc. + +This source code is licensed under the Apache 2.0 license found in the +LICENSE file in the root directory of this source tree. +*/ + +describe("Jaeger", () => { + it("prevents the CI system from failing the build", async () => { + // just an empty test + // TODO: add an actual test + }); +}); diff --git a/packages/jaeger/src/index.ts b/packages/jaeger/src/index.ts new file mode 100644 index 00000000..39469848 --- /dev/null +++ b/packages/jaeger/src/index.ts @@ -0,0 +1,114 @@ +/* +Copyright (c) Walmart Inc. + +This source code is licensed under the Apache 2.0 license found in the +LICENSE file in the root directory of this source tree. +*/ + +import { config, getRootProjectPackageInfo, ITracerBuilder } from "@walmartlabs/cookie-cutter-core"; +import { Tracer } from "opentracing"; + +import * as promClient from "prom-client"; +import { PrometheusMetricsFactory, initTracer, TracingConfig, TracingOptions } from "jaeger-client"; + +export interface IJaegerConfiguration { + /** + * Endpoint to collect jaeger traces + * + * @type {string} + * @memberof IJaegerConfiguration + */ + readonly collectorEndpoint: string; + + /** + * Namespace to be used for Prometheus metrics + * if not defined, this is derived from the package name in the root project's package.json. + * + * @type {string} + * @memberof IJaegerConfiguration + */ + readonly metricNamespace?: string; + + /** + * package is additional metadata to include for use by the jaeger agent. + * if not defined, this is derived from the package name in the root project's package.json. + * + * @type {{ name: string }} + * @memberof IJaegerConfiguration + */ + readonly package?: { name: string }; +} + +@config.section +class JaegerConfiguration implements IJaegerConfiguration { + @config.field(config.converters.string) + public set collectorEndpoint(_: string) { + config.noop(); + } + public get collectorEndpoint(): string { + return config.noop(); + } + + @config.field(config.converters.string) + public set metricNamespace(_: string) { + config.noop(); + } + public get metricNamespace(): string { + return config.noop(); + } + + @config.field(config.converters.none) + public set package(_: { name: string }) { + config.noop(); + } + public get package(): { name: string } { + return config.noop(); + } +} + +class JaegerBuilder implements ITracerBuilder { + public constructor(private configuration: Required) {} + + public create(): Tracer { + const config: TracingConfig = { + serviceName: this.configuration.package.name, + reporter: { + collectorEndpoint: this.configuration.collectorEndpoint, + }, + }; + const options: TracingOptions = { + metrics: new PrometheusMetricsFactory( + promClient, + this.configuration.metricNamespace || config.serviceName + ), + }; + return initTracer(config, options); + } +} + +export function jaegerTracer( + configuration: IJaegerConfiguration, + tracer: boolean = false +): ITracerBuilder | Tracer { + const packageInfo = getRootProjectPackageInfo(); + const parsedConfig = config.parse(JaegerConfiguration, configuration, { + package: { name: packageInfo.name }, + }); + if (tracer) { + const config: TracingConfig = { + serviceName: configuration.package.name, + reporter: { + collectorEndpoint: configuration.collectorEndpoint, + }, + }; + const options: TracingOptions = { + metrics: new PrometheusMetricsFactory( + promClient, + configuration.metricNamespace || config.serviceName + ), + }; + return initTracer(config, options); + } + + return new JaegerBuilder(parsedConfig); +} diff --git a/packages/jaeger/tsconfig.json b/packages/jaeger/tsconfig.json new file mode 100644 index 00000000..d70b99d5 --- /dev/null +++ b/packages/jaeger/tsconfig.json @@ -0,0 +1,9 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "outDir": "./dist", + "rootDir": "./src" + }, + "exclude": ["node_modules", "dist"], + "include": ["src/**/*.ts"] +} diff --git a/packages/kafka/package.json b/packages/kafka/package.json index 84c5f6b7..b4d4056c 100644 --- a/packages/kafka/package.json +++ b/packages/kafka/package.json @@ -1,6 +1,6 @@ { "name": "@walmartlabs/cookie-cutter-kafka", - "version": "1.2.0", + "version": "1.3.0", "license": "Apache-2.0", "main": "dist/index.js", "types": "dist/index.d.ts", @@ -20,10 +20,10 @@ "long": "4.0.0", "murmurhash": "1.0.0", "opentracing": "0.14.4", - "uuid": "8.0.0" + "uuid": "8.3.0" }, "devDependencies": { - "@walmartlabs/cookie-cutter-core": "^1.2.0", + "@walmartlabs/cookie-cutter-core": "^1.3.0", "ip": "1.1.5" }, "scripts": { diff --git a/packages/kafka/src/KafkaConsumer.ts b/packages/kafka/src/KafkaConsumer.ts index d9128be7..ecb0e9af 100644 --- a/packages/kafka/src/KafkaConsumer.ts +++ b/packages/kafka/src/KafkaConsumer.ts @@ -79,6 +79,7 @@ export class KafkaConsumer implements IRequireInitialization, IDisposable { private offsetCommitIntervalMs: number; private timer: NodeJS.Timer; private groupEpoch: number = 0; + private brokerMetadataErrors: number = 0; constructor(config: KafkaConsumerConfig) { this.config = config; @@ -278,6 +279,7 @@ export class KafkaConsumer implements IRequireInitialization, IDisposable { // tslint:disable-next-line:no-floating-promises this.commitOffsetsIfNecessary(); }, 0); + this.timer.unref(); } await this.consumer.run({ @@ -407,8 +409,30 @@ export class KafkaConsumer implements IRequireInitialization, IDisposable { this.metrics.gauge(KafkaMetrics.Lag, lag.toNumber(), tags); } } + + this.brokerMetadataErrors = 0; } catch (e) { - this.logger.error("Unable to retrieve watermarks", e); + this.logger.warn("Unable to retrieve watermarks", e); + + // this is a workaround for https://github.com/walmartlabs/cookie-cutter/issues/185 + // until a fix for kafkajs is available / the root cause of the problem is confirmed + if ( + e && + JSON.stringify(e).includes( + "server is not the leader for that topic-partition" + ) + ) { + this.brokerMetadataErrors++; + } + + if (this.brokerMetadataErrors > 10) { + this.logger.error("detected stale broker metadata in kafkajs"); + this.brokerMetadataErrors = 0; + + // throwing an error here will cause a UnhandledPromiseException + // and terminate the application + throw new Error("stale broker metadata"); + } } } } finally { @@ -416,6 +440,7 @@ export class KafkaConsumer implements IRequireInitialization, IDisposable { // tslint:disable-next-line:no-floating-promises this.commitOffsetsIfNecessary(); }, this.offsetCommitIntervalMs); + this.timer.unref(); } } diff --git a/packages/kubernetes/package.json b/packages/kubernetes/package.json index b1eb8a77..167ee328 100644 --- a/packages/kubernetes/package.json +++ b/packages/kubernetes/package.json @@ -1,6 +1,6 @@ { "name": "@walmartlabs/cookie-cutter-kubernetes", - "version": "1.2.0", + "version": "1.3.0", "license": "Apache-2.0", "main": "dist/index.js", "types": "dist/index.d.ts", @@ -18,18 +18,18 @@ "express": "4.17.1", "express-async-handler": "1.1.4", "fast-json-patch": "3.0.0-1", - "lodash": "4.17.15", + "lodash": "4.17.20", "opentracing": "0.14.4", "request": "2.88.2", - "request-promise-native": "1.0.8" + "request-promise-native": "1.0.9" }, "peerDependencies": { - "@walmartlabs/cookie-cutter-core": "^1.2.0" + "@walmartlabs/cookie-cutter-core": "^1.3.0" }, "devDependencies": { "@types/express": "4.17.3", "@types/request-promise-native": "1.0.17", - "@walmartlabs/cookie-cutter-core": "^1.2.0" + "@walmartlabs/cookie-cutter-core": "^1.3.0" }, "scripts": { "build": "tsc", diff --git a/packages/kubernetes/src/KubernetesPollSource.ts b/packages/kubernetes/src/KubernetesPollSource.ts index bff75c66..f6d30663 100644 --- a/packages/kubernetes/src/KubernetesPollSource.ts +++ b/packages/kubernetes/src/KubernetesPollSource.ts @@ -83,7 +83,7 @@ export class KubernetesPollSource extends KubernetesBase } while (this.running) { - this.logger.info(`Starting poll watch`, { + this.logger.debug(`Starting poll watch`, { queryPath: this.queryPath, queryParams: this.queryParams, reconnectTimeout: this.reconnectTimeout, @@ -160,7 +160,7 @@ export class KubernetesPollSource extends KubernetesBase } } - this.logger.info(`Finished poll watch`, { + this.logger.debug(`Finished poll watch`, { queryPath: this.queryPath, queryParams: this.queryParams, reconnectTimeout: this.reconnectTimeout, diff --git a/packages/kubernetes/src/KubernetesWatchSource.ts b/packages/kubernetes/src/KubernetesWatchSource.ts index 1f1e527b..80a45262 100644 --- a/packages/kubernetes/src/KubernetesWatchSource.ts +++ b/packages/kubernetes/src/KubernetesWatchSource.ts @@ -91,7 +91,7 @@ export class KubernetesWatchSource extends KubernetesBase return; } - this.logger.info(`Starting watch`, { + this.logger.debug(`Starting watch`, { queryPath: this.queryPath, queryParams: this.queryParams, reconnectTimeout: this.reconnectTimeout, @@ -152,7 +152,7 @@ export class KubernetesWatchSource extends KubernetesBase watchPromise.then( (resp) => { - this.logger.info(resp, { + this.logger.debug(resp, { queryPath: this.queryPath, queryParams: this.queryParams, }); diff --git a/packages/lightstep/package.json b/packages/lightstep/package.json index f2a4bd14..ac38666d 100644 --- a/packages/lightstep/package.json +++ b/packages/lightstep/package.json @@ -1,6 +1,6 @@ { "name": "@walmartlabs/cookie-cutter-lightstep", - "version": "1.2.0", + "version": "1.3.0", "license": "Apache-2.0", "main": "dist/index.js", "types": "dist/index.d.ts", @@ -17,10 +17,10 @@ "opentracing": "0.14.4" }, "peerDependencies": { - "@walmartlabs/cookie-cutter-core": "^1.2.0" + "@walmartlabs/cookie-cutter-core": "^1.3.0" }, "devDependencies": { - "@walmartlabs/cookie-cutter-core": "^1.2.0" + "@walmartlabs/cookie-cutter-core": "^1.3.0" }, "scripts": { "build": "tsc", diff --git a/packages/mssql/package.json b/packages/mssql/package.json index 32bf00e2..af8902fd 100644 --- a/packages/mssql/package.json +++ b/packages/mssql/package.json @@ -1,6 +1,6 @@ { "name": "@walmartlabs/cookie-cutter-mssql", - "version": "1.2.0", + "version": "1.3.0", "license": "Apache-2.0", "main": "dist/index.js", "types": "dist/index.d.ts", @@ -13,14 +13,14 @@ "url": "https://github.com/walmartlabs/cookie-cutter/issues" }, "dependencies": { - "mssql": "4.3.7", + "mssql": "4.3.9", "opentracing": "0.14.4" }, "peerDependencies": { - "@walmartlabs/cookie-cutter-core": "^1.2.0" + "@walmartlabs/cookie-cutter-core": "^1.3.0" }, "devDependencies": { - "@walmartlabs/cookie-cutter-core": "^1.2.0", + "@walmartlabs/cookie-cutter-core": "^1.3.0", "@types/mssql": "4.3.1" }, "scripts": { diff --git a/packages/mssql/src/MssqlSink.ts b/packages/mssql/src/MssqlSink.ts index a2f71c37..a813dc71 100644 --- a/packages/mssql/src/MssqlSink.ts +++ b/packages/mssql/src/MssqlSink.ts @@ -243,7 +243,14 @@ export class MssqlSink database: this.config.database, result: MssqlMetricResults.Error, }); - await tx.rollback(); + try { + await tx.rollback(); + } catch { + // ignore this error, rolling back a transaction on error + // can fail due to various reasons and we want to ensure + // that the correct error is bubbled up and not a generic + // "failed to rollback transaction" error + } throw e; } finally { if (span && haveUnfinishedSpan) { diff --git a/packages/prometheus/package.json b/packages/prometheus/package.json index 1b5df440..42971e0c 100644 --- a/packages/prometheus/package.json +++ b/packages/prometheus/package.json @@ -1,6 +1,6 @@ { "name": "@walmartlabs/cookie-cutter-prometheus", - "version": "1.2.1", + "version": "1.3.0", "license": "Apache-2.0", "main": "dist/index.js", "types": "dist/index.d.ts", @@ -13,10 +13,11 @@ "url": "https://github.com/walmartlabs/cookie-cutter/issues" }, "peerDependencies": { - "@walmartlabs/cookie-cutter-core": "^1.2.0" + "@walmartlabs/cookie-cutter-core": "^1.3.0" }, "devDependencies": { - "@walmartlabs/cookie-cutter-core": "^1.2.0" + "@types/request-promise-native": "1.0.17", + "@walmartlabs/cookie-cutter-core": "^1.3.0" }, "scripts": { "build": "tsc", @@ -26,8 +27,7 @@ "lint:fix": "yarn run lint --fix" }, "dependencies": { - "@types/request-promise-native": "1.0.17", - "request-promise-native": "1.0.8", + "request-promise-native": "1.0.9", "ip": "1.1.5" } } diff --git a/packages/prometheus/src/__test__/prometheus.test.ts b/packages/prometheus/src/__test__/prometheus.test.ts index 3d47ad86..9361feca 100644 --- a/packages/prometheus/src/__test__/prometheus.test.ts +++ b/packages/prometheus/src/__test__/prometheus.test.ts @@ -234,11 +234,13 @@ describe("Prometheus", () => { expect(mockError).toHaveBeenNthCalledWith(4, str, err, data4); }); - it("does not create/observe a Histogram when given a negative observation value", async () => { + it("creates a Histogram when given a negative observation value and bucket", async () => { const key1 = "key1"; const key2 = "key2"; const port = nextPort(); - const prom = makeLifecycle(prometheus(prometheusConfiguration(port))); + const prom = makeLifecycle( + prometheus({ ...prometheusConfiguration(port), defaultHistogramBuckets: [-5, 15] }) + ); await prom.initialize({ ...DefaultComponentContext, logger: mockLogger }); prom.timing(key1, -10); prom.timing(key2, 20); @@ -246,19 +248,19 @@ describe("Prometheus", () => { prom.timing(key2, 0); const dataSplit = (await getMetrics(port)).split("\n"); await prom.dispose(); - expect(dataSplit[0]).toBe("# TYPE test_key2 histogram"); - expect(dataSplit[1].startsWith('test_key2_bucket{le="10"} 1')).toBe(true); - expect(dataSplit[2].startsWith('test_key2_bucket{le="20"} 2')).toBe(true); - expect(dataSplit[3].startsWith('test_key2_bucket{le="+Inf"} 2')).toBe(true); - expect(dataSplit[4].startsWith("test_key2_sum 20")).toBe(true); - expect(dataSplit[5].startsWith("test_key2_count 2")).toBe(true); - expect(mockError).toHaveBeenCalledTimes(2); - const str = "Prometheus Histogram Error"; - const err = new Error("Observing a negative value is not allowed for Histograms."); - const data1 = { key: key1, value: -10, tags: undefined }; - const data2 = { key: key2, value: -10, tags: undefined }; - expect(mockError).toHaveBeenNthCalledWith(1, str, err, data1); - expect(mockError).toHaveBeenNthCalledWith(2, str, err, data2); + expect(dataSplit[0]).toBe("# TYPE test_key1 histogram"); + expect(dataSplit[1].startsWith('test_key1_bucket{le="-5"} 1')).toBe(true); + expect(dataSplit[2].startsWith('test_key1_bucket{le="15"} 1')).toBe(true); + expect(dataSplit[3].startsWith('test_key1_bucket{le="+Inf"} 1')).toBe(true); + expect(dataSplit[4].startsWith("test_key1_sum -10")).toBe(true); + expect(dataSplit[5].startsWith("test_key1_count 1")).toBe(true); + expect(dataSplit[7]).toBe("# TYPE test_key2 histogram"); + expect(dataSplit[8].startsWith('test_key2_bucket{le="-5"} 1')).toBe(true); + expect(dataSplit[9].startsWith('test_key2_bucket{le="15"} 2')).toBe(true); + expect(dataSplit[10].startsWith('test_key2_bucket{le="+Inf"} 3')).toBe(true); + expect(dataSplit[11].startsWith("test_key2_sum 10")).toBe(true); + expect(dataSplit[12].startsWith("test_key2_count 3")).toBe(true); + expect(mockError).toHaveBeenCalledTimes(0); }); it("outputs 2 histograms with observations", async () => { diff --git a/packages/prometheus/src/index.ts b/packages/prometheus/src/index.ts index ec0b83c9..89fd272b 100644 --- a/packages/prometheus/src/index.ts +++ b/packages/prometheus/src/index.ts @@ -140,13 +140,8 @@ class PrometheusMetrics * @param {IMetricTags} tags The tag values to associate with this observation */ public timing(key: string, value: number, tags?: IMetricTags): void { - const str = "Prometheus Histogram Error"; - if (value < 0) { - const err = "Observing a negative value is not allowed for Histograms."; - this.logger.error(str, new Error(err), { key, value, tags }); - return; - } if (this.containsLeLabel(tags)) { + const str = "Prometheus Histogram Error"; const err = "The 'le' label is reserved for system use in histograms."; this.logger.error(str, new Error(err), { key, value, tags }); return; diff --git a/packages/proto/package.json b/packages/proto/package.json index aaf09fab..9eaf6dfa 100644 --- a/packages/proto/package.json +++ b/packages/proto/package.json @@ -1,6 +1,6 @@ { "name": "@walmartlabs/cookie-cutter-proto", - "version": "1.2.0", + "version": "1.3.0", "license": "Apache-2.0", "main": "dist/index.js", "types": "dist/index.d.ts", @@ -17,10 +17,10 @@ "protobufjs": "6.9.0" }, "peerDependencies": { - "@walmartlabs/cookie-cutter-core": "^1.2.0" + "@walmartlabs/cookie-cutter-core": "^1.3.0" }, "devDependencies": { - "@walmartlabs/cookie-cutter-core": "^1.2.0", + "@walmartlabs/cookie-cutter-core": "^1.3.0", "eval": "0.1.4" }, "scripts": { diff --git a/packages/proto/src/ProtoMessageEncoder.ts b/packages/proto/src/ProtoMessageEncoder.ts index 25024318..dcb39659 100644 --- a/packages/proto/src/ProtoMessageEncoder.ts +++ b/packages/proto/src/ProtoMessageEncoder.ts @@ -5,13 +5,29 @@ This source code is licensed under the Apache 2.0 license found in the LICENSE file in the root directory of this source tree. */ -import { IMessage, IMessageEncoder } from "@walmartlabs/cookie-cutter-core"; +import { + IMessage, + IMessageEncoder, + IEncodedMessageEmbedder, +} from "@walmartlabs/cookie-cutter-core"; import { IProtoMessageEncoderRegistry } from "."; +import { isString } from "util"; -export class ProtoMessageEncoder implements IMessageEncoder { +export class ProtoMessageEncoder implements IMessageEncoder, IEncodedMessageEmbedder { public readonly mimeType: string = "application/x-protobuf"; - constructor(private readonly lookup: IProtoMessageEncoderRegistry) {} + constructor( + private readonly lookup: IProtoMessageEncoderRegistry, + private readonly base64Encode: boolean = false + ) {} + + public toJsonEmbedding(encoded: Uint8Array): any { + return this.base64Encode ? Buffer.from(encoded).toString("base64") : encoded; + } + + public fromJsonEmbedding(embedding: any): Uint8Array { + return isString(embedding) ? Buffer.from(embedding, "base64") : embedding.data; + } public encode(msg: IMessage): Uint8Array { const encoder = this.lookup.toEncoder(msg.type); diff --git a/packages/proto/src/__test__/ProtoMessageEncoder.test.ts b/packages/proto/src/__test__/ProtoMessageEncoder.test.ts index 0d91ebe6..b98354a2 100644 --- a/packages/proto/src/__test__/ProtoMessageEncoder.test.ts +++ b/packages/proto/src/__test__/ProtoMessageEncoder.test.ts @@ -7,23 +7,26 @@ LICENSE file in the root directory of this source tree. import { pbjsStaticModuleRegistry, ProtoMessageEncoder } from ".."; import { loadTestProto } from "./helper"; +import { IMessage } from "@walmartlabs/cookie-cutter-core"; describe("ProtoMessageEncoder", () => { + const msg: IMessage = { + type: "cookiecutter.test.SampleMessage", + payload: { + id: 2, + text: "hello", + nested: [ + { + text: "world", + }, + ], + }, + }; + it("encodes an IMessage into a buffer", async () => { const root = await loadTestProto(); const encoder = new ProtoMessageEncoder(pbjsStaticModuleRegistry(root)); - const encodedMsg = encoder.encode({ - type: "cookiecutter.test.SampleMessage", - payload: { - id: 2, - text: "hello", - nest: [ - { - text: "world", - }, - ], - }, - }); + const encodedMsg = encoder.encode(msg); expect(encodedMsg.length).toBeGreaterThan(0); }); @@ -31,21 +34,49 @@ describe("ProtoMessageEncoder", () => { it("performs round-trip encoding", async () => { const root = await loadTestProto(); const encoder = new ProtoMessageEncoder(pbjsStaticModuleRegistry(root)); - const msg = { - type: "cookiecutter.test.SampleMessage", - payload: { - id: 2, - text: "hello", - nested: [ - { - text: "world", - }, - ], - }, - }; const encodedMsg = encoder.encode(msg); const decoded = encoder.decode(encodedMsg, msg.type); expect(decoded).toMatchObject(msg); }); + + it("returns Uint8Array from toJsonEmbedding when base64Encode is false", async () => { + const root = await loadTestProto(); + const encoder = new ProtoMessageEncoder(pbjsStaticModuleRegistry(root), false); + const encodedMsg = encoder.encode(msg); + const notBase64Encoded = encoder.toJsonEmbedding(encodedMsg); + + expect(notBase64Encoded).toMatchObject(encodedMsg); + }); + + it("performs round-trip base64 encoding", async () => { + const root = await loadTestProto(); + const encoder = new ProtoMessageEncoder(pbjsStaticModuleRegistry(root), true); + const encodedMsg = encoder.encode(msg); + const base64Encoded = encoder.toJsonEmbedding(encodedMsg); + const base64Decoded = encoder.fromJsonEmbedding(base64Encoded); + const decodedMsg = encoder.decode(base64Decoded, msg.type); + + expect(base64Decoded).toMatchObject(encodedMsg); + expect(decodedMsg).toMatchObject(msg); + }); + + it("preserves backwards compatibility for decoding before IEncodedMessageEmbedder was implemented", async () => { + const root = await loadTestProto(); + const encoder = new ProtoMessageEncoder(pbjsStaticModuleRegistry(root), false); + + // this is how it used to get serialized before `toJsonEmbedding` was available + const json = JSON.stringify(encoder.encode(msg)); + const obj = JSON.parse(json); + + // since IEncodedMessageEmbedder was added the code will always + // invoke `fromJsonEmbedding`, even if `toJsonEmbedding` was not + // invoked when the data was saved + const buffer = encoder.fromJsonEmbedding(obj); + + // the message should properly decode based on the buffer + // returned from `fromJsonEmbedding` + const decoded = encoder.decode(buffer, msg.type); + expect(decoded).toMatchObject(msg); + }); }); diff --git a/packages/redis/package.json b/packages/redis/package.json index 4bcd2c41..ebd26f00 100644 --- a/packages/redis/package.json +++ b/packages/redis/package.json @@ -1,6 +1,6 @@ { "name": "@walmartlabs/cookie-cutter-redis", - "version": "1.2.0", + "version": "1.3.0", "license": "Apache-2.0", "main": "dist/index.js", "types": "dist/index.d.ts", @@ -13,14 +13,15 @@ "url": "https://github.com/walmartlabs/cookie-cutter/issues" }, "dependencies": { - "redis": "3.0.2" + "redis": "3.0.2", + "shortid": "^2.2.15" }, "peerDependencies": { - "@walmartlabs/cookie-cutter-core": "^1.2.0" + "@walmartlabs/cookie-cutter-core": "^1.3.0" }, "devDependencies": { - "@walmartlabs/cookie-cutter-core": "^1.2.0", - "@types/redis": "2.8.20" + "@types/redis": "2.8.25", + "@walmartlabs/cookie-cutter-core": "^1.3.0" }, "scripts": { "build": "tsc", diff --git a/packages/redis/src/RedisClient.ts b/packages/redis/src/RedisClient.ts index 4d6d62c6..7ed09aba 100644 --- a/packages/redis/src/RedisClient.ts +++ b/packages/redis/src/RedisClient.ts @@ -19,38 +19,113 @@ import { OpenTracingTagKeys, } from "@walmartlabs/cookie-cutter-core"; import { Span, SpanContext, Tags, Tracer } from "opentracing"; -import { isString } from "util"; -import { IRedisOptions } from "."; -import { RedisProxy } from "./RedisProxy"; +import { isString, isNullOrUndefined, isNull, isUndefined } from "util"; +import { IRedisOptions, IRedisClient, IRedisMessage } from "."; +import { RedisProxy, RawReadGroupResult, RawPELResult, RawXClaimResult } from "./RedisProxy"; -enum RedisMetrics { +export enum RedisClientMetrics { Get = "cookie_cutter.redis_client.get", Set = "cookie_cutter.redis_client.set", + XAdd = "cookie_cutter.redis_client.xadd", + XRead = "cookie_cutter.redis_client.xread", + XReadGroup = "cookie_cutter.redis_client.xreadgroup", + XGroup = "cookie_cutter.redis_client.xgroup", + XAck = "cookie_cutter.redis_client.xack", + XPending = "cookie_cutter.redis_client.xpending", + XClaim = "cookie_cutter.redis_client.xclaim", +} + +enum MetricLabels { + Type = "type", } enum RedisMetricResults { Success = "success", Error = "error", + AlreadyExists = "already_exists", } -enum RedisOpenTracingTagKeys { +export enum RedisOpenTracingTagKeys { BucketName = "redis.bucket", } -export class RedisClient implements IRequireInitialization, IDisposable { - private client: RedisProxy; - private encoder: IMessageEncoder; - private typeMapper: IMessageTypeMapper; - private tracer: Tracer; - private metrics: IMetrics; - private spanOperationName: string = "Redis Client Call"; +export interface IPELResult { + messageId: string; + consumerId: string; + idleTime: number; + timesDelivered: number; +} + +function parseRawPELResult(results: RawPELResult): IPELResult[] { + return results.map(([messageId, consumerId, idleTime, timesDelivered]) => ({ + messageId, + consumerId, + idleTime, + timesDelivered, + })); +} + +export function parseRawReadGroupResult( + results: RawReadGroupResult +): { streamName: string; messageId: string; data: string; type: string }[] { + return results.reduce((acc, curr) => { + // streamName, streamValue + const [streamName, streamValues = []] = curr; + for (const streamValue of streamValues) { + // [messageId, keyValues] + const [messageId, keyValues = []] = streamValue; + + if (isNullOrUndefined(keyValues)) { + // tslint:disable:no-console + console.log( + "detected bad item in redis stream", + JSON.stringify(results), + isNull(keyValues), + isUndefined(keyValues) + ); + } + + if (isNullOrUndefined(keyValues) || keyValues?.length < 1) { + return acc; + } + + // [RedisMetadata.OutputSinkStreamKey, serializedProto, type, typeName] + const [, data, , type] = keyValues; + + acc.push({ streamName, messageId, data, type }); + } + return acc; + }, []); +} + +function extractXClaimValues( + results: RawXClaimResult +): { messageId: string; data: string; type: string }[] { + return results.reduce((acc, curr) => { + const [messageId, keyValues = []] = curr; + + const [, data, , type] = keyValues; + acc.push({ messageId, data, type }); + return acc; + }, []); +} + +export class RedisClient implements IRedisClient, IRequireInitialization, IDisposable { + private readonly client: RedisProxy; + private readonly encoder: IMessageEncoder; + private readonly typeMapper: IMessageTypeMapper; + private tracer: Tracer = DefaultComponentContext.tracer; + private metrics: IMetrics = DefaultComponentContext.metrics; constructor(private readonly config: IRedisOptions) { this.encoder = config.encoder; this.typeMapper = config.typeMapper; - this.tracer = DefaultComponentContext.tracer; - this.metrics = DefaultComponentContext.metrics; - this.client = new RedisProxy(this.config.host, this.config.port, this.config.db); + this.client = new RedisProxy( + this.config.host, + this.config.port, + this.config.db, + this.config.password + ); } public async dispose(): Promise { @@ -73,8 +148,14 @@ export class RedisClient implements IRequireInitialization, IDisposable { return typeName; } - private spanLogAndSetTags(span: Span, funcName: string, bucket: number, key: string): void { - span.log({ bucket, key }); + private spanLogAndSetTags( + span: Span, + funcName: string, + bucket: number, + keys: string | string[], + streamNames?: string | string[] + ): void { + span.log({ bucket, keys, streamNames }); span.setTag(Tags.SPAN_KIND, Tags.SPAN_KIND_RPC_CLIENT); span.setTag(Tags.COMPONENT, "cookie-cutter-redis"); span.setTag(Tags.DB_INSTANCE, bucket); @@ -89,7 +170,7 @@ export class RedisClient implements IRequireInitialization, IDisposable { key: string ): Promise { const db = this.config.db; - const span = this.tracer.startSpan(this.spanOperationName, { childOf: context }); + const span = this.tracer.startSpan("Redis Client putObject Call", { childOf: context }); this.spanLogAndSetTags(span, this.putObject.name, db, key); const typeName = this.getTypeName(type); const msg: IMessage = { @@ -97,17 +178,19 @@ export class RedisClient implements IRequireInitialization, IDisposable { payload: body, }; const encodedBody = this.encoder.encode(msg); + const buf = Buffer.from(encodedBody); + const storableValue = this.config.base64Encode ? buf.toString("base64") : buf; try { - await this.client.set(key, encodedBody); - this.metrics.increment(RedisMetrics.Set, { - type, + await this.client.set(key, storableValue); + this.metrics.increment(RedisClientMetrics.Set, { + [MetricLabels.Type]: typeName, db, result: RedisMetricResults.Success, }); } catch (e) { failSpan(span, e); - this.metrics.increment(RedisMetrics.Set, { - type, + this.metrics.increment(RedisClientMetrics.Set, { + [MetricLabels.Type]: typeName, db, result: RedisMetricResults.Error, error: e, @@ -124,26 +207,31 @@ export class RedisClient implements IRequireInitialization, IDisposable { key: string ): Promise { const db = this.config.db; - const span = this.tracer.startSpan(this.spanOperationName, { childOf: context }); + const span = this.tracer.startSpan("Redis Client getObject Call", { childOf: context }); this.spanLogAndSetTags(span, this.getObject.name, this.config.db, key); try { const typeName = this.getTypeName(type); const response = await this.client.get(key); + let data; + if (response) { - const msg = this.encoder.decode(response, typeName); + const buf = this.config.base64Encode + ? Buffer.from(response, "base64") + : Buffer.from(response); + const msg = this.encoder.decode(new Uint8Array(buf), typeName); data = msg.payload; } - this.metrics.increment(RedisMetrics.Get, { - type, + this.metrics.increment(RedisClientMetrics.Get, { + [MetricLabels.Type]: typeName, db, result: RedisMetricResults.Success, }); return data; } catch (e) { failSpan(span, e); - this.metrics.increment(RedisMetrics.Get, { + this.metrics.increment(RedisClientMetrics.Get, { db, result: RedisMetricResults.Error, error: e, @@ -153,4 +241,320 @@ export class RedisClient implements IRequireInitialization, IDisposable { span.finish(); } } + + public async xAddObject( + context: SpanContext, + type: string | IClassType, + streamName: string, + keys: { + payload: string; + typeName: string; + }, + body: T, + id: string = "*", + maxStreamLength?: number + ): Promise { + const db = this.config.db; + const span = this.tracer!.startSpan("Redis Client xAddObject Call", { childOf: context }); + this.spanLogAndSetTags(span, this.xAddObject.name, db, keys.payload, streamName); + const typeName = this.getTypeName(type); + try { + const encodedBody = this.encoder.encode({ + type: typeName, + payload: body, + }); + + const buf = Buffer.from(encodedBody); + const storableValue = this.config.base64Encode ? buf.toString("base64") : buf; + + const args: (string | Buffer)[] = [streamName]; + if (!isNullOrUndefined(maxStreamLength)) { + args.push("MAXLEN", "~", maxStreamLength.toString()); + } + + args.push(id, keys.payload, storableValue, keys.typeName, typeName); + + const insertedId = await this.client.xadd.call(this.client, args); + this.metrics!.increment(RedisClientMetrics.XAdd, { + [MetricLabels.Type]: typeName, + db, + streamName, + result: RedisMetricResults.Success, + }); + + return insertedId; + } catch (e) { + failSpan(span, e); + this.metrics!.increment(RedisClientMetrics.XAdd, { + [MetricLabels.Type]: typeName, + db, + streamName, + result: RedisMetricResults.Error, + error: e, + }); + throw e; + } finally { + span.finish(); + } + } + + public async xGroup( + context: SpanContext, + streamName: string, + consumerGroup: string, + consumerGroupStartId: string, + suppressAlreadyExistsError: boolean = true + ): Promise { + const db = this.config.db; + const span = this.tracer.startSpan("Redis Client xGroup Call", { childOf: context }); + this.spanLogAndSetTags(span, this.xGroup.name, this.config.db, undefined, streamName); + try { + const response = await this.client.xgroup([ + "create", + streamName, + consumerGroup, + consumerGroupStartId, + "mkstream", + ]); + this.metrics.increment(RedisClientMetrics.XGroup, { + db, + streamName, + consumerGroup, + result: RedisMetricResults.Success, + }); + return response; + } catch (err) { + const alreadyExistsErrorMessage = "BUSYGROUP Consumer Group name already exists"; + if (suppressAlreadyExistsError && err.message === alreadyExistsErrorMessage) { + this.metrics.increment(RedisClientMetrics.XGroup, { + db, + streamName, + consumerGroup, + result: RedisMetricResults.AlreadyExists, + }); + + return "OK"; + } + + failSpan(span, err); + this.metrics.increment(RedisClientMetrics.XGroup, { + db, + streamName, + consumerGroup, + result: RedisMetricResults.Error, + error: err, + }); + + throw err; + } finally { + span.finish(); + } + } + + public async xAck( + context: SpanContext, + streamName: string, + consumerGroup: string, + id: string + ): Promise { + const db = this.config.db; + const span = this.tracer.startSpan("Redis Client xAck Call", { childOf: context }); + this.spanLogAndSetTags(span, this.xAck.name, this.config.db, undefined, streamName); + try { + const response = await this.client.xack(streamName, consumerGroup, id); + this.metrics.increment(RedisClientMetrics.XAck, { + db, + streamName, + consumerGroup, + result: RedisMetricResults.Success, + }); + return response; + } catch (err) { + failSpan(span, err); + this.metrics.increment(RedisClientMetrics.XAck, { + db, + streamName, + consumerGroup, + result: RedisMetricResults.Error, + error: err, + }); + + throw err; + } finally { + span.finish(); + } + } + + public async xReadGroup( + context: SpanContext, + streams: { name: string; id?: string }[], + consumerGroup: string, + consumerName: string, + count: number, + block: number + ): Promise { + const db = this.config.db; + const span = this.tracer.startSpan("Redis Client xReadGroupObject Call", { + childOf: context, + }); + const streamNames = streams.map((s) => s.name); + const ids = streams.map((s) => s.id || ">"); + + this.spanLogAndSetTags(span, this.xReadGroup.name, this.config.db, ids, streamNames); + + try { + const response = await this.client.xreadgroup([ + "group", + consumerGroup, + consumerName, + "count", + String(count), + "block", + String(block), + "streams", + ...streamNames, + ...ids, + ]); + + // if the client returns null, early exit w/ an empty array + if (!response) return []; + + const results = parseRawReadGroupResult(response); + + const messages: IRedisMessage[] = results.map( + ({ streamName, messageId, data, type }) => { + const buf = this.config.base64Encode + ? Buffer.from(data, "base64") + : Buffer.from(data); + + return { + messageId, + streamName, + ...this.encoder.decode(new Uint8Array(buf), type), + }; + } + ); + + this.metrics.increment(RedisClientMetrics.XReadGroup, { + db, + consumerGroup, + consumerName, + result: RedisMetricResults.Success, + }); + + return messages; + } catch (error) { + failSpan(span, error); + + this.metrics.increment(RedisClientMetrics.XReadGroup, { + db, + consumerGroup, + consumerName, + result: RedisMetricResults.Error, + error, + }); + throw error; + } finally { + span.finish(); + } + } + + public async xPending( + context: SpanContext, + streamName: string, + consumerGroup: string, + count + ): Promise { + const db = this.config.db; + const span = this.tracer.startSpan("Redis Client xPending Call", { childOf: context }); + this.spanLogAndSetTags(span, this.xPending.name, this.config.db, undefined, streamName); + try { + const results = await this.client.xpending([ + streamName, + consumerGroup, + "-", + "+", + String(count), + ]); + this.metrics.increment(RedisClientMetrics.XPending, { + db, + streamName, + consumerGroup, + result: RedisMetricResults.Success, + }); + return parseRawPELResult(results); + } catch (err) { + failSpan(span, err); + this.metrics.increment(RedisClientMetrics.XPending, { + db, + streamName, + consumerGroup, + result: RedisMetricResults.Error, + error: err, + }); + + throw err; + } finally { + span.finish(); + } + } + + public async xClaim( + context: SpanContext, + streamName: string, + consumerGroup: string, + consumerName: string, + minIdleTime: number, + ids: string[] + ): Promise { + if (ids.length < 1) return []; + + const db = this.config.db; + const span = this.tracer.startSpan("Redis Client xClaim Call", { childOf: context }); + this.spanLogAndSetTags(span, this.xClaim.name, this.config.db, null, streamName); + + try { + const response = await this.client.xclaim([ + streamName, + consumerGroup, + consumerName, + String(minIdleTime), + ...ids, + ]); + + if (!response) return []; + + const results = extractXClaimValues(response); + const messages: IRedisMessage[] = results.map(({ messageId, data, type }) => { + const buf = this.config.base64Encode + ? Buffer.from(data, "base64") + : Buffer.from(data); + + return { messageId, streamName, ...this.encoder.decode(new Uint8Array(buf), type) }; + }); + + this.metrics.increment(RedisClientMetrics.XClaim, { + db, + streamName, + consumerGroup, + consumerName, + result: RedisMetricResults.Success, + }); + + return messages; + } catch (error) { + failSpan(span, error); + this.metrics.increment(RedisClientMetrics.XClaim, { + db, + streamName, + consumerGroup, + consumerName, + result: RedisMetricResults.Error, + error, + }); + throw error; + } finally { + span.finish(); + } + } } diff --git a/packages/redis/src/RedisProxy.ts b/packages/redis/src/RedisProxy.ts index a20b142a..44ffec81 100644 --- a/packages/redis/src/RedisProxy.ts +++ b/packages/redis/src/RedisProxy.ts @@ -12,57 +12,79 @@ import { ILogger, IRequireInitialization, } from "@walmartlabs/cookie-cutter-core"; -import { ClientOpts, RedisClient } from "redis"; +import { RedisClient, Callback } from "redis"; import { promisify } from "util"; -export enum RedisLogMessages { - Connected = "Redis Connected", - Error = "Redis Error", - Ready = "Redis Ready", - Reconnecting = "Redis Reconnecting", - End = "Redis End", -} +// [[streamName, [[id, [key, value, key, value ...]]]]] +export type RawReadGroupResult = [[string, [[string, string[]]]]]; + +export type RawXClaimResult = [[string, string[]]]; + +export type RawPELResult = [[string, string, number, number]]; -export enum RedisEvents { - Connected = "connected", - Error = "error", - Ready = "ready", - Reconnecting = "reconnecting", - End = "end", +interface IRedisCommandPatches { + xadd: (args: (string | Buffer)[], cb: Callback) => boolean; + xreadgroup: (args: string[], cb: Callback) => boolean; + xgroup: (args: string[], cb: Callback<"OK">) => boolean; + xack: (args: string[], cb: Callback) => boolean; + xpending: (args: string[], cb: Callback) => boolean; + xclaim: (args: string[], cb: Callback) => boolean; + set: (key: string, value: string | Buffer, cb: Callback<"OK">) => boolean; } +export type RedisClientWithStreamOperations = RedisClient & IRedisCommandPatches; + export class RedisProxy implements IRequireInitialization, IDisposable { - private client: RedisClient; - private logger: ILogger; + private readonly client: RedisClientWithStreamOperations; + + private logger: ILogger = DefaultComponentContext.logger; private asyncGet: (key: string) => Promise; - private asyncSet: (key: string, value: string) => Promise<{}>; + private asyncSet: (key: string, value: string | Buffer) => Promise<"OK">; private asyncQuit: () => Promise; - constructor(host: string, port: number, db: number) { - this.logger = DefaultComponentContext.logger; - const opts: ClientOpts = { + private asyncXAdd: (args: (string | Buffer)[]) => Promise; + private asyncXReadGroup: (args: string[]) => Promise; + private asyncXGroup: (args: string[]) => Promise<"OK">; + private asyncXAck: (args: string[]) => Promise; + private asyncXPending: (args: string[]) => Promise; + private asyncXClaim: (args: string[]) => Promise; + + constructor(host: string, port: number, db: number, password?: string) { + // Redis ^2.8.0 includes all of the stream operations available on the the client. + // However, @types/redis@2.8 does not currently include typings of the stream operations. + // As proof, we can see redis@3.0.0 lists redis-commands@^1.5.0 as a dependency (https://www.runpkg.com/?redis@3.0.2/package.json) + // If we then look at redis-commands@1.5.0, we can see the available commands (including all stream commands) in the commands.json file (https://www.runpkg.com/?redis-commands@1.5.0/commands.json) + this.client = new RedisClient({ host, port, db, - }; - this.client = new RedisClient(opts); - this.client.on(RedisEvents.Connected, () => { - this.logger.info(RedisLogMessages.Connected); + password, + }) as RedisClientWithStreamOperations; + + this.client.on("connected", () => { + this.logger.debug("Connection to Redis established"); }); - this.client.on(RedisEvents.Error, (err) => { - this.logger.error(RedisLogMessages.Error, err); + this.client.on("error", (err) => { + this.logger.error("Redis Error", err); throw err; }); - this.client.on(RedisEvents.Ready, () => { - this.logger.info(RedisLogMessages.Ready); + this.client.on("ready", () => { + this.logger.debug("Redis connection is ready"); }); - this.client.on(RedisEvents.Reconnecting, () => { - this.logger.info(RedisLogMessages.Reconnecting); + this.client.on("reconnecting", () => { + this.logger.debug("Reconnecting to Redis"); }); - this.client.on(RedisEvents.End, () => { - this.logger.info(RedisLogMessages.End); + this.client.on("end", () => { + this.logger.debug("Disconnected from Redis"); }); + this.asyncGet = promisify(this.client.get).bind(this.client); - this.asyncSet = promisify(this.client.set).bind(this.client) as any; + this.asyncSet = promisify(this.client.set).bind(this.client); + this.asyncXAdd = promisify(this.client.xadd).bind(this.client); + this.asyncXReadGroup = promisify(this.client.xreadgroup).bind(this.client); + this.asyncXGroup = promisify(this.client.xgroup).bind(this.client); + this.asyncXAck = promisify(this.client.xack).bind(this.client); + this.asyncXPending = promisify(this.client.xpending).bind(this.client); + this.asyncXClaim = promisify(this.client.xclaim).bind(this.client); this.asyncQuit = promisify(this.client.quit).bind(this.client); } @@ -71,21 +93,39 @@ export class RedisProxy implements IRequireInitialization, IDisposable { } public async dispose() { - return this.asyncQuit(); + await this.asyncQuit(); + this.client.unref(); + } + + public set(key: string, value: string | Buffer): Promise<"OK"> { + return this.asyncSet(key, value); + } + + public get(key: string): Promise { + return this.asyncGet(key); + } + + public xadd(args: (string | Buffer)[]): Promise { + return this.asyncXAdd(args); + } + + public xgroup(args: string[]): Promise<"OK"> { + return this.asyncXGroup(args); + } + + public xack(streamName: string, consumerGroup: string, id: string): Promise { + return this.asyncXAck([streamName, consumerGroup, id]); + } + + public xreadgroup(args: string[]): Promise { + return this.asyncXReadGroup(args); } - public async set(key: string, value: Uint8Array) { - // Base 64 encoding is used due to library constraints, and time constraints. - // It should ultimately be updated to support direct set of byte arrays. - const storableValue = Buffer.from(value).toString("base64"); - return await this.asyncSet(key, storableValue); + public xpending(args: string[]): Promise { + return this.asyncXPending(args); } - public async get(key: string): Promise { - const val = await this.asyncGet(key); - if (val) { - return new Uint8Array(Buffer.from(val, "base64")); - } - return undefined; + public xclaim(args: string[]): Promise { + return this.asyncXClaim(args); } } diff --git a/packages/redis/src/RedisStreamSink.ts b/packages/redis/src/RedisStreamSink.ts new file mode 100644 index 00000000..638d7af7 --- /dev/null +++ b/packages/redis/src/RedisStreamSink.ts @@ -0,0 +1,97 @@ +/* +Copyright (c) Walmart Inc. + +This source code is licensed under the Apache 2.0 license found in the +LICENSE file in the root directory of this source tree. +*/ + +import { + IOutputSink, + IPublishedMessage, + IOutputSinkGuarantees, + IRequireInitialization, + IDisposable, + IComponentContext, + makeLifecycle, + Lifecycle, + OutputSinkConsistencyLevel, + RetrierContext, + IMetrics, +} from "@walmartlabs/cookie-cutter-core"; + +import { IRedisClient, IRedisOutputStreamOptions, RedisStreamMetadata } from "."; +import { ParserError, AggregateError } from "redis"; +import { RedisClient } from "./RedisClient"; + +export enum RedisMetrics { + MsgPublished = "cookie_cutter.redis_producer.msg_published", +} + +export enum RedisMetricResult { + Success = "success", + Error = "error", +} + +export class RedisStreamSink + implements IOutputSink, IRequireInitialization, IDisposable { + public guarantees: IOutputSinkGuarantees; + private client: Lifecycle; + private metrics: IMetrics; + + constructor(private readonly config: IRedisOutputStreamOptions) { + this.guarantees = { + consistency: OutputSinkConsistencyLevel.None, + idempotent: false, + }; + } + + async sink(output: IterableIterator, retry: RetrierContext): Promise { + let writeStream = this.config.stream; + try { + for (const msg of output) { + writeStream = msg.metadata[RedisStreamMetadata.Stream] || this.config.stream; + + await this.client.xAddObject( + msg.spanContext, + msg.message.type, + writeStream, + { + payload: this.config.payloadKey, + typeName: this.config.typeNameKey, + }, + msg.message.payload, + undefined, + this.config.maxStreamLength + ); + + this.metrics.increment(RedisMetrics.MsgPublished, { + stream_name: writeStream, + result: RedisMetricResult.Success, + }); + } + } catch (err) { + this.metrics.increment(RedisMetrics.MsgPublished, { + stream_name: writeStream, + result: RedisMetricResult.Error, + }); + + if (err instanceof ParserError || err instanceof AggregateError) { + retry.bail(err); + } else { + throw err; + } + } + } + + public async initialize(context: IComponentContext): Promise { + this.metrics = context.metrics; + this.client = makeLifecycle(new RedisClient(this.config)); + await this.client.initialize(context); + } + + public async dispose(): Promise { + if (this.client) { + await this.client.dispose(); + } + } +} diff --git a/packages/redis/src/RedisStreamSource.ts b/packages/redis/src/RedisStreamSource.ts new file mode 100644 index 00000000..399784c3 --- /dev/null +++ b/packages/redis/src/RedisStreamSource.ts @@ -0,0 +1,312 @@ +/* +Copyright (c) Walmart Inc. + +This source code is licensed under the Apache 2.0 license found in the +LICENSE file in the root directory of this source tree. +*/ + +import { + IInputSource, + IRequireInitialization, + IDisposable, + MessageRef, + IComponentContext, + DefaultComponentContext, + Lifecycle, + makeLifecycle, + IMetrics, + failSpan, + ILogger, +} from "@walmartlabs/cookie-cutter-core"; +import { Span, Tags, Tracer } from "opentracing"; + +import { IRedisInputStreamOptions, IRedisClient, IRedisMessage, RedisStreamMetadata } from "."; +import { RedisOpenTracingTagKeys, RedisClient } from "./RedisClient"; + +export enum RedisMetrics { + MsgReceived = "cookie_cutter.redis_consumer.input_msg_received", + MsgProcessed = "cookie_cutter.redis_consumer.input_msg_processed", + MsgsClaimed = "cookie_cutter.redis_consumer.input_msgs_claimed", + PendingMsgSize = "cookie_cutter.redis_consumer.pending_msg_size", + IncomingBatchSize = "cookie_cutter.redis_consumer.incoming_batch_size", +} + +export enum RedisMetricResult { + Success = "success", + Error = "error", +} + +export class RedisStreamSource implements IInputSource, IRequireInitialization, IDisposable { + private done: boolean = false; + private client: Lifecycle; + private tracer: Tracer = DefaultComponentContext.tracer; + private metrics: IMetrics = DefaultComponentContext.metrics; + private logger: ILogger = DefaultComponentContext.logger; + private spanOperationName: string = "Redis Input Source Client Call"; + private lastPendingMessagesCheck: Date | undefined; + + constructor(private readonly config: IRedisInputStreamOptions) {} + + public async *start(): AsyncIterableIterator { + // On initial start attempt to fetch any messages from this consumers PEL + // these are messages that were previously read with XReadGroup by + // this consumer group, but were not acked. This can happen on service restarts + let streams = this.config.streams.map((name) => ({ name, id: "0" })); + while (!this.done) { + const span = this.tracer.startSpan(this.spanOperationName); + + this.spanLogAndSetTags( + span, + this.config.db, + this.config.streams, + this.config.consumerGroup + ); + + try { + const messages = await this.client.xReadGroup( + span.context(), + streams, + this.config.consumerGroup, + this.config.consumerId, + this.config.batchSize, + this.config.blockTimeout + ); + + if (messages.length === 0) { + break; + } + + this.metrics.gauge(RedisMetrics.IncomingBatchSize, messages.length, {}); + for (const message of messages) { + // when calling XReadGroup again only get messages after this one + streams.filter((s) => s.name === message.streamName)[0].id = message.messageId; + yield this.createMessageRef(message, span); + } + } catch (e) { + failSpan(span, e); + throw e; + } finally { + span.finish(); + } + } + + // Now start processing new messages in the stream that have not been + // read before with XReadGroup + streams = this.config.streams.map((name) => ({ name, id: ">" })); + let didXReadGroup = true; + while (!this.done) { + const span = this.tracer.startSpan(this.spanOperationName); + + this.spanLogAndSetTags( + span, + this.config.db, + this.config.streams, + this.config.consumerGroup + ); + + try { + let messages = []; + + // Once in a while check the PEL list for _other_ consumers + // to reclaim orphaned messages. This can happen if a consumer dies + // or permanently leaves the consumer groupe (e.g. scaling down to less instances) + if ( + this.config.reclaimMessageInterval && + didXReadGroup && + (this.lastPendingMessagesCheck === undefined || + this.lastPendingMessagesCheck.getTime() + + this.config.reclaimMessageInterval <= + Date.now()) + ) { + messages = await this.getPendingMessagesForConsumerGroup(span); + + // don't update if there were pending messages, try again on next + // iteration until pending messages are drained + if (messages.length === 0) { + this.lastPendingMessagesCheck = new Date(Date.now()); + didXReadGroup = false; + } + } else { + messages = await this.client.xReadGroup( + span.context(), + streams, + this.config.consumerGroup, + this.config.consumerId, + this.config.batchSize, + this.config.blockTimeout + ); + + // this variable ensures that we don't get stuck in the reclaim + // loop due to bad timing ... ensure that at least one XReadGroup + // command gets interleaved after each check for pending messages + didXReadGroup = true; + } + + if (messages.length > 0) { + this.metrics.gauge(RedisMetrics.IncomingBatchSize, messages.length, {}); + for (const message of messages) { + yield this.createMessageRef(message, span); + } + } + } catch (e) { + failSpan(span, e); + throw e; + } finally { + span.finish(); + } + } + } + + public async stop(): Promise { + this.done = true; + } + + public async initialize(context: IComponentContext): Promise { + this.tracer = context.tracer; + this.metrics = context.metrics; + this.logger = context.logger; + + this.client = makeLifecycle(new RedisClient(this.config)); + await this.client.initialize(context); + + const span = this.tracer.startSpan(this.spanOperationName); + this.spanLogAndSetTags( + span, + this.config.db, + this.config.streams, + this.config.consumerGroup + ); + + try { + // Attempt to create stream + consumer group if they don't already exist + for (const readStream of this.config.streams) { + await this.client.xGroup( + span.context(), + readStream, + this.config.consumerGroup, + this.config.consumerGroupStartId + ); + } + } catch (error) { + failSpan(span, error); + throw error; + } finally { + span.finish(); + } + } + + public async dispose(): Promise { + if (this.client) { + await this.client.dispose(); + } + } + + private createMessageRef(message: IRedisMessage, span: Span): MessageRef { + this.metrics.increment(RedisMetrics.MsgReceived, { + stream_name: message.streamName, + consumer_group: this.config.consumerGroup, + }); + + const messageRef = new MessageRef( + { + [RedisStreamMetadata.MessageId]: message.messageId, + [RedisStreamMetadata.Stream]: message.streamName, + [RedisStreamMetadata.ConsumerId]: this.config.consumerGroup, + }, + message, + span.context() + ); + + messageRef.once("released", (msg, _, err) => this.onMessageReleased(span, msg, err)); + return messageRef; + } + + private async onMessageReleased(span: Span, msg: MessageRef, err: Error) { + const stream = msg.metadata(RedisStreamMetadata.Stream); + const messageId = msg.metadata(RedisStreamMetadata.MessageId); + const consumerId = msg.metadata(RedisStreamMetadata.ConsumerId); + + try { + if (err) throw err; + + const count = await this.client.xAck(span.context(), stream, consumerId, messageId); + if (count !== 1) { + throw new Error("not found in PEL"); + } + + this.metrics.increment(RedisMetrics.MsgProcessed, { + stream_name: stream, + consumer_group: consumerId, + result: RedisMetricResult.Success, + }); + } catch (e) { + failSpan(span, e); + this.metrics.increment(RedisMetrics.MsgProcessed, { + stream_name: stream, + consumer_group: consumerId, + result: RedisMetricResult.Error, + }); + + if (!err) { + this.logger.error("failed to ack message", err, { messageId, stream, consumerId }); + } + } finally { + span.finish(); + } + } + + private async getPendingMessagesForConsumerGroup(span: Span): Promise { + const messages = new Array(); + for (const readStream of this.config.streams) { + const pendingMessages = await this.client.xPending( + span.context(), + readStream, + this.config.consumerGroup, + this.config.batchSize + ); + + this.metrics.gauge(RedisMetrics.PendingMsgSize, pendingMessages.length, { + stream_name: readStream, + consumer_group: this.config.consumerGroup, + }); + + // if there are no pending messages return early w/ an empty array + if (!pendingMessages.length) { + continue; + } + + const pendingMessagesIds = pendingMessages.map(({ messageId }) => messageId); + + const claimedMessages = await this.client.xClaim( + span.context(), + readStream, + this.config.consumerGroup, + this.config.consumerId, + this.config.idleTimeout, + pendingMessagesIds + ); + + messages.push(...claimedMessages); + this.metrics.increment(RedisMetrics.MsgsClaimed, claimedMessages.length, { + stream_name: readStream, + consumer_group: this.config.consumerGroup, + }); + } + + return messages; + } + + private spanLogAndSetTags( + span: Span, + bucket: number, + streamNames: string | string[], + consumerGroup: string + ): void { + span.log({ bucket, streamNames, consumerGroup }); + + span.setTag(Tags.SPAN_KIND, Tags.SPAN_KIND_RPC_CLIENT); + span.setTag(Tags.COMPONENT, "cookie-cutter-redis"); + span.setTag(Tags.DB_INSTANCE, bucket); + span.setTag(RedisOpenTracingTagKeys.BucketName, bucket); + } +} diff --git a/packages/redis/src/__test__/client.integration.test.ts b/packages/redis/src/__test__/client.integration.test.ts new file mode 100644 index 00000000..1642bb5e --- /dev/null +++ b/packages/redis/src/__test__/client.integration.test.ts @@ -0,0 +1,37 @@ +/* +Copyright (c) Walmart Inc. + +This source code is licensed under the Apache 2.0 license found in the +LICENSE file in the root directory of this source tree. +*/ + +import { createRedisClient } from "./utils"; +import { SpanContext } from "opentracing"; + +class TestClass { + constructor(public text: string) {} +} + +describe("RedisClient", () => { + it("returns undefined when retrieving a key that does not exist", async () => { + const client = createRedisClient(); + try { + const obj = await client.getObject(new SpanContext(), Uint8Array, "does-not-exist"); + expect(obj).toBeUndefined(); + } finally { + await client.dispose(); + } + }); + + it("stores and retrieves and object by key", async () => { + const client = createRedisClient(); + try { + const expected = new TestClass("foo bar"); + await client.putObject(new SpanContext(), TestClass, expected, "key-1"); + const actual = await client.getObject(new SpanContext(), TestClass, "key-1"); + expect(actual).toMatchObject(expected); + } finally { + await client.dispose(); + } + }); +}); diff --git a/packages/redis/src/__test__/protocol.test.ts b/packages/redis/src/__test__/protocol.test.ts new file mode 100644 index 00000000..62960119 --- /dev/null +++ b/packages/redis/src/__test__/protocol.test.ts @@ -0,0 +1,35 @@ +/* +Copyright (c) Walmart Inc. + +This source code is licensed under the Apache 2.0 license found in the +LICENSE file in the root directory of this source tree. +*/ + +import { parseRawReadGroupResult } from "../RedisClient"; +import { RawReadGroupResult } from "../RedisProxy"; + +describe("XReadGroup response parsing", () => { + it("parses single stream result", () => { + const data: RawReadGroupResult = [ + [ + "stream-1", + [ + ["1597844517517-0", ["redis.stream.key", '{"foo": "bar"}']], + ["1597844517952-0", ["redis.stream.key", '{"fizz": "buzz"}']], + ["1597844518432-0", ["redis.stream.key", '{"bar": "foo"}']], + ], + ], + [ + "stream-2", + [ + ["1597844517517-0", ["redis.stream.key", '{"foo": "bar"}']], + ["1597844517952-0", ["redis.stream.key", '{"fizz": "buzz"}']], + ["1597844518432-0", ["redis.stream.key", '{"bar": "foo"}']], + ], + ], + ] as any; + + const messages = parseRawReadGroupResult(data); + expect(messages).toHaveLength(6); + }); +}); diff --git a/packages/redis/src/__test__/redisClient.test.ts b/packages/redis/src/__test__/redisClient.test.ts deleted file mode 100644 index 405e131f..00000000 --- a/packages/redis/src/__test__/redisClient.test.ts +++ /dev/null @@ -1,171 +0,0 @@ -/* -Copyright (c) Walmart Inc. - -This source code is licensed under the Apache 2.0 license found in the -LICENSE file in the root directory of this source tree. -*/ - -import { - DefaultComponentContext, - IComponentContext, - NullMessageEncoder, -} from "@walmartlabs/cookie-cutter-core"; -import { SpanContext } from "opentracing"; -import * as util from "util"; -import { IRedisOptions } from ".."; -import { RedisClient as CCRedisClient } from "../RedisClient"; -(util as any).promisify = jest.fn((fn) => fn); -const mockOn = jest.fn(); -const mockGet = jest.fn(); -const mockSet = jest.fn(); -const mockQuit = jest.fn(); - -jest.mock("redis", () => { - const mockRedisClient = jest.fn(() => ({ - on: mockOn, - get: mockGet, - set: mockSet, - quit: mockQuit, - })); - return { RedisClient: mockRedisClient }; -}); -import { RedisClient } from "redis"; -const mockClient: jest.Mock = RedisClient as any; - -// Note that an integration test is far more important than this unit test, -// and should be created before this expands usage beyond a single service. -describe("Unit test the redis client", () => { - const encoder = { - mimeType: "testMimeType", - decode: (v: any) => v, - encode: (v: any) => new Uint8Array(Buffer.from(v.payload)), - }; - const config: IRedisOptions = { - host: "testHost", - port: 0, - db: 0, - encoder: new NullMessageEncoder(), - typeMapper: { - map: (v: any) => v, - }, - }; - beforeEach(() => { - mockClient.mockClear(); - mockOn.mockClear(); - mockGet.mockClear(); - mockSet.mockClear(); - mockQuit.mockClear(); - }); - it("Instantiates the client", async () => { - expect(1).toBe(1); - const infoLogger = jest.fn(); - const redisClient = new CCRedisClient(config); - const ctx: IComponentContext = { - ...DefaultComponentContext, - logger: { info: infoLogger } as any, - }; - await redisClient.initialize(ctx); - // Check that we instantiate the client - expect(mockClient.mock.calls.length).toEqual(1); - }); - it("Disposes of underlying client", async () => { - const infoLogger = jest.fn(); - const redisClient = new CCRedisClient(config); - const ctx: IComponentContext = { - ...DefaultComponentContext, - logger: { info: infoLogger } as any, - }; - await redisClient.initialize(ctx); - await redisClient.dispose(); - expect(mockQuit.mock.calls.length).toEqual(1); - }); - it("Puts obj into storage successfully", async () => { - const infoLogger = jest.fn(); - const redisClient = new CCRedisClient({ ...config, encoder }); - const ctx: IComponentContext = { - ...DefaultComponentContext, - logger: { info: infoLogger } as any, - }; - await redisClient.initialize(ctx); - const span = new SpanContext(); - const key = "testKey"; - const value = "testValue"; - const type = "testType"; - await redisClient.putObject(span, type, value, key); - expect(mockSet.mock.calls.length).toEqual(1); - }); - it("Fails to put object in storage", async () => { - const infoLogger = jest.fn(); - const redisClient = new CCRedisClient({ - ...config, - encoder, - typeMapper: { - map: (v: any) => v.val, - }, - }); - const ctx: IComponentContext = { - ...DefaultComponentContext, - logger: { info: infoLogger } as any, - }; - await redisClient.initialize(ctx); - const span = new SpanContext(); - const key = "testKey"; - const value = "testValue"; - const type = { val: "testType" }; - const testError = "testError"; - mockSet.mockImplementation(async () => { - throw new Error(testError); - }); - await expect(redisClient.putObject(span, type as any, value, key)).rejects.toThrow( - testError - ); - }); - it("Fails during retrieval", async () => { - const infoLogger = jest.fn(); - const redisClient = new CCRedisClient({ - ...config, - encoder, - typeMapper: { - map: (v: any) => v.val, - }, - }); - const ctx: IComponentContext = { - ...DefaultComponentContext, - logger: { info: infoLogger } as any, - }; - await redisClient.initialize(ctx); - const span = new SpanContext(); - const key = "testKey"; - const type = { val: "testType" }; - const testError = "testError"; - mockGet.mockImplementation(async () => { - throw new Error(testError); - }); - await expect(redisClient.getObject(span, type as any, key)).rejects.toThrow(testError); - }); - it("Gets obj from storage successfully", async () => { - const infoLogger = jest.fn(); - const redisClient = new CCRedisClient({ - ...config, - encoder: { - mimeType: "testType", - decode: (v: any) => ({ type: "test", payload: v }), - encode: (v: any) => new Uint8Array(Buffer.from(v.payload)), - }, - }); - const ctx: IComponentContext = { - ...DefaultComponentContext, - logger: { info: infoLogger } as any, - }; - await redisClient.initialize(ctx); - const span = new SpanContext(); - const key = "testKey"; - const value = new Uint8Array(Buffer.from("TestValue")); - const base64Value = Buffer.from(value).toString("base64"); - const type = "testType"; - mockGet.mockImplementation(() => base64Value); - const getVal = await redisClient.getObject(span, type, key); - expect(mockGet.mock.calls.length).toEqual(1); - expect(getVal).toEqual(value); - }); -}); diff --git a/packages/redis/src/__test__/redisProxy.test.ts b/packages/redis/src/__test__/redisProxy.test.ts deleted file mode 100644 index f9c5f295..00000000 --- a/packages/redis/src/__test__/redisProxy.test.ts +++ /dev/null @@ -1,123 +0,0 @@ -/* -Copyright (c) Walmart Inc. - -This source code is licensed under the Apache 2.0 license found in the -LICENSE file in the root directory of this source tree. -*/ - -import { ConsoleLogger, DefaultComponentContext } from "@walmartlabs/cookie-cutter-core"; -import * as util from "util"; -import { RedisEvents, RedisLogMessages, RedisProxy } from "../RedisProxy"; -(util as any).promisify = jest.fn((fn) => fn); -const mockOn = jest.fn(); -const mockGet = jest.fn(); -const mockSet = jest.fn(); -const mockQuit = jest.fn(); - -jest.mock("redis", () => { - const mockRedisClient = jest.fn(() => ({ - on: mockOn, - get: mockGet, - set: mockSet, - quit: mockQuit, - })); - return { RedisClient: mockRedisClient }; -}); -import { RedisClient } from "redis"; - -const mockClient: jest.Mock = RedisClient as any; - -// Note that an integration test is far more important than this unit test, -// and should be created before this expands usage beyond a single service. -describe("Unit test the redis Proxy", () => { - const ctx = { ...DefaultComponentContext, logger: new ConsoleLogger() }; - beforeEach(() => { - mockClient.mockClear(); - mockOn.mockClear(); - mockGet.mockClear(); - mockSet.mockClear(); - mockQuit.mockClear(); - }); - it("Instantiates the client and registers all event handlers with logging", async () => { - expect(1).toBe(1); - const infoLogger = jest.fn(); - const errorLogger = jest.fn(); - const redisProxy = new RedisProxy("testHost", 0, 0); - await redisProxy.initialize({ - ...ctx, - logger: { - info: infoLogger, - error: errorLogger, - } as any, - }); - if (redisProxy) { - // do nothing; - } - // Check that we instantiate the client - expect(mockClient.mock.calls.length).toEqual(1); - // Check that we add the correct number of listeners - expect(mockOn.mock.calls.length).toEqual(5); - // Check that we listen to all known events - expect(mockOn.mock.calls[0][0]).toEqual(RedisEvents.Connected); - expect(mockOn.mock.calls[1][0]).toEqual(RedisEvents.Error); - expect(mockOn.mock.calls[2][0]).toEqual(RedisEvents.Ready); - expect(mockOn.mock.calls[3][0]).toEqual(RedisEvents.Reconnecting); - expect(mockOn.mock.calls[4][0]).toEqual(RedisEvents.End); - // Test that all events are logged - const testError = "testError"; - mockOn.mock.calls[0][1](); - try { - mockOn.mock.calls[1][1](testError); - } catch (error) { - expect(error).toContain(testError); - } - mockOn.mock.calls[2][1](); - mockOn.mock.calls[3][1](); - mockOn.mock.calls[4][1](); - expect(infoLogger.mock.calls[0][0]).toEqual(RedisLogMessages.Connected); - expect(infoLogger.mock.calls[1][0]).toEqual(RedisLogMessages.Ready); - expect(infoLogger.mock.calls[2][0]).toEqual(RedisLogMessages.Reconnecting); - expect(infoLogger.mock.calls[3][0]).toEqual(RedisLogMessages.End); - - expect(errorLogger.mock.calls[0][0]).toEqual(RedisLogMessages.Error); - expect(errorLogger.mock.calls[0][1]).toEqual(testError); - }); - it("Passes the key and value to the redis set function and converts the value to base64.", async () => { - const redisProxy = new RedisProxy("testHost", 0, 0); - await redisProxy.initialize(ctx); - const key = "testKey"; - const value = new Uint8Array(Buffer.from("TestValue")); - const base64Value = Buffer.from(value).toString("base64"); - await redisProxy.set(key, value); - expect(mockSet.mock.calls.length).toEqual(1); - expect(mockSet.mock.calls[0][0]).toEqual(key); - expect(mockSet.mock.calls[0][1]).toEqual(base64Value); - }); - it("Gets value by key and decodes from base64", async () => { - const redisProxy = new RedisProxy("testHost", 0, 0); - await redisProxy.initialize(ctx); - const key = "testKey"; - const value = new Uint8Array(Buffer.from("TestValue")); - const base64Value = Buffer.from(value).toString("base64"); - mockGet.mockImplementationOnce(() => base64Value); - const retValue = await redisProxy.get(key); - expect(mockGet.mock.calls.length).toEqual(1); - expect(mockGet.mock.calls[0][0]).toEqual(key); - expect(retValue).toEqual(value); - }); - it("Returns undefined when no value is returned from the client", async () => { - const redisProxy = new RedisProxy("testHost", 0, 0); - await redisProxy.initialize(ctx); - const key = "testKey"; - const retValue = await redisProxy.get(key); - expect(mockGet.mock.calls.length).toEqual(1); - expect(mockGet.mock.calls[0][0]).toEqual(key); - expect(retValue).toBeUndefined(); - }); - it("Sends a quit command to the client", async () => { - const redisProxy = new RedisProxy("testHost", 0, 0); - await redisProxy.initialize(ctx); - await redisProxy.dispose(); - expect(mockQuit.mock.calls.length).toEqual(1); - }); -}); diff --git a/packages/redis/src/__test__/stream.integration.test.ts b/packages/redis/src/__test__/stream.integration.test.ts new file mode 100644 index 00000000..3d39fecc --- /dev/null +++ b/packages/redis/src/__test__/stream.integration.test.ts @@ -0,0 +1,331 @@ +/* +Copyright (c) Walmart Inc. + +This source code is licensed under the Apache 2.0 license found in the +LICENSE file in the root directory of this source tree. +*/ + +import { + Application, + StaticInputSource, + JsonMessageEncoder, + ObjectNameMessageTypeMapper, + CapturingOutputSink, + sleep, + IPublishedMessage, + MessageRef, + ErrorHandlingMode, + IMetrics, +} from "@walmartlabs/cookie-cutter-core"; +import { + redisStreamSink, + redisStreamSource, + RedisStreamMetadata, + IRedisInputStreamOptions, + IRedisOutputStreamOptions, +} from ".."; +import { RepublishMessageDispatcher } from "./utils"; +import { RedisClientMetrics } from "../RedisClient"; +import { RedisMetrics } from "../RedisStreamSource"; + +const RoundTripTestConfigurationPermutations: [ + string, + Partial +][] = [ + ["base64_on", { base64Encode: true }], + ["base64_off", { base64Encode: false }], + ["batching_off", { batchSize: 1 }], + ["batching_on", { batchSize: 10 }], + ["reclaim_on", { reclaimMessageInterval: 1000, idleTimeout: 10000 }], + ["reclaim_off", { reclaimMessageInterval: null, idleTimeout: 100 }], + ["blocking_low", { blockTimeout: 10 }], + ["blocking_high", { blockTimeout: 500 }], + ["with_consumer_id", { consumerId: "consumer-1234" }], + ["with_max_stream_length", { maxStreamLength: 100 }], + ["default", {}], +]; + +const RedeliveryTestConfigurationPermutations: [string, Partial][] = [ + ["dynamic_consumer_id", { reclaimMessageInterval: 50, idleTimeout: 100 }], + [ + "static_consumer_id", + { consumerId: "consumer-123", reclaimMessageInterval: null, idleTimeout: 100 }, + ], +]; + +describe("Redis Streams", () => { + beforeAll(() => { + jest.setTimeout(90000); + }); + + for (const [id, cfg] of RoundTripTestConfigurationPermutations) { + it(`produces and consumes messages - ${id}`, async () => { + const input: MessageRef[] = []; + for (let i = 0; i < 25; i++) { + input.push( + new MessageRef( + { [RedisStreamMetadata.Stream]: `roundtrip-test-1-${id}` }, + { + type: "type-1", + payload: { foo: "bar-" + i }, + } + ), + new MessageRef( + { [RedisStreamMetadata.Stream]: `roundtrip-test-2-${id}` }, + { + type: "type-2", + payload: { fizz: "buzz-" + i }, + } + ), + new MessageRef( + {}, + { + type: "type-1", + payload: { foo: "buzz-" + i }, + } + ) + ); + } + + const producer = Application.create() + .input() + .add(new StaticInputSource(input)) + .done() + .dispatch(new RepublishMessageDispatcher()) + .output() + .published( + redisStreamSink({ + host: "localhost", + encoder: new JsonMessageEncoder(), + stream: `roundtrip-test-1-${id}`, + typeMapper: new ObjectNameMessageTypeMapper(), + ...cfg, + }) + ) + .done() + .run(); + + const metrics: IMetrics = { + increment: jest.fn(), + gauge: jest.fn(), + timing: jest.fn(), + }; + + const captured: IPublishedMessage[] = []; + const consumer = Application.create() + .input() + .add( + redisStreamSource({ + consumerGroup: `roundtrip-test-group-${id}`, + encoder: new JsonMessageEncoder(), + host: "localhost", + streams: [`roundtrip-test-1-${id}`, `roundtrip-test-2-${id}`], + typeMapper: new ObjectNameMessageTypeMapper(), + ...cfg, + + // important for unit test, as consumer might not be + // ready to receive before producer starts sending messages + consumerGroupStartId: "0", + }) + ) + .done() + .metrics(metrics) + .dispatch(new RepublishMessageDispatcher()) + .output() + .published(new CapturingOutputSink(captured)) + .done() + .run(); + + await producer; + while (captured.length < input.length) { + await sleep(500); + } + + consumer.cancel(); + await consumer; + + // split into streams as ordering is only guaranteed within the same stream + // ... all messages that have a field `fizz` are sent to stream2 + // ... all messages with field `foo` are sent to stream1 + const expectedStream1 = input + .filter((m) => m.payload.payload.foo) + .map((s) => s.payload); + const expectedStream2 = input + .filter((m) => m.payload.payload.fizz) + .map((s) => s.payload); + const actualStream1 = captured + .filter((m) => m.message.payload.foo) + .map((s) => s.message); + const actualStream2 = captured + .filter((m) => m.message.payload.fizz) + .map((s) => s.message); + + expect(actualStream1).toMatchObject(expectedStream1); + expect(actualStream2).toMatchObject(expectedStream2); + + expect(metrics.increment).toHaveBeenCalledWith( + RedisClientMetrics.XAck, + expect.anything() + ); + expect(metrics.increment).toHaveBeenCalledWith( + RedisClientMetrics.XReadGroup, + expect.anything() + ); + expect(metrics.increment).toHaveBeenCalledWith( + RedisClientMetrics.XGroup, + expect.anything() + ); + expect(metrics.increment).toHaveBeenCalledWith( + RedisMetrics.MsgReceived, + expect.anything() + ); + expect(metrics.increment).toHaveBeenCalledWith( + RedisMetrics.MsgProcessed, + expect.anything() + ); + expect(metrics.gauge).toHaveBeenCalledWith( + RedisMetrics.IncomingBatchSize, + expect.anything(), + expect.anything() + ); + }); + } + + for (const [id, cfg] of RedeliveryTestConfigurationPermutations) { + it(`failed messages are not acked and reprocessed - ${id}`, async () => { + const input = [ + new MessageRef( + {}, + { + type: "type-1", + payload: { foo: "bar" }, + } + ), + new MessageRef( + {}, + { + type: "type-1", + payload: { foo: "bar" }, + } + ), + ]; + + // Step 1) publish some messages + await Application.create() + .input() + .add(new StaticInputSource(input)) + .done() + .dispatch(new RepublishMessageDispatcher()) + .output() + .published( + redisStreamSink({ + host: "localhost", + encoder: new JsonMessageEncoder(), + stream: `failed-ack-test-${id}`, + typeMapper: new ObjectNameMessageTypeMapper(), + }) + ) + .done() + .run(); + + // Step 2) receive messages, but fail processing all of them + let errors = 0; + let consumer = Application.create() + .input() + .add( + redisStreamSource({ + consumerGroup: `failed-ack-group-${id}`, + encoder: new JsonMessageEncoder(), + host: "localhost", + streams: [`failed-ack-test-${id}`], + typeMapper: new ObjectNameMessageTypeMapper(), + ...cfg, + + // important for unit test, as consumer might not be + // ready to receive before producer starts sending messages + consumerGroupStartId: "0", + }) + ) + .done() + .dispatch({ + canDispatch: () => { + return true; + }, + dispatch: async () => { + errors++; + throw new Error("block processing"); + }, + }) + .run(ErrorHandlingMode.LogAndContinue); + + while (errors === 0) { + await sleep(500); + } + + consumer.cancel(); + await consumer; + + const metrics: IMetrics = { + increment: jest.fn(), + gauge: jest.fn(), + timing: jest.fn(), + }; + + // Step 3) start a new consumer, it should receive the same messages again + const captured: IPublishedMessage[] = []; + consumer = Application.create() + .input() + .add( + redisStreamSource({ + consumerGroup: `failed-ack-group-${id}`, + encoder: new JsonMessageEncoder(), + host: "localhost", + streams: [`failed-ack-test-${id}`], + typeMapper: new ObjectNameMessageTypeMapper(), + ...cfg, + + // important for unit test, as consumer might not be + // ready to receive before producer starts sending messages + consumerGroupStartId: "0", + }) + ) + .done() + .metrics(metrics) + .dispatch(new RepublishMessageDispatcher()) + .output() + .published(new CapturingOutputSink(captured)) + .done() + .run(); + + while (captured.length < input.length) { + await sleep(500); + } + + consumer.cancel(); + await consumer; + + const actual = captured.map((m) => m.message); + const expected = input.map((m) => m.payload); + expect(actual).toMatchObject(expected); + + // if the consumer id is not stable the client is supposed + // to "steal" messages from old/dead consumers with + // the XPending + XClaim mechanism + if (id === "dynamic_consumer_id") { + expect(metrics.increment).toHaveBeenCalledWith( + RedisClientMetrics.XPending, + expect.anything() + ); + expect(metrics.increment).toHaveBeenCalledWith( + RedisClientMetrics.XClaim, + expect.anything() + ); + expect(metrics.increment).toHaveBeenCalledWith( + RedisMetrics.MsgsClaimed, + expect.anything(), + expect.anything() + ); + } + }); + } +}); diff --git a/packages/redis/src/__test__/utils.ts b/packages/redis/src/__test__/utils.ts new file mode 100644 index 00000000..7011d90a --- /dev/null +++ b/packages/redis/src/__test__/utils.ts @@ -0,0 +1,40 @@ +/* +Copyright (c) Walmart Inc. + +This source code is licensed under the Apache 2.0 license found in the +LICENSE file in the root directory of this source tree. +*/ + +import { redisClient, IRedisClient, RedisStreamMetadata } from ".."; +import { + JsonMessageEncoder, + ObjectNameMessageTypeMapper, + IMessageDispatcher, + IMessage, + IDispatchContext, + Lifecycle, + makeLifecycle, +} from "@walmartlabs/cookie-cutter-core"; + +export function createRedisClient(): Lifecycle { + return makeLifecycle( + redisClient({ + host: "localhost", + encoder: new JsonMessageEncoder(), + typeMapper: new ObjectNameMessageTypeMapper(), + }) + ); +} + +export class RepublishMessageDispatcher implements IMessageDispatcher { + canDispatch(_: IMessage): boolean { + return true; + } + + async dispatch(msg: IMessage, ctx: IDispatchContext): Promise { + const stream = ctx.metadata(RedisStreamMetadata.Stream); + ctx.publish({ name: msg.type } as any, msg.payload, { + [RedisStreamMetadata.Stream]: stream, + }); + } +} diff --git a/packages/redis/src/config.ts b/packages/redis/src/config.ts index 54e1de0a..52a796a4 100644 --- a/packages/redis/src/config.ts +++ b/packages/redis/src/config.ts @@ -49,4 +49,121 @@ export class RedisOptions implements IRedisOptions { public get typeMapper(): IMessageTypeMapper { return config.noop(); } + + @config.field(config.converters.string) + public set stream(_: string) { + config.noop(); + } + public get stream(): string { + return config.noop(); + } + + @config.field(config.converters.listOf(config.converters.string)) + public set streams(_: string[]) { + config.noop(); + } + public get streams(): string[] { + return config.noop(); + } + + @config.field(config.converters.string) + public set consumerGroup(_: string) { + config.noop(); + } + public get consumerGroup(): string { + return config.noop(); + } + + @config.field(config.converters.string) + public set consumerId(_: string) { + config.noop(); + } + public get consumerId(): string { + return config.noop(); + } + + @config.field(config.converters.string) + public set consumerGroupStartId(_: string) { + config.noop(); + } + public get consumerGroupStartId(): string { + return config.noop(); + } + + @config.field(config.converters.timespan) + public set blockTimeout(_: number) { + config.noop(); + } + public get blockTimeout(): number { + return config.noop(); + } + + @config.field(config.converters.timespan) + public set idleTimeout(_: number) { + config.noop(); + } + public get idleTimeout(): number { + return config.noop(); + } + + @config.field(config.converters.timespan) + public set reclaimMessageInterval(_: number) { + config.noop(); + } + public get reclaimMessageInterval(): number { + return config.noop(); + } + + @config.field(config.converters.number) + public set batchSize(_: number) { + config.noop(); + } + public get batchSize(): number { + return config.noop(); + } + + @config.field(config.converters.boolean) + public set base64Encode(_: boolean) { + config.noop(); + } + + public get base64Encode(): boolean { + return config.noop(); + } + + @config.field(config.converters.none) + public set password(_: string) { + config.noop(); + } + + public get password(): string { + return config.noop(); + } + + @config.field(config.converters.none) + public set payloadKey(_: string) { + config.noop(); + } + + public get payloadKey(): string { + return config.noop(); + } + + @config.field(config.converters.none) + public set typeNameKey(_: string) { + config.noop(); + } + + public get typeNameKey(): string { + return config.noop(); + } + + @config.field(config.converters.none) + public set maxStreamLength(_: number) { + config.noop(); + } + + public get maxStreamLength(): number { + return config.noop(); + } } diff --git a/packages/redis/src/index.ts b/packages/redis/src/index.ts index 0b1526ef..a6e9b79c 100644 --- a/packages/redis/src/index.ts +++ b/packages/redis/src/index.ts @@ -10,17 +10,57 @@ import { IClassType, IMessageEncoder, IMessageTypeMapper, + IOutputSink, + IPublishedMessage, + IInputSource, + IMessage, + ObjectNameMessageTypeMapper, } from "@walmartlabs/cookie-cutter-core"; import { SpanContext } from "opentracing"; +import { generate } from "shortid"; + import { RedisOptions } from "./config"; -import { RedisClient } from "./RedisClient"; +import { RedisClient, IPELResult } from "./RedisClient"; +import { RedisStreamSink } from "./RedisStreamSink"; +import { RedisStreamSource } from "./RedisStreamSource"; export interface IRedisOptions { readonly host: string; - readonly port: number; - readonly db: number; + readonly port?: number; + readonly db?: number; + readonly password?: string; readonly encoder: IMessageEncoder; - readonly typeMapper: IMessageTypeMapper; + readonly typeMapper?: IMessageTypeMapper; + readonly base64Encode?: boolean; +} + +export type IRedisInputStreamOptions = IRedisOptions & { + readonly streams: string[]; + readonly consumerGroup: string; + readonly consumerId?: string; + readonly consumerGroupStartId?: string; + readonly blockTimeout?: number; + readonly batchSize?: number; + readonly idleTimeout?: number | null; + readonly reclaimMessageInterval?: number | null; +}; + +export type IRedisOutputStreamOptions = IRedisOptions & { + readonly stream: string; + readonly maxStreamLength?: number; + readonly payloadKey?: string; + readonly typeNameKey?: string; +}; + +export type IRedisMessage = IMessage & { + readonly messageId: string; + readonly streamName: string; +}; + +export enum RedisStreamMetadata { + MessageId = "redis.messageId", + Stream = "redis.stream", + ConsumerId = "redis.consumerId", } export interface IRedisClient { @@ -35,9 +75,93 @@ export interface IRedisClient { type: string | IClassType, key: string ): Promise; + xAddObject( + context: SpanContext, + type: string | IClassType, + streamName: string, + keys: { + payload: string; + typeName: string; + }, + body: T, + id?: string, + maxStreamLength?: number + ): Promise; + xReadGroup( + context: SpanContext, + streams: { name: string; id?: string }[], + consumerGroup: string, + consumerName: string, + count: number, + block: number + ): Promise; + xGroup( + context: SpanContext, + streamName: string, + consumerGroup: string, + consumerGroupStartId: string, + supressAlreadyExistsError?: boolean + ): Promise; + xAck( + context: SpanContext, + streamName: string, + consumerGroup: string, + id: string + ): Promise; + xPending( + context: SpanContext, + streamName: string, + consumerGroup: string, + count: number + ): Promise; + xClaim( + context: SpanContext, + streamName: string, + consumerGroup: string, + consumerName: string, + minIdleTime: number, + ids: string[] + ): Promise; } export function redisClient(configuration: IRedisOptions): IRedisClient { - configuration = config.parse(RedisOptions, configuration); + configuration = config.parse(RedisOptions, configuration, { + port: 6379, + db: 0, + base64Encode: true, + typeMapper: new ObjectNameMessageTypeMapper(), + }); return new RedisClient(configuration); } + +export function redisStreamSink( + configuration: IRedisOutputStreamOptions +): IOutputSink { + configuration = config.parse(RedisOptions, configuration, { + port: 6379, + db: 0, + base64Encode: true, + payloadKey: "redis.stream.key", + typeNameKey: "redis.stream.type", + typeMapper: new ObjectNameMessageTypeMapper(), + }); + return new RedisStreamSink(configuration); +} + +export function redisStreamSource(configuration: IRedisInputStreamOptions): IInputSource { + configuration = config.parse(RedisOptions, configuration, { + port: 6379, + db: 0, + base64Encode: true, + consumerId: generate(), + consumerGroupStartId: "$", + batchSize: 10, + blockTimeout: 100, + idleTimeout: 30000, + reclaimMessageInterval: 60000, + payloadKey: "redis.stream.key", + typeNameKey: "redis.stream.type", + typeMapper: new ObjectNameMessageTypeMapper(), + }); + return new RedisStreamSource(configuration); +} diff --git a/packages/s3/package.json b/packages/s3/package.json index c7261595..770c4360 100644 --- a/packages/s3/package.json +++ b/packages/s3/package.json @@ -1,6 +1,6 @@ { "name": "@walmartlabs/cookie-cutter-s3", - "version": "1.2.0", + "version": "1.3.0", "license": "Apache-2.0", "main": "dist/index.js", "types": "dist/index.d.ts", @@ -13,16 +13,16 @@ "url": "https://github.com/walmartlabs/cookie-cutter/issues" }, "dependencies": { - "aws-sdk": "2.673.0", + "aws-sdk": "2.748.0", "opentracing": "0.14.4" }, "peerDependencies": { - "@walmartlabs/cookie-cutter-core": "^1.2.0" + "@walmartlabs/cookie-cutter-core": "^1.3.0" }, "devDependencies": { - "@walmartlabs/cookie-cutter-core": "^1.2.0", + "@walmartlabs/cookie-cutter-core": "^1.3.0", "@types/node-fetch": "2.5.7", - "node-fetch": "2.6.0" + "node-fetch": "2.6.1" }, "scripts": { "build": "tsc", diff --git a/packages/statsd/package.json b/packages/statsd/package.json index 8aaa9c77..bf4b0c84 100644 --- a/packages/statsd/package.json +++ b/packages/statsd/package.json @@ -1,6 +1,6 @@ { "name": "@walmartlabs/cookie-cutter-statsd", - "version": "1.2.0", + "version": "1.3.0", "license": "Apache-2.0", "main": "dist/index.js", "types": "dist/index.d.ts", @@ -13,13 +13,13 @@ "url": "https://github.com/walmartlabs/cookie-cutter/issues" }, "dependencies": { - "hot-shots": "7.4.2" + "hot-shots": "7.8.0" }, "peerDependencies": { - "@walmartlabs/cookie-cutter-core": "^1.2.0" + "@walmartlabs/cookie-cutter-core": "^1.3.0" }, "devDependencies": { - "@walmartlabs/cookie-cutter-core": "^1.2.0" + "@walmartlabs/cookie-cutter-core": "^1.3.0" }, "scripts": { "build": "tsc", diff --git a/packages/timer/package.json b/packages/timer/package.json index aa62a286..bcde1a0a 100644 --- a/packages/timer/package.json +++ b/packages/timer/package.json @@ -1,6 +1,6 @@ { "name": "@walmartlabs/cookie-cutter-timer", - "version": "1.2.0", + "version": "1.3.0", "license": "Apache-2.0", "main": "dist/index.js", "types": "dist/index.d.ts", @@ -16,10 +16,10 @@ "opentracing": "0.14.4" }, "peerDependencies": { - "@walmartlabs/cookie-cutter-core": "^1.2.0" + "@walmartlabs/cookie-cutter-core": "^1.3.0" }, "devDependencies": { - "@walmartlabs/cookie-cutter-core": "^1.2.0" + "@walmartlabs/cookie-cutter-core": "^1.3.0" }, "scripts": { "build": "tsc", diff --git a/packages/validatejs/package.json b/packages/validatejs/package.json index b8ba697b..2ce98d2e 100644 --- a/packages/validatejs/package.json +++ b/packages/validatejs/package.json @@ -1,6 +1,6 @@ { "name": "@walmartlabs/cookie-cutter-validatejs", - "version": "1.2.0", + "version": "1.3.0", "license": "Apache-2.0", "main": "dist/index.js", "types": "dist/index.d.ts", @@ -16,10 +16,10 @@ "validate.js": "0.13.1" }, "peerDependencies": { - "@walmartlabs/cookie-cutter-core": "^1.2.0" + "@walmartlabs/cookie-cutter-core": "^1.3.0" }, "devDependencies": { - "@walmartlabs/cookie-cutter-core": "^1.2.0" + "@walmartlabs/cookie-cutter-core": "^1.3.0" }, "scripts": { "build": "tsc", diff --git a/yarn.lock b/yarn.lock index 82327a2a..f55de03e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,21 +2,22 @@ # yarn lockfile v1 -"@azure/cosmos@3.6.3": - version "3.6.3" - resolved "https://registry.yarnpkg.com/@azure/cosmos/-/cosmos-3.6.3.tgz#bb53bde35fbf338160691d2b6a62f47b4a9a1cbb" - integrity sha512-JoCDxl0TnL6EHL4xD3KC9r2bMivK13q1jl7h69wd/YFLlt3aBTTCehtAX+y4alNSENpL53XdRdw/cna0mI2XDw== +"@azure/cosmos@3.9.1": + version "3.9.1" + resolved "https://registry.yarnpkg.com/@azure/cosmos/-/cosmos-3.9.1.tgz#4fc0790a965dc38806d6f85b6d91cfc79062338e" + integrity sha512-+XUNzgQdmfWJL3ofkBtpBfbE6s56DsRCg8HSE1cDEwHdxU40LO40YCaxNHnlNbj1cbAiBJH/65DCUybthGcjGA== dependencies: "@types/debug" "^4.1.4" debug "^4.1.1" fast-json-stable-stringify "^2.0.0" + jsbi "^3.1.3" node-abort-controller "^1.0.4" node-fetch "^2.6.0" os-name "^3.1.0" priorityqueuejs "^1.0.0" semaphore "^1.0.5" - tslib "^1.10.0" - uuid "^3.3.2" + tslib "^2.0.0" + uuid "^8.1.0" "@babel/code-frame@7.5.5": version "7.5.5" @@ -25,359 +26,390 @@ dependencies: "@babel/highlight" "^7.0.0" -"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.8.3.tgz#33e25903d7481181534e12ec0a25f16b6fcf419e" - integrity sha512-a9gxpmdXtZEInkCSHUJDLHZVBgb1QS0jhss4cPP93EW7s+uC5bikET2twEF3KV+7rDblJcmNvTR7VJejqd2C2g== +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.10.4.tgz#168da1a36e90da68ae8d49c0f1b48c7c6249213a" + integrity sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg== dependencies: - "@babel/highlight" "^7.8.3" + "@babel/highlight" "^7.10.4" -"@babel/compat-data@^7.9.6": - version "7.9.6" - resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.9.6.tgz#3f604c40e420131affe6f2c8052e9a275ae2049b" - integrity sha512-5QPTrNen2bm7RBc7dsOmcA5hbrS4O2Vhmk5XOL4zWW/zD/hV0iinpefDlkm+tBBy8kDtFaaeEvmAqt+nURAV2g== +"@babel/compat-data@^7.10.4", "@babel/compat-data@^7.11.0": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.11.0.tgz#e9f73efe09af1355b723a7f39b11bad637d7c99c" + integrity sha512-TPSvJfv73ng0pfnEOh17bYMPQbI95+nGWc71Ss4vZdRBHTDqmM9Z8ZV4rYz8Ks7sfzc95n30k6ODIq5UGnXcYQ== dependencies: - browserslist "^4.11.1" + browserslist "^4.12.0" invariant "^2.2.4" semver "^5.5.0" "@babel/core@^7.1.0", "@babel/core@^7.5.5", "@babel/core@^7.7.5": - version "7.9.6" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.9.6.tgz#d9aa1f580abf3b2286ef40b6904d390904c63376" - integrity sha512-nD3deLvbsApbHAHttzIssYqgb883yU/d9roe4RZymBCDaZryMJDbptVpEpeQuRh4BJ+SYI8le9YGxKvFEvl1Wg== - dependencies: - "@babel/code-frame" "^7.8.3" - "@babel/generator" "^7.9.6" - "@babel/helper-module-transforms" "^7.9.0" - "@babel/helpers" "^7.9.6" - "@babel/parser" "^7.9.6" - "@babel/template" "^7.8.6" - "@babel/traverse" "^7.9.6" - "@babel/types" "^7.9.6" + version "7.11.1" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.11.1.tgz#2c55b604e73a40dc21b0e52650b11c65cf276643" + integrity sha512-XqF7F6FWQdKGGWAzGELL+aCO1p+lRY5Tj5/tbT3St1G8NaH70jhhDIKknIZaDans0OQBG5wRAldROLHSt44BgQ== + dependencies: + "@babel/code-frame" "^7.10.4" + "@babel/generator" "^7.11.0" + "@babel/helper-module-transforms" "^7.11.0" + "@babel/helpers" "^7.10.4" + "@babel/parser" "^7.11.1" + "@babel/template" "^7.10.4" + "@babel/traverse" "^7.11.0" + "@babel/types" "^7.11.0" convert-source-map "^1.7.0" debug "^4.1.0" gensync "^1.0.0-beta.1" json5 "^2.1.2" - lodash "^4.17.13" + lodash "^4.17.19" resolve "^1.3.2" semver "^5.4.1" source-map "^0.5.0" -"@babel/generator@^7.9.6": - version "7.9.6" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.9.6.tgz#5408c82ac5de98cda0d77d8124e99fa1f2170a43" - integrity sha512-+htwWKJbH2bL72HRluF8zumBxzuX0ZZUFl3JLNyoUjM/Ho8wnVpPXM6aUz8cfKDqQ/h7zHqKt4xzJteUosckqQ== +"@babel/generator@^7.11.0": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.11.0.tgz#4b90c78d8c12825024568cbe83ee6c9af193585c" + integrity sha512-fEm3Uzw7Mc9Xi//qU20cBKatTfs2aOtKqmvy/Vm7RkJEGFQ4xc9myCfbXxqK//ZS8MR/ciOHw6meGASJuKmDfQ== dependencies: - "@babel/types" "^7.9.6" + "@babel/types" "^7.11.0" jsesc "^2.5.1" - lodash "^4.17.13" source-map "^0.5.0" -"@babel/helper-annotate-as-pure@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.8.3.tgz#60bc0bc657f63a0924ff9a4b4a0b24a13cf4deee" - integrity sha512-6o+mJrZBxOoEX77Ezv9zwW7WV8DdluouRKNY/IR5u/YTMuKHgugHOzYWlYvYLpLA9nPsQCAAASpCIbjI9Mv+Uw== +"@babel/helper-annotate-as-pure@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.10.4.tgz#5bf0d495a3f757ac3bda48b5bf3b3ba309c72ba3" + integrity sha512-XQlqKQP4vXFB7BN8fEEerrmYvHp3fK/rBkRFz9jaJbzK0B1DSfej9Kc7ZzE8Z/OnId1jpJdNAZ3BFQjWG68rcA== dependencies: - "@babel/types" "^7.8.3" + "@babel/types" "^7.10.4" -"@babel/helper-builder-binary-assignment-operator-visitor@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.8.3.tgz#c84097a427a061ac56a1c30ebf54b7b22d241503" - integrity sha512-5eFOm2SyFPK4Rh3XMMRDjN7lBH0orh3ss0g3rTYZnBQ+r6YPj7lgDyCvPphynHvUrobJmeMignBr6Acw9mAPlw== +"@babel/helper-builder-binary-assignment-operator-visitor@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.10.4.tgz#bb0b75f31bf98cbf9ff143c1ae578b87274ae1a3" + integrity sha512-L0zGlFrGWZK4PbT8AszSfLTM5sDU1+Az/En9VrdT8/LmEiJt4zXt+Jve9DCAnQcbqDhCI+29y/L93mrDzddCcg== dependencies: - "@babel/helper-explode-assignable-expression" "^7.8.3" - "@babel/types" "^7.8.3" + "@babel/helper-explode-assignable-expression" "^7.10.4" + "@babel/types" "^7.10.4" -"@babel/helper-builder-react-jsx-experimental@^7.9.0": - version "7.9.5" - resolved "https://registry.yarnpkg.com/@babel/helper-builder-react-jsx-experimental/-/helper-builder-react-jsx-experimental-7.9.5.tgz#0b4b3e04e6123f03b404ca4dfd6528fe6bb92fe3" - integrity sha512-HAagjAC93tk748jcXpZ7oYRZH485RCq/+yEv9SIWezHRPv9moZArTnkUNciUNzvwHUABmiWKlcxJvMcu59UwTg== +"@babel/helper-builder-react-jsx-experimental@^7.10.4": + version "7.10.5" + resolved "https://registry.yarnpkg.com/@babel/helper-builder-react-jsx-experimental/-/helper-builder-react-jsx-experimental-7.10.5.tgz#f35e956a19955ff08c1258e44a515a6d6248646b" + integrity sha512-Buewnx6M4ttG+NLkKyt7baQn7ScC/Td+e99G914fRU8fGIUivDDgVIQeDHFa5e4CRSJQt58WpNHhsAZgtzVhsg== dependencies: - "@babel/helper-annotate-as-pure" "^7.8.3" - "@babel/helper-module-imports" "^7.8.3" - "@babel/types" "^7.9.5" + "@babel/helper-annotate-as-pure" "^7.10.4" + "@babel/helper-module-imports" "^7.10.4" + "@babel/types" "^7.10.5" -"@babel/helper-builder-react-jsx@^7.9.0": - version "7.9.0" - resolved "https://registry.yarnpkg.com/@babel/helper-builder-react-jsx/-/helper-builder-react-jsx-7.9.0.tgz#16bf391990b57732700a3278d4d9a81231ea8d32" - integrity sha512-weiIo4gaoGgnhff54GQ3P5wsUQmnSwpkvU0r6ZHq6TzoSzKy4JxHEgnxNytaKbov2a9z/CVNyzliuCOUPEX3Jw== +"@babel/helper-builder-react-jsx@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-builder-react-jsx/-/helper-builder-react-jsx-7.10.4.tgz#8095cddbff858e6fa9c326daee54a2f2732c1d5d" + integrity sha512-5nPcIZ7+KKDxT1427oBivl9V9YTal7qk0diccnh7RrcgrT/pGFOjgGw1dgryyx1GvHEpXVfoDF6Ak3rTiWh8Rg== dependencies: - "@babel/helper-annotate-as-pure" "^7.8.3" - "@babel/types" "^7.9.0" + "@babel/helper-annotate-as-pure" "^7.10.4" + "@babel/types" "^7.10.4" -"@babel/helper-compilation-targets@^7.9.6": - version "7.9.6" - resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.9.6.tgz#1e05b7ccc9d38d2f8b40b458b380a04dcfadd38a" - integrity sha512-x2Nvu0igO0ejXzx09B/1fGBxY9NXQlBW2kZsSxCJft+KHN8t9XWzIvFxtPHnBOAXpVsdxZKZFbRUC8TsNKajMw== +"@babel/helper-compilation-targets@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.10.4.tgz#804ae8e3f04376607cc791b9d47d540276332bd2" + integrity sha512-a3rYhlsGV0UHNDvrtOXBg8/OpfV0OKTkxKPzIplS1zpx7CygDcWWxckxZeDd3gzPzC4kUT0A4nVFDK0wGMh4MQ== dependencies: - "@babel/compat-data" "^7.9.6" - browserslist "^4.11.1" + "@babel/compat-data" "^7.10.4" + browserslist "^4.12.0" invariant "^2.2.4" levenary "^1.1.1" semver "^5.5.0" -"@babel/helper-create-class-features-plugin@^7.8.3": - version "7.9.6" - resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.9.6.tgz#965c8b0a9f051801fd9d3b372ca0ccf200a90897" - integrity sha512-6N9IeuyHvMBRyjNYOMJHrhwtu4WJMrYf8hVbEHD3pbbbmNOk1kmXSQs7bA4dYDUaIx4ZEzdnvo6NwC3WHd/Qow== - dependencies: - "@babel/helper-function-name" "^7.9.5" - "@babel/helper-member-expression-to-functions" "^7.8.3" - "@babel/helper-optimise-call-expression" "^7.8.3" - "@babel/helper-plugin-utils" "^7.8.3" - "@babel/helper-replace-supers" "^7.9.6" - "@babel/helper-split-export-declaration" "^7.8.3" - -"@babel/helper-create-regexp-features-plugin@^7.8.3", "@babel/helper-create-regexp-features-plugin@^7.8.8": - version "7.8.8" - resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.8.8.tgz#5d84180b588f560b7864efaeea89243e58312087" - integrity sha512-LYVPdwkrQEiX9+1R29Ld/wTrmQu1SSKYnuOk3g0CkcZMA1p0gsNxJFj/3gBdaJ7Cg0Fnek5z0DsMULePP7Lrqg== - dependencies: - "@babel/helper-annotate-as-pure" "^7.8.3" - "@babel/helper-regex" "^7.8.3" +"@babel/helper-create-class-features-plugin@^7.10.4": + version "7.10.5" + resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.10.5.tgz#9f61446ba80e8240b0a5c85c6fdac8459d6f259d" + integrity sha512-0nkdeijB7VlZoLT3r/mY3bUkw3T8WG/hNw+FATs/6+pG2039IJWjTYL0VTISqsNHMUTEnwbVnc89WIJX9Qed0A== + dependencies: + "@babel/helper-function-name" "^7.10.4" + "@babel/helper-member-expression-to-functions" "^7.10.5" + "@babel/helper-optimise-call-expression" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-replace-supers" "^7.10.4" + "@babel/helper-split-export-declaration" "^7.10.4" + +"@babel/helper-create-regexp-features-plugin@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.10.4.tgz#fdd60d88524659a0b6959c0579925e425714f3b8" + integrity sha512-2/hu58IEPKeoLF45DBwx3XFqsbCXmkdAay4spVr2x0jYgRxrSNp+ePwvSsy9g6YSaNDcKIQVPXk1Ov8S2edk2g== + dependencies: + "@babel/helper-annotate-as-pure" "^7.10.4" + "@babel/helper-regex" "^7.10.4" regexpu-core "^4.7.0" -"@babel/helper-define-map@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/helper-define-map/-/helper-define-map-7.8.3.tgz#a0655cad5451c3760b726eba875f1cd8faa02c15" - integrity sha512-PoeBYtxoZGtct3md6xZOCWPcKuMuk3IHhgxsRRNtnNShebf4C8YonTSblsK4tvDbm+eJAw2HAPOfCr+Q/YRG/g== - dependencies: - "@babel/helper-function-name" "^7.8.3" - "@babel/types" "^7.8.3" - lodash "^4.17.13" - -"@babel/helper-explode-assignable-expression@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.8.3.tgz#a728dc5b4e89e30fc2dfc7d04fa28a930653f982" - integrity sha512-N+8eW86/Kj147bO9G2uclsg5pwfs/fqqY5rwgIL7eTBklgXjcOJ3btzS5iM6AitJcftnY7pm2lGsrJVYLGjzIw== - dependencies: - "@babel/traverse" "^7.8.3" - "@babel/types" "^7.8.3" - -"@babel/helper-function-name@^7.8.3", "@babel/helper-function-name@^7.9.5": - version "7.9.5" - resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.9.5.tgz#2b53820d35275120e1874a82e5aabe1376920a5c" - integrity sha512-JVcQZeXM59Cd1qanDUxv9fgJpt3NeKUaqBqUEvfmQ+BCOKq2xUgaWZW2hr0dkbyJgezYuplEoh5knmrnS68efw== - dependencies: - "@babel/helper-get-function-arity" "^7.8.3" - "@babel/template" "^7.8.3" - "@babel/types" "^7.9.5" - -"@babel/helper-get-function-arity@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.8.3.tgz#b894b947bd004381ce63ea1db9f08547e920abd5" - integrity sha512-FVDR+Gd9iLjUMY1fzE2SR0IuaJToR4RkCDARVfsBBPSP53GEqSFjD8gNyxg246VUyc/ALRxFaAK8rVG7UT7xRA== - dependencies: - "@babel/types" "^7.8.3" - -"@babel/helper-hoist-variables@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.8.3.tgz#1dbe9b6b55d78c9b4183fc8cdc6e30ceb83b7134" - integrity sha512-ky1JLOjcDUtSc+xkt0xhYff7Z6ILTAHKmZLHPxAhOP0Nd77O+3nCsd6uSVYur6nJnCI029CrNbYlc0LoPfAPQg== - dependencies: - "@babel/types" "^7.8.3" - -"@babel/helper-member-expression-to-functions@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.8.3.tgz#659b710498ea6c1d9907e0c73f206eee7dadc24c" - integrity sha512-fO4Egq88utkQFjbPrSHGmGLFqmrshs11d46WI+WZDESt7Wu7wN2G2Iu+NMMZJFDOVRHAMIkB5SNh30NtwCA7RA== - dependencies: - "@babel/types" "^7.8.3" - -"@babel/helper-module-imports@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.8.3.tgz#7fe39589b39c016331b6b8c3f441e8f0b1419498" - integrity sha512-R0Bx3jippsbAEtzkpZ/6FIiuzOURPcMjHp+Z6xPe6DtApDJx+w7UYyOLanZqO8+wKR9G10s/FmHXvxaMd9s6Kg== - dependencies: - "@babel/types" "^7.8.3" - -"@babel/helper-module-transforms@^7.9.0": - version "7.9.0" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.9.0.tgz#43b34dfe15961918707d247327431388e9fe96e5" - integrity sha512-0FvKyu0gpPfIQ8EkxlrAydOWROdHpBmiCiRwLkUiBGhCUPRRbVD2/tm3sFr/c/GWFrQ/ffutGUAnx7V0FzT2wA== - dependencies: - "@babel/helper-module-imports" "^7.8.3" - "@babel/helper-replace-supers" "^7.8.6" - "@babel/helper-simple-access" "^7.8.3" - "@babel/helper-split-export-declaration" "^7.8.3" - "@babel/template" "^7.8.6" - "@babel/types" "^7.9.0" - lodash "^4.17.13" - -"@babel/helper-optimise-call-expression@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.8.3.tgz#7ed071813d09c75298ef4f208956006b6111ecb9" - integrity sha512-Kag20n86cbO2AvHca6EJsvqAd82gc6VMGule4HwebwMlwkpXuVqrNRj6CkCV2sKxgi9MyAUnZVnZ6lJ1/vKhHQ== - dependencies: - "@babel/types" "^7.8.3" - -"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.8.3.tgz#9ea293be19babc0f52ff8ca88b34c3611b208670" - integrity sha512-j+fq49Xds2smCUNYmEHF9kGNkhbet6yVIBp4e6oeQpH1RUs/Ir06xUKzDjDkGcaaokPiTNs2JBWHjaE4csUkZQ== - -"@babel/helper-regex@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/helper-regex/-/helper-regex-7.8.3.tgz#139772607d51b93f23effe72105b319d2a4c6965" - integrity sha512-BWt0QtYv/cg/NecOAZMdcn/waj/5P26DR4mVLXfFtDokSR6fyuG0Pj+e2FqtSME+MqED1khnSMulkmGl8qWiUQ== - dependencies: - lodash "^4.17.13" - -"@babel/helper-remap-async-to-generator@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.8.3.tgz#273c600d8b9bf5006142c1e35887d555c12edd86" - integrity sha512-kgwDmw4fCg7AVgS4DukQR/roGp+jP+XluJE5hsRZwxCYGg+Rv9wSGErDWhlI90FODdYfd4xG4AQRiMDjjN0GzA== - dependencies: - "@babel/helper-annotate-as-pure" "^7.8.3" - "@babel/helper-wrap-function" "^7.8.3" - "@babel/template" "^7.8.3" - "@babel/traverse" "^7.8.3" - "@babel/types" "^7.8.3" - -"@babel/helper-replace-supers@^7.8.3", "@babel/helper-replace-supers@^7.8.6", "@babel/helper-replace-supers@^7.9.6": - version "7.9.6" - resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.9.6.tgz#03149d7e6a5586ab6764996cd31d6981a17e1444" - integrity sha512-qX+chbxkbArLyCImk3bWV+jB5gTNU/rsze+JlcF6Nf8tVTigPJSI1o1oBow/9Resa1yehUO9lIipsmu9oG4RzA== - dependencies: - "@babel/helper-member-expression-to-functions" "^7.8.3" - "@babel/helper-optimise-call-expression" "^7.8.3" - "@babel/traverse" "^7.9.6" - "@babel/types" "^7.9.6" - -"@babel/helper-simple-access@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.8.3.tgz#7f8109928b4dab4654076986af575231deb639ae" - integrity sha512-VNGUDjx5cCWg4vvCTR8qQ7YJYZ+HBjxOgXEl7ounz+4Sn7+LMD3CFrCTEU6/qXKbA2nKg21CwhhBzO0RpRbdCw== - dependencies: - "@babel/template" "^7.8.3" - "@babel/types" "^7.8.3" - -"@babel/helper-split-export-declaration@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.8.3.tgz#31a9f30070f91368a7182cf05f831781065fc7a9" - integrity sha512-3x3yOeyBhW851hroze7ElzdkeRXQYQbFIb7gLK1WQYsw2GWDay5gAJNw1sWJ0VFP6z5J1whqeXH/WCdCjZv6dA== - dependencies: - "@babel/types" "^7.8.3" - -"@babel/helper-validator-identifier@^7.9.0", "@babel/helper-validator-identifier@^7.9.5": - version "7.9.5" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.9.5.tgz#90977a8e6fbf6b431a7dc31752eee233bf052d80" - integrity sha512-/8arLKUFq882w4tWGj9JYzRpAlZgiWUJ+dtteNTDqrRBz9Iguck9Rn3ykuBDoUwh2TO4tSAJlrxDUOXWklJe4g== - -"@babel/helper-wrap-function@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.8.3.tgz#9dbdb2bb55ef14aaa01fe8c99b629bd5352d8610" - integrity sha512-LACJrbUET9cQDzb6kG7EeD7+7doC3JNvUgTEQOx2qaO1fKlzE/Bf05qs9w1oXQMmXlPO65lC3Tq9S6gZpTErEQ== - dependencies: - "@babel/helper-function-name" "^7.8.3" - "@babel/template" "^7.8.3" - "@babel/traverse" "^7.8.3" - "@babel/types" "^7.8.3" - -"@babel/helpers@^7.9.6": - version "7.9.6" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.9.6.tgz#092c774743471d0bb6c7de3ad465ab3d3486d580" - integrity sha512-tI4bUbldloLcHWoRUMAj4g1bF313M/o6fBKhIsb3QnGVPwRm9JsNf/gqMkQ7zjqReABiffPV6RWj7hEglID5Iw== - dependencies: - "@babel/template" "^7.8.3" - "@babel/traverse" "^7.9.6" - "@babel/types" "^7.9.6" - -"@babel/highlight@^7.0.0", "@babel/highlight@^7.8.3": - version "7.9.0" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.9.0.tgz#4e9b45ccb82b79607271b2979ad82c7b68163079" - integrity sha512-lJZPilxX7Op3Nv/2cvFdnlepPXDxi29wxteT57Q965oc5R9v86ztx0jfxVrTcBk8C2kcPkkDa2Z4T3ZsPPVWsQ== +"@babel/helper-define-map@^7.10.4": + version "7.10.5" + resolved "https://registry.yarnpkg.com/@babel/helper-define-map/-/helper-define-map-7.10.5.tgz#b53c10db78a640800152692b13393147acb9bb30" + integrity sha512-fMw4kgFB720aQFXSVaXr79pjjcW5puTCM16+rECJ/plGS+zByelE8l9nCpV1GibxTnFVmUuYG9U8wYfQHdzOEQ== + dependencies: + "@babel/helper-function-name" "^7.10.4" + "@babel/types" "^7.10.5" + lodash "^4.17.19" + +"@babel/helper-explode-assignable-expression@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.10.4.tgz#40a1cd917bff1288f699a94a75b37a1a2dbd8c7c" + integrity sha512-4K71RyRQNPRrR85sr5QY4X3VwG4wtVoXZB9+L3r1Gp38DhELyHCtovqydRi7c1Ovb17eRGiQ/FD5s8JdU0Uy5A== + dependencies: + "@babel/traverse" "^7.10.4" + "@babel/types" "^7.10.4" + +"@babel/helper-function-name@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.10.4.tgz#d2d3b20c59ad8c47112fa7d2a94bc09d5ef82f1a" + integrity sha512-YdaSyz1n8gY44EmN7x44zBn9zQ1Ry2Y+3GTA+3vH6Mizke1Vw0aWDM66FOYEPw8//qKkmqOckrGgTYa+6sceqQ== dependencies: - "@babel/helper-validator-identifier" "^7.9.0" + "@babel/helper-get-function-arity" "^7.10.4" + "@babel/template" "^7.10.4" + "@babel/types" "^7.10.4" + +"@babel/helper-get-function-arity@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.4.tgz#98c1cbea0e2332f33f9a4661b8ce1505b2c19ba2" + integrity sha512-EkN3YDB+SRDgiIUnNgcmiD361ti+AVbL3f3Henf6dqqUyr5dMsorno0lJWJuLhDhkI5sYEpgj6y9kB8AOU1I2A== + dependencies: + "@babel/types" "^7.10.4" + +"@babel/helper-hoist-variables@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.10.4.tgz#d49b001d1d5a68ca5e6604dda01a6297f7c9381e" + integrity sha512-wljroF5PgCk2juF69kanHVs6vrLwIPNp6DLD+Lrl3hoQ3PpPPikaDRNFA+0t81NOoMt2DL6WW/mdU8k4k6ZzuA== + dependencies: + "@babel/types" "^7.10.4" + +"@babel/helper-member-expression-to-functions@^7.10.4", "@babel/helper-member-expression-to-functions@^7.10.5": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.11.0.tgz#ae69c83d84ee82f4b42f96e2a09410935a8f26df" + integrity sha512-JbFlKHFntRV5qKw3YC0CvQnDZ4XMwgzzBbld7Ly4Mj4cbFy3KywcR8NtNctRToMWJOVvLINJv525Gd6wwVEx/Q== + dependencies: + "@babel/types" "^7.11.0" + +"@babel/helper-module-imports@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.10.4.tgz#4c5c54be04bd31670a7382797d75b9fa2e5b5620" + integrity sha512-nEQJHqYavI217oD9+s5MUBzk6x1IlvoS9WTPfgG43CbMEeStE0v+r+TucWdx8KFGowPGvyOkDT9+7DHedIDnVw== + dependencies: + "@babel/types" "^7.10.4" + +"@babel/helper-module-transforms@^7.10.4", "@babel/helper-module-transforms@^7.10.5", "@babel/helper-module-transforms@^7.11.0": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.11.0.tgz#b16f250229e47211abdd84b34b64737c2ab2d359" + integrity sha512-02EVu8COMuTRO1TAzdMtpBPbe6aQ1w/8fePD2YgQmxZU4gpNWaL9gK3Jp7dxlkUlUCJOTaSeA+Hrm1BRQwqIhg== + dependencies: + "@babel/helper-module-imports" "^7.10.4" + "@babel/helper-replace-supers" "^7.10.4" + "@babel/helper-simple-access" "^7.10.4" + "@babel/helper-split-export-declaration" "^7.11.0" + "@babel/template" "^7.10.4" + "@babel/types" "^7.11.0" + lodash "^4.17.19" + +"@babel/helper-optimise-call-expression@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.10.4.tgz#50dc96413d594f995a77905905b05893cd779673" + integrity sha512-n3UGKY4VXwXThEiKrgRAoVPBMqeoPgHVqiHZOanAJCG9nQUL2pLRQirUzl0ioKclHGpGqRgIOkgcIJaIWLpygg== + dependencies: + "@babel/types" "^7.10.4" + +"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz#2f75a831269d4f677de49986dff59927533cf375" + integrity sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg== + +"@babel/helper-regex@^7.10.4": + version "7.10.5" + resolved "https://registry.yarnpkg.com/@babel/helper-regex/-/helper-regex-7.10.5.tgz#32dfbb79899073c415557053a19bd055aae50ae0" + integrity sha512-68kdUAzDrljqBrio7DYAEgCoJHxppJOERHOgOrDN7WjOzP0ZQ1LsSDRXcemzVZaLvjaJsJEESb6qt+znNuENDg== + dependencies: + lodash "^4.17.19" + +"@babel/helper-remap-async-to-generator@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.10.4.tgz#fce8bea4e9690bbe923056ded21e54b4e8b68ed5" + integrity sha512-86Lsr6NNw3qTNl+TBcF1oRZMaVzJtbWTyTko+CQL/tvNvcGYEFKbLXDPxtW0HKk3McNOk4KzY55itGWCAGK5tg== + dependencies: + "@babel/helper-annotate-as-pure" "^7.10.4" + "@babel/helper-wrap-function" "^7.10.4" + "@babel/template" "^7.10.4" + "@babel/traverse" "^7.10.4" + "@babel/types" "^7.10.4" + +"@babel/helper-replace-supers@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.10.4.tgz#d585cd9388ea06e6031e4cd44b6713cbead9e6cf" + integrity sha512-sPxZfFXocEymYTdVK1UNmFPBN+Hv5mJkLPsYWwGBxZAxaWfFu+xqp7b6qWD0yjNuNL2VKc6L5M18tOXUP7NU0A== + dependencies: + "@babel/helper-member-expression-to-functions" "^7.10.4" + "@babel/helper-optimise-call-expression" "^7.10.4" + "@babel/traverse" "^7.10.4" + "@babel/types" "^7.10.4" + +"@babel/helper-simple-access@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.10.4.tgz#0f5ccda2945277a2a7a2d3a821e15395edcf3461" + integrity sha512-0fMy72ej/VEvF8ULmX6yb5MtHG4uH4Dbd6I/aHDb/JVg0bbivwt9Wg+h3uMvX+QSFtwr5MeItvazbrc4jtRAXw== + dependencies: + "@babel/template" "^7.10.4" + "@babel/types" "^7.10.4" + +"@babel/helper-skip-transparent-expression-wrappers@^7.11.0": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.11.0.tgz#eec162f112c2f58d3af0af125e3bb57665146729" + integrity sha512-0XIdiQln4Elglgjbwo9wuJpL/K7AGCY26kmEt0+pRP0TAj4jjyNq1MjoRvikrTVqKcx4Gysxt4cXvVFXP/JO2Q== + dependencies: + "@babel/types" "^7.11.0" + +"@babel/helper-split-export-declaration@^7.10.4", "@babel/helper-split-export-declaration@^7.11.0": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.11.0.tgz#f8a491244acf6a676158ac42072911ba83ad099f" + integrity sha512-74Vejvp6mHkGE+m+k5vHY93FX2cAtrw1zXrZXRlG4l410Nm9PxfEiVTn1PjDPV5SnmieiueY4AFg2xqhNFuuZg== + dependencies: + "@babel/types" "^7.11.0" + +"@babel/helper-validator-identifier@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz#a78c7a7251e01f616512d31b10adcf52ada5e0d2" + integrity sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw== + +"@babel/helper-wrap-function@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.10.4.tgz#8a6f701eab0ff39f765b5a1cfef409990e624b87" + integrity sha512-6py45WvEF0MhiLrdxtRjKjufwLL1/ob2qDJgg5JgNdojBAZSAKnAjkyOCNug6n+OBl4VW76XjvgSFTdaMcW0Ug== + dependencies: + "@babel/helper-function-name" "^7.10.4" + "@babel/template" "^7.10.4" + "@babel/traverse" "^7.10.4" + "@babel/types" "^7.10.4" + +"@babel/helpers@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.10.4.tgz#2abeb0d721aff7c0a97376b9e1f6f65d7a475044" + integrity sha512-L2gX/XeUONeEbI78dXSrJzGdz4GQ+ZTA/aazfUsFaWjSe95kiCuOZ5HsXvkiw3iwF+mFHSRUfJU8t6YavocdXA== + dependencies: + "@babel/template" "^7.10.4" + "@babel/traverse" "^7.10.4" + "@babel/types" "^7.10.4" + +"@babel/highlight@^7.0.0", "@babel/highlight@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.10.4.tgz#7d1bdfd65753538fabe6c38596cdb76d9ac60143" + integrity sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA== + dependencies: + "@babel/helper-validator-identifier" "^7.10.4" chalk "^2.0.0" js-tokens "^4.0.0" -"@babel/parser@^7.1.0", "@babel/parser@^7.8.6", "@babel/parser@^7.9.6": - version "7.9.6" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.9.6.tgz#3b1bbb30dabe600cd72db58720998376ff653bc7" - integrity sha512-AoeIEJn8vt+d/6+PXDRPaksYhnlbMIiejioBZvvMQsOjW/JYK6k/0dKnvvP3EhK5GfMBWDPtrxRtegWdAcdq9Q== +"@babel/parser@^7.1.0", "@babel/parser@^7.10.4", "@babel/parser@^7.11.0", "@babel/parser@^7.11.1": + version "7.11.3" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.11.3.tgz#9e1eae46738bcd08e23e867bab43e7b95299a8f9" + integrity sha512-REo8xv7+sDxkKvoxEywIdsNFiZLybwdI7hcT5uEPyQrSMB4YQ973BfC9OOrD/81MaIjh6UxdulIQXkjmiH3PcA== -"@babel/plugin-proposal-async-generator-functions@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.8.3.tgz#bad329c670b382589721b27540c7d288601c6e6f" - integrity sha512-NZ9zLv848JsV3hs8ryEh7Uaz/0KsmPLqv0+PdkDJL1cJy0K4kOCFa8zc1E3mp+RHPQcpdfb/6GovEsW4VDrOMw== +"@babel/plugin-proposal-async-generator-functions@^7.10.4": + version "7.10.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.10.5.tgz#3491cabf2f7c179ab820606cec27fed15e0e8558" + integrity sha512-cNMCVezQbrRGvXJwm9fu/1sJj9bHdGAgKodZdLqOQIpfoH3raqmRPBM17+lh7CzhiKRRBrGtZL9WcjxSoGYUSg== dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - "@babel/helper-remap-async-to-generator" "^7.8.3" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-remap-async-to-generator" "^7.10.4" "@babel/plugin-syntax-async-generators" "^7.8.0" -"@babel/plugin-proposal-class-properties@^7.5.5": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.8.3.tgz#5e06654af5cd04b608915aada9b2a6788004464e" - integrity sha512-EqFhbo7IosdgPgZggHaNObkmO1kNUe3slaKu54d5OWvy+p9QIKOzK1GAEpAIsZtWVtPXUHSMcT4smvDrCfY4AA== +"@babel/plugin-proposal-class-properties@^7.10.4", "@babel/plugin-proposal-class-properties@^7.5.5": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.10.4.tgz#a33bf632da390a59c7a8c570045d1115cd778807" + integrity sha512-vhwkEROxzcHGNu2mzUC0OFFNXdZ4M23ib8aRRcJSsW8BZK9pQMD7QB7csl97NBbgGZO7ZyHUyKDnxzOaP4IrCg== dependencies: - "@babel/helper-create-class-features-plugin" "^7.8.3" - "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-create-class-features-plugin" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-proposal-dynamic-import@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.8.3.tgz#38c4fe555744826e97e2ae930b0fb4cc07e66054" - integrity sha512-NyaBbyLFXFLT9FP+zk0kYlUlA8XtCUbehs67F0nnEg7KICgMc2mNkIeu9TYhKzyXMkrapZFwAhXLdnt4IYHy1w== +"@babel/plugin-proposal-dynamic-import@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.10.4.tgz#ba57a26cb98b37741e9d5bca1b8b0ddf8291f17e" + integrity sha512-up6oID1LeidOOASNXgv/CFbgBqTuKJ0cJjz6An5tWD+NVBNlp3VNSBxv2ZdU7SYl3NxJC7agAQDApZusV6uFwQ== dependencies: - "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-dynamic-import" "^7.8.0" -"@babel/plugin-proposal-json-strings@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.8.3.tgz#da5216b238a98b58a1e05d6852104b10f9a70d6b" - integrity sha512-KGhQNZ3TVCQG/MjRbAUwuH+14y9q0tpxs1nWWs3pbSleRdDro9SAMMDyye8HhY1gqZ7/NqIc8SKhya0wRDgP1Q== +"@babel/plugin-proposal-export-namespace-from@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.10.4.tgz#570d883b91031637b3e2958eea3c438e62c05f54" + integrity sha512-aNdf0LY6/3WXkhh0Fdb6Zk9j1NMD8ovj3F6r0+3j837Pn1S1PdNtcwJ5EG9WkVPNHPxyJDaxMaAOVq4eki0qbg== dependencies: - "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-export-namespace-from" "^7.8.3" + +"@babel/plugin-proposal-json-strings@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.10.4.tgz#593e59c63528160233bd321b1aebe0820c2341db" + integrity sha512-fCL7QF0Jo83uy1K0P2YXrfX11tj3lkpN7l4dMv9Y9VkowkhkQDwFHFd8IiwyK5MZjE8UpbgokkgtcReH88Abaw== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-json-strings" "^7.8.0" -"@babel/plugin-proposal-nullish-coalescing-operator@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.8.3.tgz#e4572253fdeed65cddeecfdab3f928afeb2fd5d2" - integrity sha512-TS9MlfzXpXKt6YYomudb/KU7nQI6/xnapG6in1uZxoxDghuSMZsPb6D2fyUwNYSAp4l1iR7QtFOjkqcRYcUsfw== +"@babel/plugin-proposal-logical-assignment-operators@^7.11.0": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.11.0.tgz#9f80e482c03083c87125dee10026b58527ea20c8" + integrity sha512-/f8p4z+Auz0Uaf+i8Ekf1iM7wUNLcViFUGiPxKeXvxTSl63B875YPiVdUDdem7hREcI0E0kSpEhS8tF5RphK7Q== dependencies: - "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" + +"@babel/plugin-proposal-nullish-coalescing-operator@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.10.4.tgz#02a7e961fc32e6d5b2db0649e01bf80ddee7e04a" + integrity sha512-wq5n1M3ZUlHl9sqT2ok1T2/MTt6AXE0e1Lz4WzWBr95LsAZ5qDXe4KnFuauYyEyLiohvXFMdbsOTMyLZs91Zlw== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.0" -"@babel/plugin-proposal-numeric-separator@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.8.3.tgz#5d6769409699ec9b3b68684cd8116cedff93bad8" - integrity sha512-jWioO1s6R/R+wEHizfaScNsAx+xKgwTLNXSh7tTC4Usj3ItsPEhYkEpU4h+lpnBwq7NBVOJXfO6cRFYcX69JUQ== +"@babel/plugin-proposal-numeric-separator@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.10.4.tgz#ce1590ff0a65ad12970a609d78855e9a4c1aef06" + integrity sha512-73/G7QoRoeNkLZFxsoCCvlg4ezE4eM+57PnOqgaPOozd5myfj7p0muD1mRVJvbUWbOzD+q3No2bWbaKy+DJ8DA== dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - "@babel/plugin-syntax-numeric-separator" "^7.8.3" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-numeric-separator" "^7.10.4" -"@babel/plugin-proposal-object-rest-spread@^7.5.5", "@babel/plugin-proposal-object-rest-spread@^7.9.6": - version "7.9.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.9.6.tgz#7a093586fcb18b08266eb1a7177da671ac575b63" - integrity sha512-Ga6/fhGqA9Hj+y6whNpPv8psyaK5xzrQwSPsGPloVkvmH+PqW1ixdnfJ9uIO06OjQNYol3PMnfmJ8vfZtkzF+A== +"@babel/plugin-proposal-object-rest-spread@^7.11.0", "@babel/plugin-proposal-object-rest-spread@^7.5.5": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.11.0.tgz#bd81f95a1f746760ea43b6c2d3d62b11790ad0af" + integrity sha512-wzch41N4yztwoRw0ak+37wxwJM2oiIiy6huGCoqkvSTA9acYWcPfn9Y4aJqmFFJ70KTJUu29f3DQ43uJ9HXzEA== dependencies: - "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-object-rest-spread" "^7.8.0" - "@babel/plugin-transform-parameters" "^7.9.5" + "@babel/plugin-transform-parameters" "^7.10.4" -"@babel/plugin-proposal-optional-catch-binding@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.8.3.tgz#9dee96ab1650eed88646ae9734ca167ac4a9c5c9" - integrity sha512-0gkX7J7E+AtAw9fcwlVQj8peP61qhdg/89D5swOkjYbkboA2CVckn3kiyum1DE0wskGb7KJJxBdyEBApDLLVdw== +"@babel/plugin-proposal-optional-catch-binding@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.10.4.tgz#31c938309d24a78a49d68fdabffaa863758554dd" + integrity sha512-LflT6nPh+GK2MnFiKDyLiqSqVHkQnVf7hdoAvyTnnKj9xB3docGRsdPuxp6qqqW19ifK3xgc9U5/FwrSaCNX5g== dependencies: - "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-optional-catch-binding" "^7.8.0" -"@babel/plugin-proposal-optional-chaining@^7.9.0": - version "7.9.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.9.0.tgz#31db16b154c39d6b8a645292472b98394c292a58" - integrity sha512-NDn5tu3tcv4W30jNhmc2hyD5c56G6cXx4TesJubhxrJeCvuuMpttxr0OnNCqbZGhFjLrg+NIhxxC+BK5F6yS3w== +"@babel/plugin-proposal-optional-chaining@^7.11.0": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.11.0.tgz#de5866d0646f6afdaab8a566382fe3a221755076" + integrity sha512-v9fZIu3Y8562RRwhm1BbMRxtqZNFmFA2EG+pT2diuU8PT3H6T/KXoZ54KgYisfOFZHV6PfvAiBIZ9Rcz+/JCxA== dependencies: - "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-skip-transparent-expression-wrappers" "^7.11.0" "@babel/plugin-syntax-optional-chaining" "^7.8.0" -"@babel/plugin-proposal-unicode-property-regex@^7.4.4", "@babel/plugin-proposal-unicode-property-regex@^7.8.3": - version "7.8.8" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.8.8.tgz#ee3a95e90cdc04fe8cd92ec3279fa017d68a0d1d" - integrity sha512-EVhjVsMpbhLw9ZfHWSx2iy13Q8Z/eg8e8ccVWt23sWQK5l1UdkoLJPN5w69UA4uITGBnEZD2JOe4QOHycYKv8A== +"@babel/plugin-proposal-private-methods@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.10.4.tgz#b160d972b8fdba5c7d111a145fc8c421fc2a6909" + integrity sha512-wh5GJleuI8k3emgTg5KkJK6kHNsGEr0uBTDBuQUBJwckk9xs1ez79ioheEVVxMLyPscB0LfkbVHslQqIzWV6Bw== dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.8.8" - "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-create-class-features-plugin" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-proposal-unicode-property-regex@^7.10.4", "@babel/plugin-proposal-unicode-property-regex@^7.4.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.10.4.tgz#4483cda53041ce3413b7fe2f00022665ddfaa75d" + integrity sha512-H+3fOgPnEXFL9zGYtKQe4IDOPKYlZdF1kqFDQRRb8PK4B8af1vAGK04tF5iQAAsui+mHNBQSAtd2/ndEDe9wuA== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-async-generators@^7.8.0", "@babel/plugin-syntax-async-generators@^7.8.4": version "7.8.4" @@ -393,12 +425,12 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.0" -"@babel/plugin-syntax-class-properties@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.8.3.tgz#6cb933a8872c8d359bfde69bbeaae5162fd1e8f7" - integrity sha512-UcAyQWg2bAN647Q+O811tG9MrJ38Z10jjhQdKNAL8fsyPzE3cCN/uT+f55cFVY4aGO4jqJAvmqsuY3GQDwAoXg== +"@babel/plugin-syntax-class-properties@^7.10.4", "@babel/plugin-syntax-class-properties@^7.8.3": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.10.4.tgz#6644e6a0baa55a61f9e3231f6c9eeb6ee46c124c" + integrity sha512-GCSBF7iUle6rNugfURwNmCGG3Z/2+opxAMLs1nND4bhEG5PuxTIggDBoeYYSujAlLtsupzOHYJQgPS3pivwXIA== dependencies: - "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-dynamic-import@^7.8.0": version "7.8.3" @@ -407,6 +439,20 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.0" +"@babel/plugin-syntax-export-namespace-from@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz#028964a9ba80dbc094c915c487ad7c4e7a66465a" + integrity sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-syntax-import-meta@^7.8.3": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz#ee601348c370fa334d2207be158777496521fd51" + integrity sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-json-strings@^7.8.0", "@babel/plugin-syntax-json-strings@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz#01ca21b668cd8218c9e640cb6dd88c5412b2c96a" @@ -414,19 +460,19 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.0" -"@babel/plugin-syntax-jsx@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.8.3.tgz#521b06c83c40480f1e58b4fd33b92eceb1d6ea94" - integrity sha512-WxdW9xyLgBdefoo0Ynn3MRSkhe5tFVxxKNVdnZSh318WrG2e2jH+E9wd/++JsqcLJZPfz87njQJ8j2Upjm0M0A== +"@babel/plugin-syntax-jsx@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.10.4.tgz#39abaae3cbf710c4373d8429484e6ba21340166c" + integrity sha512-KCg9mio9jwiARCB7WAcQ7Y1q+qicILjoK8LP/VkPkEKaf5dkaZZK1EcTe91a3JJlZ3qy6L5s9X52boEYi8DM9g== dependencies: - "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-syntax-logical-assignment-operators@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.8.3.tgz#3995d7d7ffff432f6ddc742b47e730c054599897" - integrity sha512-Zpg2Sgc++37kuFl6ppq2Q7Awc6E6AIW671x5PY8E/f7MCIyPPGK/EoeZXvvY3P42exZ3Q4/t3YOzP/HiN79jDg== +"@babel/plugin-syntax-logical-assignment-operators@^7.10.4", "@babel/plugin-syntax-logical-assignment-operators@^7.8.3": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz#ca91ef46303530448b906652bac2e9fe9941f699" + integrity sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig== dependencies: - "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-nullish-coalescing-operator@^7.8.0", "@babel/plugin-syntax-nullish-coalescing-operator@^7.8.3": version "7.8.3" @@ -435,12 +481,12 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.0" -"@babel/plugin-syntax-numeric-separator@^7.8.0", "@babel/plugin-syntax-numeric-separator@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.8.3.tgz#0e3fb63e09bea1b11e96467271c8308007e7c41f" - integrity sha512-H7dCMAdN83PcCmqmkHB5dtp+Xa9a6LKSvA2hiFBC/5alSHxM5VgWZXFqDi0YFe8XNGT6iCa+z4V4zSt/PdZ7Dw== +"@babel/plugin-syntax-numeric-separator@^7.10.4", "@babel/plugin-syntax-numeric-separator@^7.8.3": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz#b9b070b3e33570cd9fd07ba7fa91c0dd37b9af97" + integrity sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug== dependencies: - "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-object-rest-spread@^7.8.0", "@babel/plugin-syntax-object-rest-spread@^7.8.3": version "7.8.3" @@ -463,368 +509,391 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.0" -"@babel/plugin-syntax-top-level-await@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.8.3.tgz#3acdece695e6b13aaf57fc291d1a800950c71391" - integrity sha512-kwj1j9lL/6Wd0hROD3b/OZZ7MSrZLqqn9RAZ5+cYYsflQ9HZBIKCUkr3+uL1MEJ1NePiUbf98jjiMQSv0NMR9g== +"@babel/plugin-syntax-top-level-await@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.10.4.tgz#4bbeb8917b54fcf768364e0a81f560e33a3ef57d" + integrity sha512-ni1brg4lXEmWyafKr0ccFWkJG0CeMt4WV1oyeBW6EFObF4oOHclbkj5cARxAPQyAQ2UTuplJyK4nfkXIMMFvsQ== dependencies: - "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-arrow-functions@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.8.3.tgz#82776c2ed0cd9e1a49956daeb896024c9473b8b6" - integrity sha512-0MRF+KC8EqH4dbuITCWwPSzsyO3HIWWlm30v8BbbpOrS1B++isGxPnnuq/IZvOX5J2D/p7DQalQm+/2PnlKGxg== +"@babel/plugin-transform-arrow-functions@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.10.4.tgz#e22960d77e697c74f41c501d44d73dbf8a6a64cd" + integrity sha512-9J/oD1jV0ZCBcgnoFWFq1vJd4msoKb/TCpGNFyyLt0zABdcvgK3aYikZ8HjzB14c26bc7E3Q1yugpwGy2aTPNA== dependencies: - "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-async-to-generator@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.8.3.tgz#4308fad0d9409d71eafb9b1a6ee35f9d64b64086" - integrity sha512-imt9tFLD9ogt56Dd5CI/6XgpukMwd/fLGSrix2httihVe7LOGVPhyhMh1BU5kDM7iHD08i8uUtmV2sWaBFlHVQ== +"@babel/plugin-transform-async-to-generator@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.10.4.tgz#41a5017e49eb6f3cda9392a51eef29405b245a37" + integrity sha512-F6nREOan7J5UXTLsDsZG3DXmZSVofr2tGNwfdrVwkDWHfQckbQXnXSPfD7iO+c/2HGqycwyLST3DnZ16n+cBJQ== dependencies: - "@babel/helper-module-imports" "^7.8.3" - "@babel/helper-plugin-utils" "^7.8.3" - "@babel/helper-remap-async-to-generator" "^7.8.3" + "@babel/helper-module-imports" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-remap-async-to-generator" "^7.10.4" -"@babel/plugin-transform-block-scoped-functions@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.8.3.tgz#437eec5b799b5852072084b3ae5ef66e8349e8a3" - integrity sha512-vo4F2OewqjbB1+yaJ7k2EJFHlTP3jR634Z9Cj9itpqNjuLXvhlVxgnjsHsdRgASR8xYDrx6onw4vW5H6We0Jmg== +"@babel/plugin-transform-block-scoped-functions@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.10.4.tgz#1afa595744f75e43a91af73b0d998ecfe4ebc2e8" + integrity sha512-WzXDarQXYYfjaV1szJvN3AD7rZgZzC1JtjJZ8dMHUyiK8mxPRahynp14zzNjU3VkPqPsO38CzxiWO1c9ARZ8JA== dependencies: - "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-block-scoping@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.8.3.tgz#97d35dab66857a437c166358b91d09050c868f3a" - integrity sha512-pGnYfm7RNRgYRi7bids5bHluENHqJhrV4bCZRwc5GamaWIIs07N4rZECcmJL6ZClwjDz1GbdMZFtPs27hTB06w== +"@babel/plugin-transform-block-scoping@^7.10.4": + version "7.11.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.11.1.tgz#5b7efe98852bef8d652c0b28144cd93a9e4b5215" + integrity sha512-00dYeDE0EVEHuuM+26+0w/SCL0BH2Qy7LwHuI4Hi4MH5gkC8/AqMN5uWFJIsoXZrAphiMm1iXzBw6L2T+eA0ew== dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - lodash "^4.17.13" + "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-classes@^7.9.5": - version "7.9.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.9.5.tgz#800597ddb8aefc2c293ed27459c1fcc935a26c2c" - integrity sha512-x2kZoIuLC//O5iA7PEvecB105o7TLzZo8ofBVhP79N+DO3jaX+KYfww9TQcfBEZD0nikNyYcGB1IKtRq36rdmg== +"@babel/plugin-transform-classes@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.10.4.tgz#405136af2b3e218bc4a1926228bc917ab1a0adc7" + integrity sha512-2oZ9qLjt161dn1ZE0Ms66xBncQH4In8Sqw1YWgBUZuGVJJS5c0OFZXL6dP2MRHrkU/eKhWg8CzFJhRQl50rQxA== dependencies: - "@babel/helper-annotate-as-pure" "^7.8.3" - "@babel/helper-define-map" "^7.8.3" - "@babel/helper-function-name" "^7.9.5" - "@babel/helper-optimise-call-expression" "^7.8.3" - "@babel/helper-plugin-utils" "^7.8.3" - "@babel/helper-replace-supers" "^7.8.6" - "@babel/helper-split-export-declaration" "^7.8.3" + "@babel/helper-annotate-as-pure" "^7.10.4" + "@babel/helper-define-map" "^7.10.4" + "@babel/helper-function-name" "^7.10.4" + "@babel/helper-optimise-call-expression" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-replace-supers" "^7.10.4" + "@babel/helper-split-export-declaration" "^7.10.4" globals "^11.1.0" -"@babel/plugin-transform-computed-properties@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.8.3.tgz#96d0d28b7f7ce4eb5b120bb2e0e943343c86f81b" - integrity sha512-O5hiIpSyOGdrQZRQ2ccwtTVkgUDBBiCuK//4RJ6UfePllUTCENOzKxfh6ulckXKc0DixTFLCfb2HVkNA7aDpzA== +"@babel/plugin-transform-computed-properties@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.10.4.tgz#9ded83a816e82ded28d52d4b4ecbdd810cdfc0eb" + integrity sha512-JFwVDXcP/hM/TbyzGq3l/XWGut7p46Z3QvqFMXTfk6/09m7xZHJUN9xHfsv7vqqD4YnfI5ueYdSJtXqqBLyjBw== dependencies: - "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-destructuring@^7.9.5": - version "7.9.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.9.5.tgz#72c97cf5f38604aea3abf3b935b0e17b1db76a50" - integrity sha512-j3OEsGel8nHL/iusv/mRd5fYZ3DrOxWC82x0ogmdN/vHfAP4MYw+AFKYanzWlktNwikKvlzUV//afBW5FTp17Q== +"@babel/plugin-transform-destructuring@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.10.4.tgz#70ddd2b3d1bea83d01509e9bb25ddb3a74fc85e5" + integrity sha512-+WmfvyfsyF603iPa6825mq6Qrb7uLjTOsa3XOFzlYcYDHSS4QmpOWOL0NNBY5qMbvrcf3tq0Cw+v4lxswOBpgA== dependencies: - "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-dotall-regex@^7.4.4", "@babel/plugin-transform-dotall-regex@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.8.3.tgz#c3c6ec5ee6125c6993c5cbca20dc8621a9ea7a6e" - integrity sha512-kLs1j9Nn4MQoBYdRXH6AeaXMbEJFaFu/v1nQkvib6QzTj8MZI5OQzqmD83/2jEM1z0DLilra5aWO5YpyC0ALIw== +"@babel/plugin-transform-dotall-regex@^7.10.4", "@babel/plugin-transform-dotall-regex@^7.4.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.10.4.tgz#469c2062105c1eb6a040eaf4fac4b488078395ee" + integrity sha512-ZEAVvUTCMlMFAbASYSVQoxIbHm2OkG2MseW6bV2JjIygOjdVv8tuxrCTzj1+Rynh7ODb8GivUy7dzEXzEhuPaA== dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.8.3" - "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-create-regexp-features-plugin" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-duplicate-keys@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.8.3.tgz#8d12df309aa537f272899c565ea1768e286e21f1" - integrity sha512-s8dHiBUbcbSgipS4SMFuWGqCvyge5V2ZeAWzR6INTVC3Ltjig/Vw1G2Gztv0vU/hRG9X8IvKvYdoksnUfgXOEQ== +"@babel/plugin-transform-duplicate-keys@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.10.4.tgz#697e50c9fee14380fe843d1f306b295617431e47" + integrity sha512-GL0/fJnmgMclHiBTTWXNlYjYsA7rDrtsazHG6mglaGSTh0KsrW04qml+Bbz9FL0LcJIRwBWL5ZqlNHKTkU3xAA== dependencies: - "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-exponentiation-operator@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.8.3.tgz#581a6d7f56970e06bf51560cd64f5e947b70d7b7" - integrity sha512-zwIpuIymb3ACcInbksHaNcR12S++0MDLKkiqXHl3AzpgdKlFNhog+z/K0+TGW+b0w5pgTq4H6IwV/WhxbGYSjQ== +"@babel/plugin-transform-exponentiation-operator@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.10.4.tgz#5ae338c57f8cf4001bdb35607ae66b92d665af2e" + integrity sha512-S5HgLVgkBcRdyQAHbKj+7KyuWx8C6t5oETmUuwz1pt3WTWJhsUV0WIIXuVvfXMxl/QQyHKlSCNNtaIamG8fysw== dependencies: - "@babel/helper-builder-binary-assignment-operator-visitor" "^7.8.3" - "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-builder-binary-assignment-operator-visitor" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-for-of@^7.9.0": - version "7.9.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.9.0.tgz#0f260e27d3e29cd1bb3128da5e76c761aa6c108e" - integrity sha512-lTAnWOpMwOXpyDx06N+ywmF3jNbafZEqZ96CGYabxHrxNX8l5ny7dt4bK/rGwAh9utyP2b2Hv7PlZh1AAS54FQ== +"@babel/plugin-transform-for-of@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.10.4.tgz#c08892e8819d3a5db29031b115af511dbbfebae9" + integrity sha512-ItdQfAzu9AlEqmusA/65TqJ79eRcgGmpPPFvBnGILXZH975G0LNjP1yjHvGgfuCxqrPPueXOPe+FsvxmxKiHHQ== dependencies: - "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-function-name@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.8.3.tgz#279373cb27322aaad67c2683e776dfc47196ed8b" - integrity sha512-rO/OnDS78Eifbjn5Py9v8y0aR+aSYhDhqAwVfsTl0ERuMZyr05L1aFSCJnbv2mmsLkit/4ReeQ9N2BgLnOcPCQ== +"@babel/plugin-transform-function-name@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.10.4.tgz#6a467880e0fc9638514ba369111811ddbe2644b7" + integrity sha512-OcDCq2y5+E0dVD5MagT5X+yTRbcvFjDI2ZVAottGH6tzqjx/LKpgkUepu3hp/u4tZBzxxpNGwLsAvGBvQ2mJzg== dependencies: - "@babel/helper-function-name" "^7.8.3" - "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-function-name" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-literals@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.8.3.tgz#aef239823d91994ec7b68e55193525d76dbd5dc1" - integrity sha512-3Tqf8JJ/qB7TeldGl+TT55+uQei9JfYaregDcEAyBZ7akutriFrt6C/wLYIer6OYhleVQvH/ntEhjE/xMmy10A== +"@babel/plugin-transform-literals@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.10.4.tgz#9f42ba0841100a135f22712d0e391c462f571f3c" + integrity sha512-Xd/dFSTEVuUWnyZiMu76/InZxLTYilOSr1UlHV+p115Z/Le2Fi1KXkJUYz0b42DfndostYlPub3m8ZTQlMaiqQ== dependencies: - "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-member-expression-literals@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.8.3.tgz#963fed4b620ac7cbf6029c755424029fa3a40410" - integrity sha512-3Wk2EXhnw+rP+IDkK6BdtPKsUE5IeZ6QOGrPYvw52NwBStw9V1ZVzxgK6fSKSxqUvH9eQPR3tm3cOq79HlsKYA== +"@babel/plugin-transform-member-expression-literals@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.10.4.tgz#b1ec44fcf195afcb8db2c62cd8e551c881baf8b7" + integrity sha512-0bFOvPyAoTBhtcJLr9VcwZqKmSjFml1iVxvPL0ReomGU53CX53HsM4h2SzckNdkQcHox1bpAqzxBI1Y09LlBSw== dependencies: - "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-modules-amd@^7.9.6": - version "7.9.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.9.6.tgz#8539ec42c153d12ea3836e0e3ac30d5aae7b258e" - integrity sha512-zoT0kgC3EixAyIAU+9vfaUVKTv9IxBDSabgHoUCBP6FqEJ+iNiN7ip7NBKcYqbfUDfuC2mFCbM7vbu4qJgOnDw== +"@babel/plugin-transform-modules-amd@^7.10.4": + version "7.10.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.10.5.tgz#1b9cddaf05d9e88b3aad339cb3e445c4f020a9b1" + integrity sha512-elm5uruNio7CTLFItVC/rIzKLfQ17+fX7EVz5W0TMgIHFo1zY0Ozzx+lgwhL4plzl8OzVn6Qasx5DeEFyoNiRw== dependencies: - "@babel/helper-module-transforms" "^7.9.0" - "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-module-transforms" "^7.10.5" + "@babel/helper-plugin-utils" "^7.10.4" babel-plugin-dynamic-import-node "^2.3.3" -"@babel/plugin-transform-modules-commonjs@^7.9.6": - version "7.9.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.9.6.tgz#64b7474a4279ee588cacd1906695ca721687c277" - integrity sha512-7H25fSlLcn+iYimmsNe3uK1at79IE6SKW9q0/QeEHTMC9MdOZ+4bA+T1VFB5fgOqBWoqlifXRzYD0JPdmIrgSQ== +"@babel/plugin-transform-modules-commonjs@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.10.4.tgz#66667c3eeda1ebf7896d41f1f16b17105a2fbca0" + integrity sha512-Xj7Uq5o80HDLlW64rVfDBhao6OX89HKUmb+9vWYaLXBZOma4gA6tw4Ni1O5qVDoZWUV0fxMYA0aYzOawz0l+1w== dependencies: - "@babel/helper-module-transforms" "^7.9.0" - "@babel/helper-plugin-utils" "^7.8.3" - "@babel/helper-simple-access" "^7.8.3" + "@babel/helper-module-transforms" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-simple-access" "^7.10.4" babel-plugin-dynamic-import-node "^2.3.3" -"@babel/plugin-transform-modules-systemjs@^7.9.6": - version "7.9.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.9.6.tgz#207f1461c78a231d5337a92140e52422510d81a4" - integrity sha512-NW5XQuW3N2tTHim8e1b7qGy7s0kZ2OH3m5octc49K1SdAKGxYxeIx7hiIz05kS1R2R+hOWcsr1eYwcGhrdHsrg== +"@babel/plugin-transform-modules-systemjs@^7.10.4": + version "7.10.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.10.5.tgz#6270099c854066681bae9e05f87e1b9cadbe8c85" + integrity sha512-f4RLO/OL14/FP1AEbcsWMzpbUz6tssRaeQg11RH1BP/XnPpRoVwgeYViMFacnkaw4k4wjRSjn3ip1Uw9TaXuMw== dependencies: - "@babel/helper-hoist-variables" "^7.8.3" - "@babel/helper-module-transforms" "^7.9.0" - "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-hoist-variables" "^7.10.4" + "@babel/helper-module-transforms" "^7.10.5" + "@babel/helper-plugin-utils" "^7.10.4" babel-plugin-dynamic-import-node "^2.3.3" -"@babel/plugin-transform-modules-umd@^7.9.0": - version "7.9.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.9.0.tgz#e909acae276fec280f9b821a5f38e1f08b480697" - integrity sha512-uTWkXkIVtg/JGRSIABdBoMsoIeoHQHPTL0Y2E7xf5Oj7sLqwVsNXOkNk0VJc7vF0IMBsPeikHxFjGe+qmwPtTQ== +"@babel/plugin-transform-modules-umd@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.10.4.tgz#9a8481fe81b824654b3a0b65da3df89f3d21839e" + integrity sha512-mohW5q3uAEt8T45YT7Qc5ws6mWgJAaL/8BfWD9Dodo1A3RKWli8wTS+WiQ/knF+tXlPirW/1/MqzzGfCExKECA== dependencies: - "@babel/helper-module-transforms" "^7.9.0" - "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-module-transforms" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-named-capturing-groups-regex@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.8.3.tgz#a2a72bffa202ac0e2d0506afd0939c5ecbc48c6c" - integrity sha512-f+tF/8UVPU86TrCb06JoPWIdDpTNSGGcAtaD9mLP0aYGA0OS0j7j7DHJR0GTFrUZPUU6loZhbsVZgTh0N+Qdnw== +"@babel/plugin-transform-named-capturing-groups-regex@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.10.4.tgz#78b4d978810b6f3bcf03f9e318f2fc0ed41aecb6" + integrity sha512-V6LuOnD31kTkxQPhKiVYzYC/Jgdq53irJC/xBSmqcNcqFGV+PER4l6rU5SH2Vl7bH9mLDHcc0+l9HUOe4RNGKA== dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.8.3" + "@babel/helper-create-regexp-features-plugin" "^7.10.4" -"@babel/plugin-transform-new-target@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.8.3.tgz#60cc2ae66d85c95ab540eb34babb6434d4c70c43" - integrity sha512-QuSGysibQpyxexRyui2vca+Cmbljo8bcRckgzYV4kRIsHpVeyeC3JDO63pY+xFZ6bWOBn7pfKZTqV4o/ix9sFw== +"@babel/plugin-transform-new-target@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.10.4.tgz#9097d753cb7b024cb7381a3b2e52e9513a9c6888" + integrity sha512-YXwWUDAH/J6dlfwqlWsztI2Puz1NtUAubXhOPLQ5gjR/qmQ5U96DY4FQO8At33JN4XPBhrjB8I4eMmLROjjLjw== dependencies: - "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-object-super@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.8.3.tgz#ebb6a1e7a86ffa96858bd6ac0102d65944261725" - integrity sha512-57FXk+gItG/GejofIyLIgBKTas4+pEU47IXKDBWFTxdPd7F80H8zybyAY7UoblVfBhBGs2EKM+bJUu2+iUYPDQ== +"@babel/plugin-transform-object-super@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.10.4.tgz#d7146c4d139433e7a6526f888c667e314a093894" + integrity sha512-5iTw0JkdRdJvr7sY0vHqTpnruUpTea32JHmq/atIWqsnNussbRzjEDyWep8UNztt1B5IusBYg8Irb0bLbiEBCQ== dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - "@babel/helper-replace-supers" "^7.8.3" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-replace-supers" "^7.10.4" -"@babel/plugin-transform-parameters@^7.9.5": - version "7.9.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.9.5.tgz#173b265746f5e15b2afe527eeda65b73623a0795" - integrity sha512-0+1FhHnMfj6lIIhVvS4KGQJeuhe1GI//h5uptK4PvLt+BGBxsoUJbd3/IW002yk//6sZPlFgsG1hY6OHLcy6kA== +"@babel/plugin-transform-parameters@^7.10.4": + version "7.10.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.10.5.tgz#59d339d58d0b1950435f4043e74e2510005e2c4a" + integrity sha512-xPHwUj5RdFV8l1wuYiu5S9fqWGM2DrYc24TMvUiRrPVm+SM3XeqU9BcokQX/kEUe+p2RBwy+yoiR1w/Blq6ubw== dependencies: - "@babel/helper-get-function-arity" "^7.8.3" - "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-get-function-arity" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-property-literals@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.8.3.tgz#33194300d8539c1ed28c62ad5087ba3807b98263" - integrity sha512-uGiiXAZMqEoQhRWMK17VospMZh5sXWg+dlh2soffpkAl96KAm+WZuJfa6lcELotSRmooLqg0MWdH6UUq85nmmg== +"@babel/plugin-transform-property-literals@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.10.4.tgz#f6fe54b6590352298785b83edd815d214c42e3c0" + integrity sha512-ofsAcKiUxQ8TY4sScgsGeR2vJIsfrzqvFb9GvJ5UdXDzl+MyYCaBj/FGzXuv7qE0aJcjWMILny1epqelnFlz8g== dependencies: - "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-react-display-name@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.8.3.tgz#70ded987c91609f78353dd76d2fb2a0bb991e8e5" - integrity sha512-3Jy/PCw8Fe6uBKtEgz3M82ljt+lTg+xJaM4og+eyu83qLT87ZUSckn0wy7r31jflURWLO83TW6Ylf7lyXj3m5A== +"@babel/plugin-transform-react-display-name@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.10.4.tgz#b5795f4e3e3140419c3611b7a2a3832b9aef328d" + integrity sha512-Zd4X54Mu9SBfPGnEcaGcOrVAYOtjT2on8QZkLKEq1S/tHexG39d9XXGZv19VfRrDjPJzFmPfTAqOQS1pfFOujw== dependencies: - "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-react-jsx-development@^7.9.0": - version "7.9.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.9.0.tgz#3c2a130727caf00c2a293f0aed24520825dbf754" - integrity sha512-tK8hWKrQncVvrhvtOiPpKrQjfNX3DtkNLSX4ObuGcpS9p0QrGetKmlySIGR07y48Zft8WVgPakqd/bk46JrMSw== +"@babel/plugin-transform-react-jsx-development@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.10.4.tgz#6ec90f244394604623880e15ebc3c34c356258ba" + integrity sha512-RM3ZAd1sU1iQ7rI2dhrZRZGv0aqzNQMbkIUCS1txYpi9wHQ2ZHNjo5TwX+UD6pvFW4AbWqLVYvKy5qJSAyRGjQ== dependencies: - "@babel/helper-builder-react-jsx-experimental" "^7.9.0" - "@babel/helper-plugin-utils" "^7.8.3" - "@babel/plugin-syntax-jsx" "^7.8.3" + "@babel/helper-builder-react-jsx-experimental" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-jsx" "^7.10.4" -"@babel/plugin-transform-react-jsx-self@^7.9.0": - version "7.9.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.9.0.tgz#f4f26a325820205239bb915bad8e06fcadabb49b" - integrity sha512-K2ObbWPKT7KUTAoyjCsFilOkEgMvFG+y0FqOl6Lezd0/13kMkkjHskVsZvblRPj1PHA44PrToaZANrryppzTvQ== +"@babel/plugin-transform-react-jsx-self@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.10.4.tgz#cd301a5fed8988c182ed0b9d55e9bd6db0bd9369" + integrity sha512-yOvxY2pDiVJi0axdTWHSMi5T0DILN+H+SaeJeACHKjQLezEzhLx9nEF9xgpBLPtkZsks9cnb5P9iBEi21En3gg== dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - "@babel/plugin-syntax-jsx" "^7.8.3" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-jsx" "^7.10.4" -"@babel/plugin-transform-react-jsx-source@^7.9.0": - version "7.9.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.9.0.tgz#89ef93025240dd5d17d3122294a093e5e0183de0" - integrity sha512-K6m3LlSnTSfRkM6FcRk8saNEeaeyG5k7AVkBU2bZK3+1zdkSED3qNdsWrUgQBeTVD2Tp3VMmerxVO2yM5iITmw== +"@babel/plugin-transform-react-jsx-source@^7.10.4": + version "7.10.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.10.5.tgz#34f1779117520a779c054f2cdd9680435b9222b4" + integrity sha512-wTeqHVkN1lfPLubRiZH3o73f4rfon42HpgxUSs86Nc+8QIcm/B9s8NNVXu/gwGcOyd7yDib9ikxoDLxJP0UiDA== dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - "@babel/plugin-syntax-jsx" "^7.8.3" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-jsx" "^7.10.4" -"@babel/plugin-transform-react-jsx@^7.9.4": - version "7.9.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.9.4.tgz#86f576c8540bd06d0e95e0b61ea76d55f6cbd03f" - integrity sha512-Mjqf3pZBNLt854CK0C/kRuXAnE6H/bo7xYojP+WGtX8glDGSibcwnsWwhwoSuRg0+EBnxPC1ouVnuetUIlPSAw== +"@babel/plugin-transform-react-jsx@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.10.4.tgz#673c9f913948764a4421683b2bef2936968fddf2" + integrity sha512-L+MfRhWjX0eI7Js093MM6MacKU4M6dnCRa/QPDwYMxjljzSCzzlzKzj9Pk4P3OtrPcxr2N3znR419nr3Xw+65A== dependencies: - "@babel/helper-builder-react-jsx" "^7.9.0" - "@babel/helper-builder-react-jsx-experimental" "^7.9.0" - "@babel/helper-plugin-utils" "^7.8.3" - "@babel/plugin-syntax-jsx" "^7.8.3" + "@babel/helper-builder-react-jsx" "^7.10.4" + "@babel/helper-builder-react-jsx-experimental" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-jsx" "^7.10.4" + +"@babel/plugin-transform-react-pure-annotations@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.10.4.tgz#3eefbb73db94afbc075f097523e445354a1c6501" + integrity sha512-+njZkqcOuS8RaPakrnR9KvxjoG1ASJWpoIv/doyWngId88JoFlPlISenGXjrVacZUIALGUr6eodRs1vmPnF23A== + dependencies: + "@babel/helper-annotate-as-pure" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-regenerator@^7.8.7": - version "7.8.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.8.7.tgz#5e46a0dca2bee1ad8285eb0527e6abc9c37672f8" - integrity sha512-TIg+gAl4Z0a3WmD3mbYSk+J9ZUH6n/Yc57rtKRnlA/7rcCvpekHXe0CMZHP1gYp7/KLe9GHTuIba0vXmls6drA== +"@babel/plugin-transform-regenerator@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.10.4.tgz#2015e59d839074e76838de2159db421966fd8b63" + integrity sha512-3thAHwtor39A7C04XucbMg17RcZ3Qppfxr22wYzZNcVIkPHfpM9J0SO8zuCV6SZa265kxBJSrfKTvDCYqBFXGw== dependencies: regenerator-transform "^0.14.2" -"@babel/plugin-transform-reserved-words@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.8.3.tgz#9a0635ac4e665d29b162837dd3cc50745dfdf1f5" - integrity sha512-mwMxcycN3omKFDjDQUl+8zyMsBfjRFr0Zn/64I41pmjv4NJuqcYlEtezwYtw9TFd9WR1vN5kiM+O0gMZzO6L0A== +"@babel/plugin-transform-reserved-words@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.10.4.tgz#8f2682bcdcef9ed327e1b0861585d7013f8a54dd" + integrity sha512-hGsw1O6Rew1fkFbDImZIEqA8GoidwTAilwCyWqLBM9f+e/u/sQMQu7uX6dyokfOayRuuVfKOW4O7HvaBWM+JlQ== dependencies: - "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-shorthand-properties@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.8.3.tgz#28545216e023a832d4d3a1185ed492bcfeac08c8" - integrity sha512-I9DI6Odg0JJwxCHzbzW08ggMdCezoWcuQRz3ptdudgwaHxTjxw5HgdFJmZIkIMlRymL6YiZcped4TTCB0JcC8w== +"@babel/plugin-transform-shorthand-properties@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.10.4.tgz#9fd25ec5cdd555bb7f473e5e6ee1c971eede4dd6" + integrity sha512-AC2K/t7o07KeTIxMoHneyX90v3zkm5cjHJEokrPEAGEy3UCp8sLKfnfOIGdZ194fyN4wfX/zZUWT9trJZ0qc+Q== dependencies: - "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-spread@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.8.3.tgz#9c8ffe8170fdfb88b114ecb920b82fb6e95fe5e8" - integrity sha512-CkuTU9mbmAoFOI1tklFWYYbzX5qCIZVXPVy0jpXgGwkplCndQAa58s2jr66fTeQnA64bDox0HL4U56CFYoyC7g== +"@babel/plugin-transform-spread@^7.11.0": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.11.0.tgz#fa84d300f5e4f57752fe41a6d1b3c554f13f17cc" + integrity sha512-UwQYGOqIdQJe4aWNyS7noqAnN2VbaczPLiEtln+zPowRNlD+79w3oi2TWfYe0eZgd+gjZCbsydN7lzWysDt+gw== dependencies: - "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-skip-transparent-expression-wrappers" "^7.11.0" -"@babel/plugin-transform-sticky-regex@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.8.3.tgz#be7a1290f81dae767475452199e1f76d6175b100" - integrity sha512-9Spq0vGCD5Bb4Z/ZXXSK5wbbLFMG085qd2vhL1JYu1WcQ5bXqZBAYRzU1d+p79GcHs2szYv5pVQCX13QgldaWw== +"@babel/plugin-transform-sticky-regex@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.10.4.tgz#8f3889ee8657581130a29d9cc91d7c73b7c4a28d" + integrity sha512-Ddy3QZfIbEV0VYcVtFDCjeE4xwVTJWTmUtorAJkn6u/92Z/nWJNV+mILyqHKrUxXYKA2EoCilgoPePymKL4DvQ== dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - "@babel/helper-regex" "^7.8.3" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-regex" "^7.10.4" -"@babel/plugin-transform-template-literals@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.8.3.tgz#7bfa4732b455ea6a43130adc0ba767ec0e402a80" - integrity sha512-820QBtykIQOLFT8NZOcTRJ1UNuztIELe4p9DCgvj4NK+PwluSJ49we7s9FB1HIGNIYT7wFUJ0ar2QpCDj0escQ== +"@babel/plugin-transform-template-literals@^7.10.4": + version "7.10.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.10.5.tgz#78bc5d626a6642db3312d9d0f001f5e7639fde8c" + integrity sha512-V/lnPGIb+KT12OQikDvgSuesRX14ck5FfJXt6+tXhdkJ+Vsd0lDCVtF6jcB4rNClYFzaB2jusZ+lNISDk2mMMw== dependencies: - "@babel/helper-annotate-as-pure" "^7.8.3" - "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-annotate-as-pure" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-typeof-symbol@^7.8.4": - version "7.8.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.8.4.tgz#ede4062315ce0aaf8a657a920858f1a2f35fc412" - integrity sha512-2QKyfjGdvuNfHsb7qnBBlKclbD4CfshH2KvDabiijLMGXPHJXGxtDzwIF7bQP+T0ysw8fYTtxPafgfs/c1Lrqg== +"@babel/plugin-transform-typeof-symbol@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.10.4.tgz#9509f1a7eec31c4edbffe137c16cc33ff0bc5bfc" + integrity sha512-QqNgYwuuW0y0H+kUE/GWSR45t/ccRhe14Fs/4ZRouNNQsyd4o3PG4OtHiIrepbM2WKUBDAXKCAK/Lk4VhzTaGA== dependencies: - "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-unicode-regex@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.8.3.tgz#0cef36e3ba73e5c57273effb182f46b91a1ecaad" - integrity sha512-+ufgJjYdmWfSQ+6NS9VGUR2ns8cjJjYbrbi11mZBTaWm+Fui/ncTLFF28Ei1okavY+xkojGr1eJxNsWYeA5aZw== +"@babel/plugin-transform-unicode-escapes@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.10.4.tgz#feae523391c7651ddac115dae0a9d06857892007" + integrity sha512-y5XJ9waMti2J+e7ij20e+aH+fho7Wb7W8rNuu72aKRwCHFqQdhkdU2lo3uZ9tQuboEJcUFayXdARhcxLQ3+6Fg== dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.8.3" - "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-transform-unicode-regex@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.10.4.tgz#e56d71f9282fac6db09c82742055576d5e6d80a8" + integrity sha512-wNfsc4s8N2qnIwpO/WP2ZiSyjfpTamT2C9V9FDH/Ljub9zw6P3SjkXcFmc0RQUt96k2fmIvtla2MMjgTwIAC+A== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" "@babel/polyfill@^7.4.4": - version "7.8.7" - resolved "https://registry.yarnpkg.com/@babel/polyfill/-/polyfill-7.8.7.tgz#151ec24c7135481336168c3bd8b8bf0cf91c032f" - integrity sha512-LeSfP9bNZH2UOZgcGcZ0PIHUt1ZuHub1L3CVmEyqLxCeDLm4C5Gi8jRH8ZX2PNpDhQCo0z6y/+DIs2JlliXW8w== + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/polyfill/-/polyfill-7.10.4.tgz#915e5bfe61490ac0199008e35ca9d7d151a8e45a" + integrity sha512-8BYcnVqQ5kMD2HXoHInBH7H1b/uP3KdnwCYXOqFnXqguOyuu443WXusbIUbWEfY3Z0Txk0M1uG/8YuAMhNl6zg== dependencies: core-js "^2.6.5" regenerator-runtime "^0.13.4" "@babel/preset-env@^7.5.5": - version "7.9.6" - resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.9.6.tgz#df063b276c6455ec6fcfc6e53aacc38da9b0aea6" - integrity sha512-0gQJ9RTzO0heXOhzftog+a/WyOuqMrAIugVYxMYf83gh1CQaQDjMtsOpqOwXyDL/5JcWsrCm8l4ju8QC97O7EQ== - dependencies: - "@babel/compat-data" "^7.9.6" - "@babel/helper-compilation-targets" "^7.9.6" - "@babel/helper-module-imports" "^7.8.3" - "@babel/helper-plugin-utils" "^7.8.3" - "@babel/plugin-proposal-async-generator-functions" "^7.8.3" - "@babel/plugin-proposal-dynamic-import" "^7.8.3" - "@babel/plugin-proposal-json-strings" "^7.8.3" - "@babel/plugin-proposal-nullish-coalescing-operator" "^7.8.3" - "@babel/plugin-proposal-numeric-separator" "^7.8.3" - "@babel/plugin-proposal-object-rest-spread" "^7.9.6" - "@babel/plugin-proposal-optional-catch-binding" "^7.8.3" - "@babel/plugin-proposal-optional-chaining" "^7.9.0" - "@babel/plugin-proposal-unicode-property-regex" "^7.8.3" + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.11.0.tgz#860ee38f2ce17ad60480c2021ba9689393efb796" + integrity sha512-2u1/k7rG/gTh02dylX2kL3S0IJNF+J6bfDSp4DI2Ma8QN6Y9x9pmAax59fsCk6QUQG0yqH47yJWA+u1I1LccAg== + dependencies: + "@babel/compat-data" "^7.11.0" + "@babel/helper-compilation-targets" "^7.10.4" + "@babel/helper-module-imports" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-proposal-async-generator-functions" "^7.10.4" + "@babel/plugin-proposal-class-properties" "^7.10.4" + "@babel/plugin-proposal-dynamic-import" "^7.10.4" + "@babel/plugin-proposal-export-namespace-from" "^7.10.4" + "@babel/plugin-proposal-json-strings" "^7.10.4" + "@babel/plugin-proposal-logical-assignment-operators" "^7.11.0" + "@babel/plugin-proposal-nullish-coalescing-operator" "^7.10.4" + "@babel/plugin-proposal-numeric-separator" "^7.10.4" + "@babel/plugin-proposal-object-rest-spread" "^7.11.0" + "@babel/plugin-proposal-optional-catch-binding" "^7.10.4" + "@babel/plugin-proposal-optional-chaining" "^7.11.0" + "@babel/plugin-proposal-private-methods" "^7.10.4" + "@babel/plugin-proposal-unicode-property-regex" "^7.10.4" "@babel/plugin-syntax-async-generators" "^7.8.0" + "@babel/plugin-syntax-class-properties" "^7.10.4" "@babel/plugin-syntax-dynamic-import" "^7.8.0" + "@babel/plugin-syntax-export-namespace-from" "^7.8.3" "@babel/plugin-syntax-json-strings" "^7.8.0" + "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.0" - "@babel/plugin-syntax-numeric-separator" "^7.8.0" + "@babel/plugin-syntax-numeric-separator" "^7.10.4" "@babel/plugin-syntax-object-rest-spread" "^7.8.0" "@babel/plugin-syntax-optional-catch-binding" "^7.8.0" "@babel/plugin-syntax-optional-chaining" "^7.8.0" - "@babel/plugin-syntax-top-level-await" "^7.8.3" - "@babel/plugin-transform-arrow-functions" "^7.8.3" - "@babel/plugin-transform-async-to-generator" "^7.8.3" - "@babel/plugin-transform-block-scoped-functions" "^7.8.3" - "@babel/plugin-transform-block-scoping" "^7.8.3" - "@babel/plugin-transform-classes" "^7.9.5" - "@babel/plugin-transform-computed-properties" "^7.8.3" - "@babel/plugin-transform-destructuring" "^7.9.5" - "@babel/plugin-transform-dotall-regex" "^7.8.3" - "@babel/plugin-transform-duplicate-keys" "^7.8.3" - "@babel/plugin-transform-exponentiation-operator" "^7.8.3" - "@babel/plugin-transform-for-of" "^7.9.0" - "@babel/plugin-transform-function-name" "^7.8.3" - "@babel/plugin-transform-literals" "^7.8.3" - "@babel/plugin-transform-member-expression-literals" "^7.8.3" - "@babel/plugin-transform-modules-amd" "^7.9.6" - "@babel/plugin-transform-modules-commonjs" "^7.9.6" - "@babel/plugin-transform-modules-systemjs" "^7.9.6" - "@babel/plugin-transform-modules-umd" "^7.9.0" - "@babel/plugin-transform-named-capturing-groups-regex" "^7.8.3" - "@babel/plugin-transform-new-target" "^7.8.3" - "@babel/plugin-transform-object-super" "^7.8.3" - "@babel/plugin-transform-parameters" "^7.9.5" - "@babel/plugin-transform-property-literals" "^7.8.3" - "@babel/plugin-transform-regenerator" "^7.8.7" - "@babel/plugin-transform-reserved-words" "^7.8.3" - "@babel/plugin-transform-shorthand-properties" "^7.8.3" - "@babel/plugin-transform-spread" "^7.8.3" - "@babel/plugin-transform-sticky-regex" "^7.8.3" - "@babel/plugin-transform-template-literals" "^7.8.3" - "@babel/plugin-transform-typeof-symbol" "^7.8.4" - "@babel/plugin-transform-unicode-regex" "^7.8.3" + "@babel/plugin-syntax-top-level-await" "^7.10.4" + "@babel/plugin-transform-arrow-functions" "^7.10.4" + "@babel/plugin-transform-async-to-generator" "^7.10.4" + "@babel/plugin-transform-block-scoped-functions" "^7.10.4" + "@babel/plugin-transform-block-scoping" "^7.10.4" + "@babel/plugin-transform-classes" "^7.10.4" + "@babel/plugin-transform-computed-properties" "^7.10.4" + "@babel/plugin-transform-destructuring" "^7.10.4" + "@babel/plugin-transform-dotall-regex" "^7.10.4" + "@babel/plugin-transform-duplicate-keys" "^7.10.4" + "@babel/plugin-transform-exponentiation-operator" "^7.10.4" + "@babel/plugin-transform-for-of" "^7.10.4" + "@babel/plugin-transform-function-name" "^7.10.4" + "@babel/plugin-transform-literals" "^7.10.4" + "@babel/plugin-transform-member-expression-literals" "^7.10.4" + "@babel/plugin-transform-modules-amd" "^7.10.4" + "@babel/plugin-transform-modules-commonjs" "^7.10.4" + "@babel/plugin-transform-modules-systemjs" "^7.10.4" + "@babel/plugin-transform-modules-umd" "^7.10.4" + "@babel/plugin-transform-named-capturing-groups-regex" "^7.10.4" + "@babel/plugin-transform-new-target" "^7.10.4" + "@babel/plugin-transform-object-super" "^7.10.4" + "@babel/plugin-transform-parameters" "^7.10.4" + "@babel/plugin-transform-property-literals" "^7.10.4" + "@babel/plugin-transform-regenerator" "^7.10.4" + "@babel/plugin-transform-reserved-words" "^7.10.4" + "@babel/plugin-transform-shorthand-properties" "^7.10.4" + "@babel/plugin-transform-spread" "^7.11.0" + "@babel/plugin-transform-sticky-regex" "^7.10.4" + "@babel/plugin-transform-template-literals" "^7.10.4" + "@babel/plugin-transform-typeof-symbol" "^7.10.4" + "@babel/plugin-transform-unicode-escapes" "^7.10.4" + "@babel/plugin-transform-unicode-regex" "^7.10.4" "@babel/preset-modules" "^0.1.3" - "@babel/types" "^7.9.6" - browserslist "^4.11.1" + "@babel/types" "^7.11.0" + browserslist "^4.12.0" core-js-compat "^3.6.2" invariant "^2.2.2" levenary "^1.1.1" @@ -842,66 +911,67 @@ esutils "^2.0.2" "@babel/preset-react@^7.0.0": - version "7.9.4" - resolved "https://registry.yarnpkg.com/@babel/preset-react/-/preset-react-7.9.4.tgz#c6c97693ac65b6b9c0b4f25b948a8f665463014d" - integrity sha512-AxylVB3FXeOTQXNXyiuAQJSvss62FEotbX2Pzx3K/7c+MKJMdSg6Ose6QYllkdCFA8EInCJVw7M/o5QbLuA4ZQ== - dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - "@babel/plugin-transform-react-display-name" "^7.8.3" - "@babel/plugin-transform-react-jsx" "^7.9.4" - "@babel/plugin-transform-react-jsx-development" "^7.9.0" - "@babel/plugin-transform-react-jsx-self" "^7.9.0" - "@babel/plugin-transform-react-jsx-source" "^7.9.0" + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/preset-react/-/preset-react-7.10.4.tgz#92e8a66d816f9911d11d4cc935be67adfc82dbcf" + integrity sha512-BrHp4TgOIy4M19JAfO1LhycVXOPWdDbTRep7eVyatf174Hff+6Uk53sDyajqZPu8W1qXRBiYOfIamek6jA7YVw== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-transform-react-display-name" "^7.10.4" + "@babel/plugin-transform-react-jsx" "^7.10.4" + "@babel/plugin-transform-react-jsx-development" "^7.10.4" + "@babel/plugin-transform-react-jsx-self" "^7.10.4" + "@babel/plugin-transform-react-jsx-source" "^7.10.4" + "@babel/plugin-transform-react-pure-annotations" "^7.10.4" "@babel/register@^7.5.5": - version "7.9.0" - resolved "https://registry.yarnpkg.com/@babel/register/-/register-7.9.0.tgz#02464ede57548bddbb5e9f705d263b7c3f43d48b" - integrity sha512-Tv8Zyi2J2VRR8g7pC5gTeIN8Ihultbmk0ocyNz8H2nEZbmhp1N6q0A1UGsQbDvGP/sNinQKUHf3SqXwqjtFv4Q== + version "7.10.5" + resolved "https://registry.yarnpkg.com/@babel/register/-/register-7.10.5.tgz#354f3574895f1307f79efe37a51525e52fd38d89" + integrity sha512-eYHdLv43nyvmPn9bfNfrcC4+iYNwdQ8Pxk1MFJuU/U5LpSYl/PH4dFMazCYZDFVi8ueG3shvO+AQfLrxpYulQw== dependencies: find-cache-dir "^2.0.0" - lodash "^4.17.13" + lodash "^4.17.19" make-dir "^2.1.0" pirates "^4.0.0" source-map-support "^0.5.16" "@babel/runtime@^7.8.4": - version "7.9.6" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.9.6.tgz#a9102eb5cadedf3f31d08a9ecf294af7827ea29f" - integrity sha512-64AF1xY3OAkFHqOb9s4jpgk1Mm5vDZ4L3acHvAml+53nO1XbXLuDodsVpO4OIUsmemlUHMxNdYMNJmsvOwLrvQ== + version "7.11.2" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.11.2.tgz#f549c13c754cc40b87644b9fa9f09a6a95fe0736" + integrity sha512-TeWkU52so0mPtDcaCTxNBI/IHiz0pZgr8VEFqXFtZWpYD08ZB6FaSwVAS8MKRQAP3bYKiVjwysOJgMFY28o6Tw== dependencies: regenerator-runtime "^0.13.4" -"@babel/template@^7.3.3", "@babel/template@^7.8.3", "@babel/template@^7.8.6": - version "7.8.6" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.8.6.tgz#86b22af15f828dfb086474f964dcc3e39c43ce2b" - integrity sha512-zbMsPMy/v0PWFZEhQJ66bqjhH+z0JgMoBWuikXybgG3Gkd/3t5oQ1Rw2WQhnSrsOmsKXnZOx15tkC4qON/+JPg== - dependencies: - "@babel/code-frame" "^7.8.3" - "@babel/parser" "^7.8.6" - "@babel/types" "^7.8.6" - -"@babel/traverse@^7.1.0", "@babel/traverse@^7.5.5", "@babel/traverse@^7.8.3", "@babel/traverse@^7.9.6": - version "7.9.6" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.9.6.tgz#5540d7577697bf619cc57b92aa0f1c231a94f442" - integrity sha512-b3rAHSjbxy6VEAvlxM8OV/0X4XrG72zoxme6q1MOoe2vd0bEc+TwayhuC1+Dfgqh1QEG+pj7atQqvUprHIccsg== - dependencies: - "@babel/code-frame" "^7.8.3" - "@babel/generator" "^7.9.6" - "@babel/helper-function-name" "^7.9.5" - "@babel/helper-split-export-declaration" "^7.8.3" - "@babel/parser" "^7.9.6" - "@babel/types" "^7.9.6" +"@babel/template@^7.10.4", "@babel/template@^7.3.3": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.10.4.tgz#3251996c4200ebc71d1a8fc405fba940f36ba278" + integrity sha512-ZCjD27cGJFUB6nmCB1Enki3r+L5kJveX9pq1SvAUKoICy6CZ9yD8xO086YXdYhvNjBdnekm4ZnaP5yC8Cs/1tA== + dependencies: + "@babel/code-frame" "^7.10.4" + "@babel/parser" "^7.10.4" + "@babel/types" "^7.10.4" + +"@babel/traverse@^7.1.0", "@babel/traverse@^7.10.4", "@babel/traverse@^7.11.0", "@babel/traverse@^7.5.5": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.11.0.tgz#9b996ce1b98f53f7c3e4175115605d56ed07dd24" + integrity sha512-ZB2V+LskoWKNpMq6E5UUCrjtDUh5IOTAyIl0dTjIEoXum/iKWkoIEKIRDnUucO6f+2FzNkE0oD4RLKoPIufDtg== + dependencies: + "@babel/code-frame" "^7.10.4" + "@babel/generator" "^7.11.0" + "@babel/helper-function-name" "^7.10.4" + "@babel/helper-split-export-declaration" "^7.11.0" + "@babel/parser" "^7.11.0" + "@babel/types" "^7.11.0" debug "^4.1.0" globals "^11.1.0" - lodash "^4.17.13" + lodash "^4.17.19" -"@babel/types@^7.0.0", "@babel/types@^7.3.0", "@babel/types@^7.3.3", "@babel/types@^7.4.4", "@babel/types@^7.5.5", "@babel/types@^7.8.3", "@babel/types@^7.8.6", "@babel/types@^7.9.0", "@babel/types@^7.9.5", "@babel/types@^7.9.6": - version "7.9.6" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.9.6.tgz#2c5502b427251e9de1bd2dff95add646d95cc9f7" - integrity sha512-qxXzvBO//jO9ZnoasKF1uJzHd2+M6Q2ZPIVfnFps8JJvXy0ZBbwbNOmE6SGIY5XOY6d1Bo5lb9d9RJ8nv3WSeA== +"@babel/types@^7.0.0", "@babel/types@^7.10.4", "@babel/types@^7.10.5", "@babel/types@^7.11.0", "@babel/types@^7.3.0", "@babel/types@^7.3.3", "@babel/types@^7.4.4", "@babel/types@^7.5.5": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.11.0.tgz#2ae6bf1ba9ae8c3c43824e5861269871b206e90d" + integrity sha512-O53yME4ZZI0jO1EVGtF1ePGl0LHirG4P1ibcD80XyzZcKhcMFeCXmh4Xb1ifGBIV233Qg12x4rBfQgA+tmOukA== dependencies: - "@babel/helper-validator-identifier" "^7.9.5" - lodash "^4.17.13" + "@babel/helper-validator-identifier" "^7.10.4" + lodash "^4.17.19" to-fast-properties "^2.0.0" "@bcoe/v8-coverage@^0.2.3": @@ -957,16 +1027,59 @@ arrify "^2.0.0" extend "^3.0.2" +"@google-cloud/paginator@^3.0.0": + version "3.0.4" + resolved "https://registry.yarnpkg.com/@google-cloud/paginator/-/paginator-3.0.4.tgz#4106cadd8153d157c8afd16d66dfb89a38ba8748" + integrity sha512-fKI+jYQdV1F9jtG6tSRro3ilNSeBWVmTzxc8Z0kiPRXcj8eshh9fiF8TtxfDefyUKgTdWgHpzGBwLbZ/OGikJg== + dependencies: + arrify "^2.0.0" + extend "^3.0.2" + +"@google-cloud/precise-date@^2.0.0": + version "2.0.3" + resolved "https://registry.yarnpkg.com/@google-cloud/precise-date/-/precise-date-2.0.3.tgz#14f6f28ce35dabf3882e7aeab1c9d51bd473faed" + integrity sha512-+SDJ3ZvGkF7hzo6BGa8ZqeK3F6Z4+S+KviC9oOK+XCs3tfMyJCh/4j93XIWINgMMDIh9BgEvlw4306VxlXIlYA== + "@google-cloud/projectify@^1.0.0": version "1.0.4" resolved "https://registry.yarnpkg.com/@google-cloud/projectify/-/projectify-1.0.4.tgz#28daabebba6579ed998edcadf1a8f3be17f3b5f0" integrity sha512-ZdzQUN02eRsmTKfBj9FDL0KNDIFNjBn/d6tHQmA/+FImH5DO6ZV8E7FzxMgAUiVAUq41RFAkb25p1oHOZ8psfg== +"@google-cloud/projectify@^2.0.0": + version "2.0.1" + resolved "https://registry.yarnpkg.com/@google-cloud/projectify/-/projectify-2.0.1.tgz#13350ee609346435c795bbfe133a08dfeab78d65" + integrity sha512-ZDG38U/Yy6Zr21LaR3BTiiLtpJl6RkPS/JwoRT453G+6Q1DhlV0waNf8Lfu+YVYGIIxgKnLayJRfYlFJfiI8iQ== + "@google-cloud/promisify@^1.0.0": version "1.0.4" resolved "https://registry.yarnpkg.com/@google-cloud/promisify/-/promisify-1.0.4.tgz#ce86ffa94f9cfafa2e68f7b3e4a7fad194189723" integrity sha512-VccZDcOql77obTnFh0TbNED/6ZbbmHDf8UMNnzO1d5g9V0Htfm4k5cllY8P1tJsRKC3zWYGRLaViiupcgVjBoQ== +"@google-cloud/promisify@^2.0.0": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@google-cloud/promisify/-/promisify-2.0.2.tgz#81d654b4cb227c65c7ad2f9a7715262febd409ed" + integrity sha512-EvuabjzzZ9E2+OaYf+7P9OAiiwbTxKYL0oGLnREQd+Su2NTQBpomkdlkBowFvyWsaV0d1sSGxrKpSNcrhPqbxg== + +"@google-cloud/pubsub@2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@google-cloud/pubsub/-/pubsub-2.0.0.tgz#a70b599ce60fe1a7bcebb522c00ff93f252901e8" + integrity sha512-dLJ38O+UYiBK6V/cx2TDVny0N0x6RSTepY1ME7AEmLNg06QpwHFpFwJ0Ss1zv1ldWKy6mp3iV+uHH8LWbUe31Q== + dependencies: + "@google-cloud/paginator" "^3.0.0" + "@google-cloud/precise-date" "^2.0.0" + "@google-cloud/projectify" "^2.0.0" + "@google-cloud/promisify" "^2.0.0" + "@types/duplexify" "^3.6.0" + "@types/long" "^4.0.0" + arrify "^2.0.0" + extend "^3.0.2" + google-auth-library "^6.0.0" + google-gax "^2.1.0" + is-stream-ended "^0.1.4" + lodash.snakecase "^4.1.1" + p-defer "^3.0.0" + protobufjs "^6.8.1" + "@google-cloud/storage@4.4.0": version "4.4.0" resolved "https://registry.yarnpkg.com/@google-cloud/storage/-/storage-4.4.0.tgz#28bf3954b2711bab7731919a1992c84d543918ef" @@ -995,26 +1108,49 @@ through2 "^3.0.0" xdg-basedir "^4.0.0" -"@instana/collector@1.97.0": - version "1.97.0" - resolved "https://registry.yarnpkg.com/@instana/collector/-/collector-1.97.0.tgz#dd130d585735aff6c0971f087b168f22e8706042" - integrity sha512-n4Ud3iXsriztq9GxdSB3h2BxLjA2Es39dsvbDiXi09U2zc/eRZmabz3MyXzWAcpABKa/5lmCdd7oyRddyR04GA== +"@grpc/grpc-js@~1.1.1": + version "1.1.3" + resolved "https://registry.yarnpkg.com/@grpc/grpc-js/-/grpc-js-1.1.3.tgz#0b91b166d744b6a43b00430dceff0f0ff88c98d5" + integrity sha512-HtOsk2YUofBcm1GkPqGzb6pwHhv+74eC2CUO229USIDKRtg30ycbZmqC+HdNtY3nHqoc9IgcRlntFgopyQoYCA== + dependencies: + semver "^6.2.0" + +"@grpc/proto-loader@^0.5.1": + version "0.5.5" + resolved "https://registry.yarnpkg.com/@grpc/proto-loader/-/proto-loader-0.5.5.tgz#6725e7a1827bdf8e92e29fbf4e9ef0203c0906a9" + integrity sha512-WwN9jVNdHRQoOBo9FDH7qU+mgfjPc8GygPYms3M+y3fbQLfnCe/Kv/E01t7JRgnrsOHH8euvSbed3mIalXhwqQ== + dependencies: + lodash.camelcase "^4.3.0" + protobufjs "^6.8.6" + +"@instana/autoprofile@^1.106.2": + version "1.106.2" + resolved "https://registry.yarnpkg.com/@instana/autoprofile/-/autoprofile-1.106.2.tgz#010a70813170f7ecab8be228387cedbc51bc1a0a" + integrity sha512-5aoc2VwdSc9cwptTeYSZ/t5sKX/SFz0zBt/aDTE8g67hKOiQamaBmGLN/Yty6SNnBOyZSrW+p4iUllqv90OEEA== + dependencies: + nan "^2.14.0" + node-abi "^2.19.1" + node-gyp "^6.1.0" + +"@instana/collector@1.106.2": + version "1.106.2" + resolved "https://registry.yarnpkg.com/@instana/collector/-/collector-1.106.2.tgz#f9c9ed86b8bba8749ce593b6746a7aac842f96e0" + integrity sha512-Ln+5F1mQMmrrjdVa3igrc5DzAOgr7oRLrjM46eLjFR34HnUxlQPvjg32H4+WKqgGLOiWOr4iw+pQqwPc/lSU4w== dependencies: - "@instana/core" "^1.97.0" + "@instana/core" "^1.106.2" + "@instana/shared-metrics" "^1.106.2" bunyan "^1.8.12" - event-loop-lag "^1.4.0" semver "5.5.1" serialize-error "^2.1.0" + shimmer "1.2.0" optionalDependencies: - event-loop-stats "1.3.0" - gcstats.js "1.0.0" - netlinkwrapper "^1.1.2" - v8-profiler-node8 "^6.0.1" + "@instana/autoprofile" "^1.106.2" + netlinkwrapper "^1.2.0" -"@instana/core@^1.97.0": - version "1.97.0" - resolved "https://registry.yarnpkg.com/@instana/core/-/core-1.97.0.tgz#acfca15cdeccba91917322a805609bdfbca00dad" - integrity sha512-/mIKgoYWOdEAvldPYrQdetXgllKBVTjIE61yfvoedKQb8CL5pYazpj5+0wfjwkxHHD81pW5c6FAuuYq/d2xMzQ== +"@instana/core@^1.106.2": + version "1.106.2" + resolved "https://registry.yarnpkg.com/@instana/core/-/core-1.106.2.tgz#1a80a956b1215098e481fec69a179cf901729e9b" + integrity sha512-ROqPpighGgLkR/g7+/qprdDa9ahP2ZnKAi8DrvvBV34/uL0nL3c701K5ZCXKZIJW9t/Fdgx3OBj1rf+RHmrNfg== dependencies: async-hook-jl "^1.7.6" cls-bluebird "^2.1.0" @@ -1026,13 +1162,25 @@ semver "5.5.1" shimmer "1.2.0" +"@instana/shared-metrics@^1.106.2": + version "1.106.2" + resolved "https://registry.yarnpkg.com/@instana/shared-metrics/-/shared-metrics-1.106.2.tgz#06df8e6fb726a45f344f100239a004f547d6340b" + integrity sha512-X8x6vo9iEyDJ30HJilN4a8qffYK3/E7hq2IaW8ls3YKrnfLZa+7Bd5aN/1b1kbsB4/J+9cUazS28S9WBM7BVBg== + dependencies: + "@instana/core" "^1.106.2" + optionalDependencies: + event-loop-lag "^1.4.0" + event-loop-stats "1.3.0" + gcstats.js "1.0.0" + "@istanbuljs/load-nyc-config@^1.0.0": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.0.0.tgz#10602de5570baea82f8afbfa2630b24e7a8cfe5b" - integrity sha512-ZR0rq/f/E4f4XcgnDvtMWXCUJpi8eO0rssVhmztsZqLIEFA9UUP9zmpE0VxlM+kv/E1ul2I876Fwil2ayptDVg== + version "1.1.0" + resolved "https://registry.yarnpkg.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz#fd3db1d59ecf7cf121e80650bb86712f9b55eced" + integrity sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ== dependencies: camelcase "^5.3.1" find-up "^4.1.0" + get-package-type "^0.1.0" js-yaml "^3.13.1" resolve-from "^5.0.0" @@ -1218,13 +1366,14 @@ "@types/yargs" "^15.0.0" chalk "^3.0.0" -"@jest/types@^26.0.1": - version "26.0.1" - resolved "https://registry.yarnpkg.com/@jest/types/-/types-26.0.1.tgz#b78333fbd113fa7aec8d39de24f88de8686dac67" - integrity sha512-IbtjvqI9+eS1qFnOIEL7ggWmT+iK/U+Vde9cGWtYb/b6XgKb3X44ZAe/z9YZzoAAZ/E92m0DqrilF934IGNnQA== +"@jest/types@^26.3.0": + version "26.3.0" + resolved "https://registry.yarnpkg.com/@jest/types/-/types-26.3.0.tgz#97627bf4bdb72c55346eef98e3b3f7ddc4941f71" + integrity sha512-BDPG23U0qDeAvU4f99haztXwdAg3hz4El95LkAM+tHAqqhiVzRpEGHHU8EDxT/AnxOrA65YjLBwDahdJ9pTLJQ== dependencies: "@types/istanbul-lib-coverage" "^2.0.0" - "@types/istanbul-reports" "^1.1.1" + "@types/istanbul-reports" "^3.0.0" + "@types/node" "*" "@types/yargs" "^15.0.0" chalk "^4.0.0" @@ -1323,9 +1472,9 @@ integrity sha512-ONhaKPIufzzrlNbqtWFFd+jlnemX6lJAgq9ZeiZtS7I1PIf/la7CW4m83rTXRnVnsMbW2k56pGYu7AUFJD9Pow== "@sinonjs/commons@^1.7.0": - version "1.7.2" - resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-1.7.2.tgz#505f55c74e0272b43f6c52d81946bed7058fc0e2" - integrity sha512-+DUO6pnp3udV/v2VfUWgaY5BIE1IfT7lLfeDzPVeMT1XKkaAp9LgSI9x5RtrFQoZ9Oi0PgXQQHPaoKu7dCjVxw== + version "1.8.1" + resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-1.8.1.tgz#e7df00f98a203324f6dc7cc606cad9d4a8ab2217" + integrity sha512-892K+kWUUi3cl+LlqEWIDrhvLgdL79tECi8JZUyq6IviKy/DNhuzCRlbHUjxK89f4ypPMMaFnFuR9Ie6DoIMsw== dependencies: type-detect "4.0.8" @@ -1334,10 +1483,18 @@ resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-1.1.2.tgz#ccb91445360179a04e7fe6aff78c00ffc1eeaf82" integrity sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw== +"@types/amqplib@^0.5.13": + version "0.5.13" + resolved "https://registry.yarnpkg.com/@types/amqplib/-/amqplib-0.5.13.tgz#a0dc9be08f38b91e5f7532acf0c89b0e515cdc6c" + integrity sha512-0r8cJfUajAlcHxlJsZyqRrSAYzv+pJPsaAQjDC6e5rACi3AOIuR0AfevJG7NLvw3Qu4EGhf3KS/ECwd5cUAY2A== + dependencies: + "@types/bluebird" "*" + "@types/node" "*" + "@types/babel__core@^7.1.7": - version "7.1.7" - resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.1.7.tgz#1dacad8840364a57c98d0dd4855c6dd3752c6b89" - integrity sha512-RL62NqSFPCDK2FM1pSDH0scHpJvsXtZNiYlMB73DgPBaG1E38ZYVL+ei5EkWRbr+KC4YNiAUNBnRj+bgwpgjMw== + version "7.1.9" + resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.1.9.tgz#77e59d438522a6fb898fa43dc3455c6e72f3963d" + integrity sha512-sY2RsIJ5rpER1u3/aQ8OFSI7qGIy8o1NEEbgb2UaJcvOtXOMpd39ko723NBpjQFg9SIX7TXtjejZVGeIMLhoOw== dependencies: "@babel/parser" "^7.1.0" "@babel/types" "^7.0.0" @@ -1361,12 +1518,17 @@ "@babel/types" "^7.0.0" "@types/babel__traverse@*", "@types/babel__traverse@^7.0.6": - version "7.0.11" - resolved "https://registry.yarnpkg.com/@types/babel__traverse/-/babel__traverse-7.0.11.tgz#1ae3010e8bf8851d324878b42acec71986486d18" - integrity sha512-ddHK5icION5U6q11+tV2f9Mo6CZVuT8GJKld2q9LqHSZbvLbH34Kcu2yFGckZut453+eQU6btIA3RihmnRgI+Q== + version "7.0.13" + resolved "https://registry.yarnpkg.com/@types/babel__traverse/-/babel__traverse-7.0.13.tgz#1874914be974a492e1b4cb00585cabb274e8ba18" + integrity sha512-i+zS7t6/s9cdQvbqKDARrcbrPvtJGlbYsMkazo03nTAK3RX9FNrLllXys22uiTGJapPOTZTQ35nHh4ISph4SLQ== dependencies: "@babel/types" "^7.3.0" +"@types/bluebird@*": + version "3.5.32" + resolved "https://registry.yarnpkg.com/@types/bluebird/-/bluebird-3.5.32.tgz#381e7b59e39f010d20bbf7e044e48f5caf1ab620" + integrity sha512-dIOxFfI0C+jz89g6lQ+TqhGgPQ0MxSnh/E4xuC0blhFtyW269+mPG5QeLgbdwst/LvdP8o1y0o/Gz5EHXLec/g== + "@types/body-parser@*": version "1.19.0" resolved "https://registry.yarnpkg.com/@types/body-parser/-/body-parser-1.19.0.tgz#0685b3c47eb3006ffed117cdd55164b61f80538f" @@ -1389,9 +1551,9 @@ integrity sha512-6ckxMjBBD8URvjB6J3NcnuAn5Pkl7t3TizAg+xdlzzQGSPSmBcXf8KoIH0ua/i+tio+ZRUHEXp0HEmvaR4kt0w== "@types/cheerio@^0.22.8": - version "0.22.18" - resolved "https://registry.yarnpkg.com/@types/cheerio/-/cheerio-0.22.18.tgz#19018dceae691509901e339d63edf1e935978fe6" - integrity sha512-Fq7R3fINAPSdUEhOyjG4iVxgHrOnqDJbY0/BUuiN0pvD/rfmZWekVZnv+vcs8TtpA2XF50uv50LaE4EnpEL/Hw== + version "0.22.21" + resolved "https://registry.yarnpkg.com/@types/cheerio/-/cheerio-0.22.21.tgz#5e37887de309ba11b2e19a6e14cad7874b31a8a3" + integrity sha512-aGI3DfswwqgKPiEOTaiHV2ZPC9KEhprpgEbJnv0fZl3SGX0cGgEva1126dGrMC6AJM6v/aihlUgJn9M5DbDZ/Q== dependencies: "@types/node" "*" @@ -1412,6 +1574,13 @@ resolved "https://registry.yarnpkg.com/@types/debug/-/debug-4.1.5.tgz#b14efa8852b7768d898906613c23f688713e02cd" integrity sha512-Q1y515GcOdTHgagaVFhHnIFQ38ygs/kmxdNpvpou+raI9UO3YZcHDngBSYKQklcKlvA7iuQlmIKbzvmxcOE9CQ== +"@types/duplexify@^3.6.0": + version "3.6.0" + resolved "https://registry.yarnpkg.com/@types/duplexify/-/duplexify-3.6.0.tgz#dfc82b64bd3a2168f5bd26444af165bf0237dcd8" + integrity sha512-5zOA53RUlzN74bvrSGwjudssD9F3a797sDZQkiYpUOxW+WHaXTCPz4/d5Dgi6FKnOqZ2CpaTo0DhgIfsXAOE/A== + dependencies: + "@types/node" "*" + "@types/expect@24.3.0": version "24.3.0" resolved "https://registry.yarnpkg.com/@types/expect/-/expect-24.3.0.tgz#d7cab8b3c10c2d92a0cbb31981feceb81d3486f1" @@ -1420,9 +1589,9 @@ expect "*" "@types/express-serve-static-core@*": - version "4.17.7" - resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.17.7.tgz#dfe61f870eb549dc6d7e12050901847c7d7e915b" - integrity sha512-EMgTj/DF9qpgLXyc+Btimg+XoH7A2liE8uKul8qSmMTHCeNYzydDKFdsJskDvw42UsesCnhO63dO0Grbj8J4Dw== + version "4.17.9" + resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.17.9.tgz#2d7b34dcfd25ec663c25c85d76608f8b249667f1" + integrity sha512-DG0BYg6yO+ePW+XoDENYz8zhNGC3jDDEpComMYn7WJc4mY1Us8Rw9ax2YhJXxpyk2SF47PQAoQ0YyVT1a0bEkA== dependencies: "@types/node" "*" "@types/qs" "*" @@ -1445,9 +1614,9 @@ "@types/node" "*" "@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0", "@types/istanbul-lib-coverage@^2.0.1": - version "2.0.1" - resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.1.tgz#42995b446db9a48a11a07ec083499a860e9138ff" - integrity sha512-hRJD2ahnnpLgsj6KWMYSrmXkM3rm2Dl1qkx6IOFD5FnuNPXJIG5L0dhgKXCYTRMGzU4n0wImQ/xfmRc4POUFlg== + version "2.0.3" + resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.3.tgz#4ba8ddb720221f432e443bd5f9117fd22cfd4762" + integrity sha512-sz7iLqvVUg1gIedBOvlkxPlc8/uVzyS5OwGz1cKjXzkl3FpL3al0crU8YGU1WoHkxn0Wxbw5tyi6hvzJKNzFsw== "@types/istanbul-lib-report@*": version "3.0.0" @@ -1457,13 +1626,28 @@ "@types/istanbul-lib-coverage" "*" "@types/istanbul-reports@^1.1.1": - version "1.1.1" - resolved "https://registry.yarnpkg.com/@types/istanbul-reports/-/istanbul-reports-1.1.1.tgz#7a8cbf6a406f36c8add871625b278eaf0b0d255a" - integrity sha512-UpYjBi8xefVChsCoBpKShdxTllC9pwISirfoZsUa2AAdQg/Jd2KQGtSbw+ya7GPo7x/wAPlH6JBhKhAsXUEZNA== + version "1.1.2" + resolved "https://registry.yarnpkg.com/@types/istanbul-reports/-/istanbul-reports-1.1.2.tgz#e875cc689e47bce549ec81f3df5e6f6f11cfaeb2" + integrity sha512-P/W9yOX/3oPZSpaYOCQzGqgCQRXn0FFO/V8bWrCQs+wLmvVVxk6CRBXALEvNs9OHIatlnlFokfhuDo2ug01ciw== dependencies: "@types/istanbul-lib-coverage" "*" "@types/istanbul-lib-report" "*" +"@types/istanbul-reports@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@types/istanbul-reports/-/istanbul-reports-3.0.0.tgz#508b13aa344fa4976234e75dddcc34925737d821" + integrity sha512-nwKNbvnwJ2/mndE9ItP/zc2TCzw6uuodnF4EHYWD+gCQDVBuRQL5UzbZD0/ezy1iKsFU2ZQiDqg4M9dN4+wZgA== + dependencies: + "@types/istanbul-lib-report" "*" + +"@types/jaeger-client@3.15.4": + version "3.15.4" + resolved "https://registry.yarnpkg.com/@types/jaeger-client/-/jaeger-client-3.15.4.tgz#7c7548c1bbdfbdb819df63afb230998ed2e298dc" + integrity sha512-DdA3jLT6VoAnn9/AI7DBOSXSFFM839f1dXvf/wTWcofs8ajcclEexGPEbELYfC3XuoEIWLPd7OmrqF/6mp4n/A== + dependencies: + opentracing "~0.14.3" + prom-client "~11.3.0" + "@types/jest@25.2.1": version "25.2.1" resolved "https://registry.yarnpkg.com/@types/jest/-/jest-25.2.1.tgz#9544cd438607955381c1bdbdb97767a249297db5" @@ -1473,11 +1657,11 @@ pretty-format "^25.2.1" "@types/js-yaml@^3.12.1": - version "3.12.3" - resolved "https://registry.yarnpkg.com/@types/js-yaml/-/js-yaml-3.12.3.tgz#abf383c5b639d0aa8b8c4a420d6a85f703357d6c" - integrity sha512-otRe77JNNWzoVGLKw8TCspKswRoQToys4tuL6XYVBFxjgeM0RUrx7m3jkaTdxILxeGry3zM8mGYkGXMeQ02guA== + version "3.12.5" + resolved "https://registry.yarnpkg.com/@types/js-yaml/-/js-yaml-3.12.5.tgz#136d5e6a57a931e1cce6f9d8126aa98a9c92a6bb" + integrity sha512-JCcp6J0GV66Y4ZMDAQCXot4xprYB+Zfd3meK9+INSJeVZwJmHAW30BBEEkPzXswMXuiyReUGOP3GxrADc9wPww== -"@types/long@*", "@types/long@4.0.1", "@types/long@^4.0.1": +"@types/long@*", "@types/long@4.0.1", "@types/long@^4.0.0", "@types/long@^4.0.1": version "4.0.1" resolved "https://registry.yarnpkg.com/@types/long/-/long-4.0.1.tgz#459c65fa1867dafe6a8f322c4c51695663cc55e9" integrity sha512-5tXH6Bx/kNGd3MgffdmP4dy2Z+G4eaXw0SE81Tq3BNadtnMR5/ySMzX4SLEzHJzSmPNn4HIdpQsBvXMUykr58w== @@ -1488,9 +1672,9 @@ integrity sha512-RaE0B+14ToE4l6UqdarKPnXwVDuigfFv+5j9Dze/Nqr23yyuqdNvzcZi3xB+3Agvi5R4EOgAksfv3lXX4vBt9w== "@types/mime@*": - version "2.0.1" - resolved "https://registry.yarnpkg.com/@types/mime/-/mime-2.0.1.tgz#dc488842312a7f075149312905b5e3c0b054c79d" - integrity sha512-FwI9gX75FgVBJ7ywgnq/P7tw+/o1GUbtP0KzbtusLigAOgIgNISRK0ZPl4qertvXSIE8YbsVJueQ90cDt9YYyw== + version "2.0.3" + resolved "https://registry.yarnpkg.com/@types/mime/-/mime-2.0.3.tgz#c893b73721db73699943bfc3653b1deb7faa4a3a" + integrity sha512-Jus9s4CDbqwocc5pOAnh8ShfrnMcPHuJYzVcSUU7lrh8Ni5HuIqX3oilL86p3dlTrk0LzHRCgA/GQ7uNCw6l2Q== "@types/ms@0.7.31": version "0.7.31" @@ -1513,20 +1697,25 @@ "@types/node" "*" form-data "^3.0.0" -"@types/node@*", "@types/node@^13.7.0": - version "13.13.5" - resolved "https://registry.yarnpkg.com/@types/node/-/node-13.13.5.tgz#96ec3b0afafd64a4ccea9107b75bf8489f0e5765" - integrity sha512-3ySmiBYJPqgjiHA7oEaIo2Rzz0HrOZ7yrNO5HWyaE5q0lQ3BppDZ3N53Miz8bw2I7gh1/zir2MGVZBvpb1zq9g== +"@types/node@*": + version "14.0.27" + resolved "https://registry.yarnpkg.com/@types/node/-/node-14.0.27.tgz#a151873af5a5e851b51b3b065c9e63390a9e0eb1" + integrity sha512-kVrqXhbclHNHGu9ztnAwSncIgJv/FaxmzXJvGXNdcCpV1b8u1/Mi6z6m0vwy0LzKeXFTPLH0NzwmoJ3fNCIq0g== -"@types/node@8.10.59": - version "8.10.59" - resolved "https://registry.yarnpkg.com/@types/node/-/node-8.10.59.tgz#9e34261f30183f9777017a13d185dfac6b899e04" - integrity sha512-8RkBivJrDCyPpBXhVZcjh7cQxVBSmRk9QM7hOketZzp6Tg79c0N8kkpAIito9bnJ3HCVCHVYz+KHTEbfQNfeVQ== +"@types/node@10.17.30": + version "10.17.30" + resolved "https://registry.yarnpkg.com/@types/node/-/node-10.17.30.tgz#20556a0d7f62b83e163973a6cd640af636d3dd3b" + integrity sha512-euU8QLX0ipj+5mOYa4ZqZoTv+53BY7yTg9I2ZIhDXgiI3M+0n4mdAt9TQCuvxVAgU179g8OsRLaBt0qEi0T6xA== "@types/node@^10.12.0": - version "10.17.21" - resolved "https://registry.yarnpkg.com/@types/node/-/node-10.17.21.tgz#c00e9603399126925806bed2d9a1e37da506965e" - integrity sha512-PQKsydPxYxF1DsAFWmunaxd3sOi3iMt6Zmx/tgaagHYmwJ/9cRH91hQkeJZaUGWbvn0K5HlSVEXkn5U/llWPpQ== + version "10.17.28" + resolved "https://registry.yarnpkg.com/@types/node/-/node-10.17.28.tgz#0e36d718a29355ee51cec83b42d921299200f6d9" + integrity sha512-dzjES1Egb4c1a89C7lKwQh8pwjYmlOAG9dW1pBgxEk57tMrLnssOfEthz8kdkNaBd7lIqQx7APm5+mZ619IiCQ== + +"@types/node@^13.7.0": + version "13.13.15" + resolved "https://registry.yarnpkg.com/@types/node/-/node-13.13.15.tgz#fe1cc3aa465a3ea6858b793fd380b66c39919766" + integrity sha512-kwbcs0jySLxzLsa2nWUAGOd/s21WU1jebrEdtzhsj1D4Yps1EOuyI1Qcu+FD56dL7NRNIJtDDjcqIG22NwkgLw== "@types/normalize-package-data@^2.4.0": version "2.4.0" @@ -1539,9 +1728,9 @@ integrity sha512-5qOlnZscTn4xxM5MeGXAMOsIOIKIbh9e85zJWfBRVPlRMEVawzoPhINYbRGkBZCI8LxvBe7tJCdWiarA99OZfQ== "@types/q@^1.5.1": - version "1.5.2" - resolved "https://registry.yarnpkg.com/@types/q/-/q-1.5.2.tgz#690a1475b84f2a884fd07cd797c00f5f31356ea8" - integrity sha512-ce5d3q03Ex0sy4R14722Rmt6MT07Ua+k4FwDfdcToYJcMKNtRVQvJ6JCAPdAmAnbRb6CsX6aYb9m96NGod9uTw== + version "1.5.4" + resolved "https://registry.yarnpkg.com/@types/q/-/q-1.5.4.tgz#15925414e0ad2cd765bfef58842f7e26a7accb24" + integrity sha512-1HcDas8SEj4z1Wc696tH56G8OlRaH/sqZOynNNB+HF0WOeXPaxTtbYzJY2oEfiUxjSKjhCKr+MvR7dCHcEelug== "@types/qs@*": version "6.9.2" @@ -1553,10 +1742,10 @@ resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.3.tgz#7ee330ba7caafb98090bece86a5ee44115904c2c" integrity sha512-ewFXqrQHlFsgc09MK5jP5iR7vumV/BYayNC6PgJO2LPe8vrnNFyjQjSppfEngITi0qvfKtzFvgKymGheFM9UOA== -"@types/redis@2.8.20": - version "2.8.20" - resolved "https://registry.yarnpkg.com/@types/redis/-/redis-2.8.20.tgz#7060fa9d65ccf7ef32f714f05f83a016a20211c8" - integrity sha512-IJOvkg+BnCRDlMrrBIasCs8bqddnjiplI26HwsPSeY/biEJaDzAQnjs2i5z5vJelTbi3TIiLUIrKXk7j9Tmi/Q== +"@types/redis@2.8.25": + version "2.8.25" + resolved "https://registry.yarnpkg.com/@types/redis/-/redis-2.8.25.tgz#046bfff24b82effa59d74744c6fcf8995be17479" + integrity sha512-e5N5Dg712aZ1CPi1Li0XalukPSWd2RTLYzmrMsQ84NkYQ7cqKHC+HroXM1WP65O1zRGfzld72/u9ikumEe+ylA== dependencies: "@types/node" "*" @@ -1568,9 +1757,9 @@ "@types/request" "*" "@types/request@*", "@types/request@^2.47.1": - version "2.48.4" - resolved "https://registry.yarnpkg.com/@types/request/-/request-2.48.4.tgz#df3d43d7b9ed3550feaa1286c6eabf0738e6cf7e" - integrity sha512-W1t1MTKYR8PxICH+A4HgEIPuAC3sbljoEVfyZbeFJJDbr30guDspJri2XOaM2E+Un7ZjrihaDi7cf6fPa2tbgw== + version "2.48.5" + resolved "https://registry.yarnpkg.com/@types/request/-/request-2.48.5.tgz#019b8536b402069f6d11bee1b2c03e7f232937a0" + integrity sha512-/LO7xRVnL3DxJ1WkPGDQrp4VTV1reX9RkC85mJ+Qzykj2Bdw+mG15aAfDahc76HtknjzE16SX/Yddn6MxVbmGQ== dependencies: "@types/caseless" "*" "@types/node" "*" @@ -1578,9 +1767,9 @@ form-data "^2.5.0" "@types/serve-static@*": - version "1.13.3" - resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.13.3.tgz#eb7e1c41c4468272557e897e9171ded5e2ded9d1" - integrity sha512-oprSwp094zOglVrXdlo/4bAHtKTAxX6VT8FOZlBKrmyLbNvE1zxZyJ6yikMVtHIvwP45+ZQGJn+FdXGKTozq0g== + version "1.13.5" + resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.13.5.tgz#3d25d941a18415d3ab092def846e135a08bbcf53" + integrity sha512-6M64P58N+OXjU432WoLLBQxbA0LRGBCRm7aAGQJ+SMC1IMl0dgRVi9EFfoDcS2a7Xogygk/eGN94CfwU9UF7UQ== dependencies: "@types/express-serve-static-core" "*" "@types/mime" "*" @@ -1591,9 +1780,9 @@ integrity sha512-l42BggppR6zLmpfU6fq9HEa2oGPEI8yrSPL3GITjfRInppYFahObbIQOQK3UGxEnyQpltZLaPe75046NOZQikw== "@types/tedious@*": - version "4.0.0" - resolved "https://registry.yarnpkg.com/@types/tedious/-/tedious-4.0.0.tgz#1eed2823c4388b2473255153d0f68fb3efcdc5c9" - integrity sha512-uu/7XzkXSoU/AngLDdGURUFw98vZFgzQOuOIIUbSPiUfkaU7O1z29bDN4VejtmM5NS21fCHVJdd+cM96h+L78w== + version "4.0.1" + resolved "https://registry.yarnpkg.com/@types/tedious/-/tedious-4.0.1.tgz#39d484378d23a3f6f293eed92acee24de80f3024" + integrity sha512-5ZG0l2MdtM/kGY2dAvTUEyb2ZLsQn1tOa6DdEcHi/FOekcO0YMtvs7nGWMP72rxbQqx6+BlmCk0rplmF7m86XQ== dependencies: "@types/node" "*" @@ -1603,9 +1792,9 @@ integrity sha512-I99sngh224D0M7XgW1s120zxCt3VYQ3IQsuw3P3jbq5GG4yc79+ZjyKznyOGIQrflfylLgcfekeZW/vk0yng6A== "@types/underscore@^1.8.9": - version "1.10.0" - resolved "https://registry.yarnpkg.com/@types/underscore/-/underscore-1.10.0.tgz#5cb0dff2a5f616fc8e0c61b482bf01fa20a03cec" - integrity sha512-ZAbqul7QAKpM2h1PFGa5ETN27ulmqtj0QviYHasw9LffvXZvVHuraOx/FOsIPPDNGZN0Qo1nASxxSfMYOtSoCw== + version "1.10.21" + resolved "https://registry.yarnpkg.com/@types/underscore/-/underscore-1.10.21.tgz#20aa6e9417aef046c384ea4491b30a6a730cf797" + integrity sha512-tDEGvuNq36TPjzqXwqzjbcRJSn0I7XH03817tWVhAaaz8k5+0CwUH2K2KpZ3oB5sgkhGMV2l6KhIG401I+ODgg== "@types/ws@^6.0.1": version "6.0.4" @@ -1625,23 +1814,23 @@ integrity sha512-FA/BWv8t8ZWJ+gEOnLLd8ygxH/2UFbAvgEonyfN6yWGLKc7zVjbpl2Y4CTjid9h2RfgPP6SEt6uHwEOply00yw== "@types/yargs@^13.0.0": - version "13.0.8" - resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-13.0.8.tgz#a38c22def2f1c2068f8971acb3ea734eb3c64a99" - integrity sha512-XAvHLwG7UQ+8M4caKIH0ZozIOYay5fQkAgyIXegXT9jPtdIGdhga+sUEdAr1CiG46aB+c64xQEYyEzlwWVTNzA== + version "13.0.10" + resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-13.0.10.tgz#e77bf3fc73c781d48c2eb541f87c453e321e5f4b" + integrity sha512-MU10TSgzNABgdzKvQVW1nuuT+sgBMWeXNc3XOs5YXV5SDAK+PPja2eUuBNB9iqElu03xyEDqlnGw0jgl4nbqGQ== dependencies: "@types/yargs-parser" "*" "@types/yargs@^15.0.0": - version "15.0.4" - resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-15.0.4.tgz#7e5d0f8ca25e9d5849f2ea443cf7c402decd8299" - integrity sha512-9T1auFmbPZoxHz0enUFlUuKRy3it01R+hlggyVUMtnCTQRunsQYifnSGb8hET4Xo8yiC0o0r1paW3ud5+rbURg== + version "15.0.5" + resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-15.0.5.tgz#947e9a6561483bdee9adffc983e91a6902af8b79" + integrity sha512-Dk/IDOPtOgubt/IaevIUbTgV7doaKkoorvOyYM2CMwuDyP89bekI7H4xLIwunNYiK9jhCkmc6pUrJk3cj2AB9w== dependencies: "@types/yargs-parser" "*" abab@^2.0.0: - version "2.0.3" - resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.3.tgz#623e2075e02eb2d3f2475e49f99c91846467907a" - integrity sha512-tsFzPpcttalNjFBCFMqsKYQcWxxen1pgJR56by//QwvJc4/OUS3kPOOttx2tSIfjsylB0pYu7f5D3K1RCxUnUg== + version "2.0.4" + resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.4.tgz#6dfa57b417ca06d21b2478f0e638302f99c2405c" + integrity sha512-Eu9ELJWCz/c1e9gTiCY+FceWxcqzjYEbqMgtndnuSqZSUCOL73TWNK2mHfIj4Cw2E/ongOp+JISVNCmovt2KYQ== abbrev@1: version "1.1.1" @@ -1682,9 +1871,9 @@ acorn@^6.0.1: integrity sha512-ZVA9k326Nwrj3Cj9jlh3wGFutC2ZornPNARZwsNYqQYgN0EsV2d53w5RN/co65Ohn4sUAUtb1rSUAOD6XN9idA== acorn@^7.1.0: - version "7.2.0" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.2.0.tgz#17ea7e40d7c8640ff54a694c889c26f31704effe" - integrity sha512-apwXVmYVpQ34m/i71vrApRrRKCWQnZZF1+npOD0WV5xZFfwWOmKGQ2RWlfdy9vWITsenisM8M0Qeq8agcFHNiQ== + version "7.4.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.0.tgz#e1ad486e6c54501634c6c397c5c121daa383607c" + integrity sha512-+G7P8jJmCHr+S+cLfQxygbWhXy+8YTVGzAkpEbcLo2mLoL7tij/VG41QSHACSf5QgYRhMZYHuNc6drJaO0Da+w== address@1.1.2, address@^1.0.1: version "1.1.2" @@ -1692,9 +1881,9 @@ address@1.1.2, address@^1.0.1: integrity sha512-aT6camzM4xEA54YVJYSqxz1kv4IHnQZRtThJJHhUMRExaU5spC7jX5ugSwTaTgJliIgs4VhZOk7htClvQ/LmRA== agent-base@6: - version "6.0.0" - resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.0.tgz#5d0101f19bbfaed39980b22ae866de153b93f09a" - integrity sha512-j1Q7cSCqN+AwrmDd+pzgqc0/NpC655x2bUf5ZjRIO77DcNBFmh+OgRNzF6OKdCC9RSCb19fGd99+bhXFdkRNqw== + version "6.0.1" + resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.1.tgz#808007e4e5867decb0ab6ab2f928fbdb5a596db4" + integrity sha512-01q25QQDwLSsyfhrKbn8yuur+JNw0H+0Y4JiGIKd3z9aYk/w/2kxD/Upc+t2ZBBSUNff50VjPsSW2YxM8QYKVg== dependencies: debug "4" @@ -1706,10 +1895,10 @@ aggregate-error@^1.0.0: clean-stack "^1.0.0" indent-string "^3.0.0" -ajv@^6.5.5: - version "6.12.2" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.2.tgz#c629c5eced17baf314437918d2da88c99d5958cd" - integrity sha512-k+V+hzjm5q/Mr8ef/1Y9goCmlsK4I6Sm74teeyGvFk1XrOsbsKLjEdrvny42CZ+a8sXbk8KWpY/bDwS+FLL2UQ== +ajv@^6.12.3: + version "6.12.3" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.3.tgz#18c5af38a111ddeb4f2697bd78d68abc1cabd706" + integrity sha512-4K0cK3L1hsqk9xIb2z9vs/XU+PGJZ9PNpJRDS9YLzmNdX6jmVPfamLvTJr0aDAusnHyCHO6MjzlkAsgtqp9teA== dependencies: fast-deep-equal "^3.1.1" fast-json-stable-stringify "^2.0.0" @@ -1726,6 +1915,23 @@ amdefine@>=0.0.4: resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5" integrity sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU= +amqplib@^0.5.6: + version "0.5.6" + resolved "https://registry.yarnpkg.com/amqplib/-/amqplib-0.5.6.tgz#86a7850f4f39c568eaa0dd0300ef374e17941cf4" + integrity sha512-J4TR0WAMPBHN+tgTuhNsSObfM9eTVTZm/FNw0LyaGfbiLsBxqSameDNYpChUFXW4bnTKHDXy0ab+nuLhumnRrQ== + dependencies: + bitsyntax "~0.1.0" + bluebird "^3.5.2" + buffer-more-ints "~1.0.0" + readable-stream "1.x >=1.1.9" + safe-buffer "~5.1.2" + url-parse "~1.4.3" + +ansi-color@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/ansi-color/-/ansi-color-0.2.1.tgz#3e75c037475217544ed763a8db5709fa9ae5bf9a" + integrity sha1-PnXAN0dSF1RO12Oo21cJ+prlv5o= + ansi-escapes@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.2.0.tgz#8780b98ff9dbf5638152d1f1fe5c1d7b4442976b" @@ -1972,24 +2178,24 @@ autolinker@~0.28.0: gulp-header "^1.7.1" autoprefixer@^9.6.0: - version "9.7.6" - resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-9.7.6.tgz#63ac5bbc0ce7934e6997207d5bb00d68fa8293a4" - integrity sha512-F7cYpbN7uVVhACZTeeIeealwdGM6wMtfWARVLTy5xmKtgVdBNJvbDRoCK3YO1orcs7gv/KwYlb3iXwu9Ug9BkQ== + version "9.8.6" + resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-9.8.6.tgz#3b73594ca1bf9266320c5acf1588d74dea74210f" + integrity sha512-XrvP4VVHdRBCdX1S3WXVD8+RyG9qeb1D5Sn1DeLiG2xfSpzellk5k54xbUERJ3M5DggQxes39UGOTP8CFrEGbg== dependencies: - browserslist "^4.11.1" - caniuse-lite "^1.0.30001039" - chalk "^2.4.2" + browserslist "^4.12.0" + caniuse-lite "^1.0.30001109" + colorette "^1.2.1" normalize-range "^0.1.2" num2fraction "^1.2.2" - postcss "^7.0.27" - postcss-value-parser "^4.0.3" + postcss "^7.0.32" + postcss-value-parser "^4.1.0" -aws-sdk@2.673.0: - version "2.673.0" - resolved "https://registry.yarnpkg.com/aws-sdk/-/aws-sdk-2.673.0.tgz#5848900c90cfd8939602019df16fdc38d2a1cdbf" - integrity sha512-OoEPqTLmA5+4uSFf/k4ZLb8cEdx+CwlzovqGf6/gKvb8VrUxe5B5/d2RGlGM777Ke9TmuFhJtTIDugpgc2jo/Q== +aws-sdk@2.748.0: + version "2.748.0" + resolved "https://registry.yarnpkg.com/aws-sdk/-/aws-sdk-2.748.0.tgz#660d9d8202b1e48820ae9e018abad8d7b51af0b1" + integrity sha512-H+DCioQ4AChoBxGMtagcJ3a0mM0lOh3ta/dWIrfPTECAlRIuxlrBDp78cRhPgvdYYUxW54kB/IaHGR2xPP8JXw== dependencies: - buffer "4.9.1" + buffer "4.9.2" events "1.1.1" ieee754 "1.1.13" jmespath "0.15.0" @@ -2005,9 +2211,9 @@ aws-sign2@~0.7.0: integrity sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg= aws4@^1.8.0: - version "1.9.1" - resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.9.1.tgz#7e33d8f7d449b3f673cd72deb9abdc552dbe528e" - integrity sha512-wMHVg2EOHaMRxbzgFJ9gtjOOCrI80OHLG14rxi28XwOW8ux6IiEbRCGGGqCtdAIg4FQCbW20k9RsT4y3gJlFug== + version "1.10.1" + resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.10.1.tgz#e1e82e4f3e999e2cfd61b161280d16a111f86428" + integrity sha512-zg7Hz2k5lI8kb7U32998pRRFin7zJlkfezGJjUc2heaD4Pw2wObakCDVzkKztTm/Ln7eiVvYsjqak0Ed4LkMDA== azure-storage@2.10.3: version "2.10.3" @@ -2077,13 +2283,14 @@ babel-plugin-jest-hoist@^25.5.0: "@types/babel__traverse" "^7.0.6" babel-preset-current-node-syntax@^0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-0.1.2.tgz#fb4a4c51fe38ca60fede1dc74ab35eb843cb41d6" - integrity sha512-u/8cS+dEiK1SFILbOC8/rUI3ml9lboKuuMvZ/4aQnQmhecQAgPw5ew066C1ObnEAUmlx7dv/s2z52psWEtLNiw== + version "0.1.3" + resolved "https://registry.yarnpkg.com/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-0.1.3.tgz#b4b547acddbf963cba555ba9f9cbbb70bfd044da" + integrity sha512-uyexu1sVwcdFnyq9o8UQYsXwXflIh8LvrF5+cKrYam93ned1CStffB3+BEcsxGSgagoA3GEyjDqO4a/58hyPYQ== dependencies: "@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-json-strings" "^7.8.3" "@babel/plugin-syntax-logical-assignment-operators" "^7.8.3" "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" @@ -2163,10 +2370,10 @@ big.js@^5.2.2: resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328" integrity sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ== -bignumber.js@^7.0.0: - version "7.2.1" - resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-7.2.1.tgz#80c048759d826800807c4bfd521e50edbba57a5f" - integrity sha512-S4XzBk5sMB+Rcb/LNcpzXr57VRTxgAvaAEDAl1AwRx27j00hT84O6OkteE7u8UB3NuaaygCRrEpqox4uDOrbdQ== +bignumber.js@^9.0.0: + version "9.0.0" + resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-9.0.0.tgz#805880f84a329b5eac6e7cb6f8274b6d82bdf075" + integrity sha512-t/OYhhJ2SD+YGBQcjY8GzzDHEk9f3nerxjtfa6tlMXfe7frs/WozhvCNoGvpM0P3bNf3Gq5ZRMlGr5f3r4/N8A== bin-build@^3.0.0: version "3.0.0" @@ -2222,9 +2429,9 @@ binary-extensions@^1.0.0: integrity sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw== binary-extensions@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.0.0.tgz#23c0df14f6a88077f5f986c0d167ec03c3d5537c" - integrity sha512-Phlt0plgpIIBOGTT/ehfFnbNlfsDEiqmzE2KRXoX1bLIlir4X/MR+zSyBEkL05ffWgnRSf/DXv+WrUAVr93/ow== + version "2.1.0" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.1.0.tgz#30fa40c9e7fe07dbc895678cd287024dea241dd9" + integrity sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ== bindings@1.5.0, bindings@^1.3.0, bindings@^1.5.0: version "1.5.0" @@ -2233,13 +2440,33 @@ bindings@1.5.0, bindings@^1.3.0, bindings@^1.5.0: dependencies: file-uri-to-path "1.0.0" -bl@^1.0.0, bl@^1.2.2: - version "1.2.2" - resolved "https://registry.yarnpkg.com/bl/-/bl-1.2.2.tgz#a160911717103c07410cef63ef51b397c025af9c" - integrity sha512-e8tQYnZodmebYDWGH7KMRvtzKXaJHx3BbilrgZCfvyLUYdKpK1t5PSPmpkny/SgiTSCnjfLW7v5rlONXVFkQEA== +bintrees@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/bintrees/-/bintrees-1.0.1.tgz#0e655c9b9c2435eaab68bf4027226d2b55a34524" + integrity sha1-DmVcm5wkNeqraL9AJyJtK1WjRSQ= + +bitsyntax@~0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/bitsyntax/-/bitsyntax-0.1.0.tgz#b0c59acef03505de5a2ed62a2f763c56ae1d6205" + integrity sha512-ikAdCnrloKmFOugAfxWws89/fPc+nw0OOG1IzIE72uSOg/A3cYptKCjSUhDTuj7fhsJtzkzlv7l3b8PzRHLN0Q== dependencies: - readable-stream "^2.3.5" - safe-buffer "^5.1.1" + buffer-more-ints "~1.0.0" + debug "~2.6.9" + safe-buffer "~5.1.2" + +bl@^1.0.0, bl@^1.2.2, bl@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/bl/-/bl-4.0.3.tgz#12d6287adc29080e22a705e5764b2a9522cdc489" + integrity sha512-fs4G6/Hu4/EE+F75J8DuN/0IpQqNjAdC7aEQv7Qt8MHGUH7Ckv2MwTEEeN9QehD0pfIDkMI1bkHYkKy7xHyKIg== + dependencies: + buffer "^5.5.0" + inherits "^2.0.4" + readable-stream "^3.4.0" + +bluebird@^3.5.2: + version "3.7.2" + resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" + integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg== bluebird@~3.5.0: version "3.5.5" @@ -2341,15 +2568,15 @@ browserslist@4.7.0: electron-to-chromium "^1.3.247" node-releases "^1.1.29" -browserslist@^4.0.0, browserslist@^4.11.1, browserslist@^4.8.5: - version "4.12.0" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.12.0.tgz#06c6d5715a1ede6c51fc39ff67fd647f740b656d" - integrity sha512-UH2GkcEDSI0k/lRkuDSzFl9ZZ87skSy9w2XAn1MsZnL+4c4rqbBd3e82UWHbYDpztABrPBhZsTEeuxVfHppqDg== +browserslist@^4.0.0, browserslist@^4.12.0, browserslist@^4.8.5: + version "4.14.0" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.14.0.tgz#2908951abfe4ec98737b72f34c3bcedc8d43b000" + integrity sha512-pUsXKAF2lVwhmtpeA3LJrZ76jXuusrNyhduuQs7CDFf9foT4Y38aQOserd2lMe5DSSrjf3fx34oHwryuvxAUgQ== dependencies: - caniuse-lite "^1.0.30001043" - electron-to-chromium "^1.3.413" - node-releases "^1.1.53" - pkg-up "^2.0.0" + caniuse-lite "^1.0.30001111" + electron-to-chromium "^1.3.523" + escalade "^3.0.2" + node-releases "^1.1.60" bs-logger@0.x: version "0.2.6" @@ -2398,10 +2625,15 @@ buffer-from@1.x, buffer-from@^1.0.0: resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A== -buffer@4.9.1: - version "4.9.1" - resolved "https://registry.yarnpkg.com/buffer/-/buffer-4.9.1.tgz#6d1bb601b07a4efced97094132093027c95bc298" - integrity sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg= +buffer-more-ints@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/buffer-more-ints/-/buffer-more-ints-1.0.0.tgz#ef4f8e2dddbad429ed3828a9c55d44f05c611422" + integrity sha512-EMetuGFz5SLsT0QTnXzINh4Ksr+oo4i+UGTXEshiGCQWnsgSs7ZhJ8fzlwQ+OzEMs0MpDAMr1hxnblp5a4vcHg== + +buffer@4.9.2: + version "4.9.2" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-4.9.2.tgz#230ead344002988644841ab0244af8c44bbe3ef8" + integrity sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg== dependencies: base64-js "^1.0.2" ieee754 "^1.1.4" @@ -2415,18 +2647,28 @@ buffer@^5.2.1, buffer@^5.5.0: base64-js "^1.0.2" ieee754 "^1.1.4" +bufrw@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/bufrw/-/bufrw-1.3.0.tgz#28d6cfdaf34300376836310f5c31d57eeb40c8fa" + integrity sha512-jzQnSbdJqhIltU9O5KUiTtljP9ccw2u5ix59McQy4pV2xGhVLhRZIndY8GIrgh5HjXa6+QJ9AQhOd2QWQizJFQ== + dependencies: + ansi-color "^0.2.1" + error "^7.0.0" + hexer "^1.5.0" + xtend "^4.0.0" + builtin-modules@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f" integrity sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8= bunyan@^1.8.12: - version "1.8.12" - resolved "https://registry.yarnpkg.com/bunyan/-/bunyan-1.8.12.tgz#f150f0f6748abdd72aeae84f04403be2ef113797" - integrity sha1-8VDw9nSKvdcq6uhPBEA74u8RN5c= + version "1.8.14" + resolved "https://registry.yarnpkg.com/bunyan/-/bunyan-1.8.14.tgz#3d8c1afea7de158a5238c7cb8a66ab6b38dd45b4" + integrity sha512-LlahJUxXzZLuw/hetUQJmRgZ1LF6+cr5TPpRj6jf327AsiIq2jhYEH4oqUUkVKTor+9w2BT3oxVwhzE5lw9tcg== optionalDependencies: dtrace-provider "~0.8" - moment "^2.10.6" + moment "^2.19.3" mv "~2" safe-json-stringify "~1" @@ -2545,10 +2787,10 @@ caniuse-api@^3.0.0: lodash.memoize "^4.1.2" lodash.uniq "^4.5.0" -caniuse-lite@^1.0.0, caniuse-lite@^1.0.30000989, caniuse-lite@^1.0.30001039, caniuse-lite@^1.0.30001043: - version "1.0.30001055" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001055.tgz#7b52c3537f7a8c0408aca867e83d2b04268b54cd" - integrity sha512-MbwsBmKrBSKIWldfdIagO5OJWZclpJtS4h0Jrk/4HFrXJxTdVdH23Fd+xCiHriVGvYcWyW8mR/CPsYajlH8Iuw== +caniuse-lite@^1.0.0, caniuse-lite@^1.0.30000989, caniuse-lite@^1.0.30001109, caniuse-lite@^1.0.30001111: + version "1.0.30001114" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001114.tgz#2e88119afb332ead5eaa330e332e951b1c4bfea9" + integrity sha512-ml/zTsfNBM+T1+mjglWRPgVsu2L76GAaADKX5f4t0pbhttEp0WMawJsHDYlFkVZkoA+89uvBRrVrEE4oqenzXQ== capital-case@^1.0.3: version "1.0.3" @@ -2617,9 +2859,9 @@ chalk@^3.0.0: supports-color "^7.1.0" chalk@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.0.0.tgz#6e98081ed2d17faab615eb52ac66ec1fe6209e72" - integrity sha512-N9oWFcegS0sFr9oh1oz2d7Npos6vNoWW9HvtCg5N1KRFpUhaAhvTv5Y58g880fZaEYSNm3qDz8SU1UrGvp+n7A== + version "4.1.0" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.0.tgz#4e14870a618d9e2edd97dd8345fd9d9dc315646a" + integrity sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A== dependencies: ansi-styles "^4.1.0" supports-color "^7.1.0" @@ -2689,9 +2931,9 @@ chokidar@^2.0.4: fsevents "^1.2.7" chokidar@^3.0.2: - version "3.4.0" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.4.0.tgz#b30611423ce376357c765b9b8f904b9fba3c0be8" - integrity sha512-aXAaho2VJtisB/1fg1+3nlLJqGOuewTzQpd/Tz0yTg2R0e4IGtshYvtjowyEumcBv2z+y4+kc75Mz7j5xJskcQ== + version "3.4.2" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.4.2.tgz#38dc8e658dec3809741eb3ef7bb0a47fe424232d" + integrity sha512-IZHaDeBeI+sZJRX7lGcXsdzgvZqKv6sECqsbErJA4mHWfpRrD8B97kSFN4cQz6nGBGiuFia1MKR4d6c1o8Cv7A== dependencies: anymatch "~3.1.1" braces "~3.0.2" @@ -2879,6 +3121,11 @@ color@^3.0.0: color-convert "^1.9.1" color-string "^1.5.2" +colorette@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/colorette/-/colorette-1.2.1.tgz#4d0b921325c14faf92633086a536db6e89564b1b" + integrity sha512-puCDz0CzydiSYOrnXpz/PKd69zRrribezjtE9yd4zvytoRc8+RY/KJPvtPFKZS3E3wP6neGyMe0vOTlHO5L3Pw== + colour@~0.7.1: version "0.7.1" resolved "https://registry.yarnpkg.com/colour/-/colour-0.7.1.tgz#9cb169917ec5d12c0736d3e8685746df1cadf778" @@ -2891,7 +3138,7 @@ combined-stream@^1.0.6, combined-stream@^1.0.8, combined-stream@~1.0.6: dependencies: delayed-stream "~1.0.0" -commander@^2.12.1, commander@^2.20.0: +commander@^2.12.1, commander@^2.20.0, commander@^2.8.1: version "2.20.3" resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== @@ -2901,13 +3148,6 @@ commander@^5.0.0: resolved "https://registry.yarnpkg.com/commander/-/commander-5.1.0.tgz#46abbd1652f8e059bddaef99bbdcb2ad9cf179ae" integrity sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg== -commander@~2.8.1: - version "2.8.1" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.8.1.tgz#06be367febfda0c330aa1e2a072d3dc9762425d4" - integrity sha1-Br42f+v9oMMwqh4qBy09yXYkJdQ= - dependencies: - graceful-readlink ">= 1.0.0" - commondir@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" @@ -3091,9 +3331,9 @@ cross-spawn@^5.0.1: which "^1.2.9" cross-spawn@^7.0.0: - version "7.0.2" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.2.tgz#d0d7dcfa74e89115c7619f4f721a94e1fdb716d6" - integrity sha512-PD6G8QG3S4FK/XCGFbEQrDqO2AnMMsy0meR7lerlIOHAAbkuavGU/pOqprrlvfTNjvowivTeBsjebAL0NSoMxw== + version "7.0.3" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" + integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== dependencies: path-key "^3.1.0" shebang-command "^2.0.0" @@ -3173,9 +3413,9 @@ css-what@2.1: integrity sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg== css-what@^3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/css-what/-/css-what-3.2.1.tgz#f4a8f12421064621b456755e34a03a2c22df5da1" - integrity sha512-WwOrosiQTvyms+Ti5ZC5vGEK0Vod3FTt1ca+payZqvKuGJF+dq7bG63DstxtN0dpm6FxY27a/zS3Wten+gEtGw== + version "3.3.0" + resolved "https://registry.yarnpkg.com/css-what/-/css-what-3.3.0.tgz#10fec696a9ece2e591ac772d759aacabac38cd39" + integrity sha512-pv9JPyatiPaQ6pf4OvD/dbfm0o5LviWmwxNWzblYf/1u9QZd0ihV+PMwy5jdQWQ3349kZmKEx9WXuSka2dM4cg== cssesc@^3.0.0: version "3.0.0" @@ -3307,7 +3547,7 @@ date-and-time@^0.12.0: resolved "https://registry.yarnpkg.com/date-and-time/-/date-and-time-0.12.0.tgz#6d30c91c47fa72edadd628b71ec2ac46909b9267" integrity sha512-n2RJIAp93AucgF/U/Rz5WRS2Hjg5Z+QxscaaMCi6pVZT1JpJKRH+C08vyH/lRR1kxNXnPxgo3lWfd+jCb/UcuQ== -debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.0: +debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.0, debug@~2.6.9: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== @@ -3507,10 +3747,10 @@ diff-sequences@^25.2.6: resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-25.2.6.tgz#5f467c00edd35352b7bca46d7927d60e687a76dd" integrity sha512-Hq8o7+6GaZeoFjtpgvRBUknSXNeJiCx7V9Fr94ZMljNiCr9n9L8H8aJqgWOQiDDGdyn29fRNcDdRVJ5fdyihfg== -diff-sequences@^26.0.0: - version "26.0.0" - resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-26.0.0.tgz#0760059a5c287637b842bd7085311db7060e88a6" - integrity sha512-JC/eHYEC3aSS0vZGjuoc4vHA0yAQTzhQQldXMeMF+JlxLGJlCO38Gma82NV9gk1jGFz8mDzUMeaKXvjRRdJ2dg== +diff-sequences@^26.3.0: + version "26.3.0" + resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-26.3.0.tgz#62a59b1b29ab7fd27cef2a33ae52abe73042d0a2" + integrity sha512-5j5vdRcw3CNctePNYN0Wy2e/JbWT6cAYnXv5OuqPhDpyCGc0uLu2TK0zOCJWNB9kOIfYMSpIulRaDgIi4HJ6Ig== diff@^4.0.1: version "4.0.2" @@ -3698,9 +3938,9 @@ duplexer3@^0.1.4: integrity sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI= duplexer@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.1.tgz#ace6ff808c1ce66b57d1ebf97977acb02334cfc1" - integrity sha1-rOb/gIwc5mtX0ev5eXessCM0z8E= + version "0.1.2" + resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.2.tgz#3abe43aef3835f8ae077d136ddce0f276b0400e6" + integrity sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg== duplexify@^3.5.0, duplexify@^3.6.0: version "3.7.1" @@ -3742,10 +3982,10 @@ ee-first@1.1.1: resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= -electron-to-chromium@^1.3.247, electron-to-chromium@^1.3.413: - version "1.3.432" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.432.tgz#3bf7b191978ff2e8bc3caf811bb52b1e9f9eab25" - integrity sha512-/GdNhXyLP5Yl2322CUX/+Xi8NhdHBqL6lD9VJVKjH6CjoPGakvwZ5CpKgj/oOlbzuWWjOvMjDw1bBuAIRCNTlw== +electron-to-chromium@^1.3.247, electron-to-chromium@^1.3.523: + version "1.3.533" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.533.tgz#d7e5ca4d57e9bc99af87efbe13e7be5dde729b0f" + integrity sha512-YqAL+NXOzjBnpY+dcOKDlZybJDCOzgsq4koW3fvyty/ldTmsb4QazZpOWmVvZ2m0t5jbBf7L0lIGU3BUipwG+A== emitter-listener@^1.1.2: version "1.1.2" @@ -3787,9 +4027,14 @@ entities@^1.1.1, entities@~1.1.1: integrity sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w== entities@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/entities/-/entities-2.0.2.tgz#ac74db0bba8d33808bbf36809c3a5c3683531436" - integrity sha512-dmD3AvJQBUjKpcNkoqr+x+IF0SdRtPz9Vk0uTy4yWqga9ibB6s4v++QFWNohjiUGoMlF552ZvNyXDxz5iW0qmw== + version "2.0.3" + resolved "https://registry.yarnpkg.com/entities/-/entities-2.0.3.tgz#5c487e5742ab93c15abb5da22759b8590ec03b7f" + integrity sha512-MyoZ0jgnLvB2X3Lg5HqpFmn1kybDiIfEQmKzTb5apr51Rb+T3KdmMiqa70T+bhGnyv7bQ6WMj2QMHpGMmlrUYQ== + +env-paths@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-2.2.0.tgz#cdca557dc009152917d6166e2febe1f039685e43" + integrity sha512-6u0VYSCo/OW6IoD5WCLLy9JUGARbamfSavcNXry/eu8aHVFei6CD3Sw+VGX5alea1i9pgPHW0mbu6Xj0uBh7gA== error-ex@^1.2.0, error-ex@^1.3.1: version "1.3.2" @@ -3798,6 +4043,14 @@ error-ex@^1.2.0, error-ex@^1.3.1: dependencies: is-arrayish "^0.2.1" +error@7.0.2: + version "7.0.2" + resolved "https://registry.yarnpkg.com/error/-/error-7.0.2.tgz#a5f75fff4d9926126ddac0ea5dc38e689153cb02" + integrity sha1-pfdf/02ZJhJt2sDqXcOOaJFTywI= + dependencies: + string-template "~0.2.1" + xtend "~4.0.0" + error@^7.0.0: version "7.2.1" resolved "https://registry.yarnpkg.com/error/-/error-7.2.1.tgz#eab21a4689b5f684fc83da84a0e390de82d94894" @@ -3806,21 +4059,21 @@ error@^7.0.0: string-template "~0.2.1" es-abstract@^1.17.0-next.1, es-abstract@^1.17.2, es-abstract@^1.17.5: - version "1.17.5" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.17.5.tgz#d8c9d1d66c8981fb9200e2251d799eee92774ae9" - integrity sha512-BR9auzDbySxOcfog0tLECW8l28eRGpDpU3Dm3Hp4q/N+VtLTmyj4EUN088XZWQDW/hzj6sYRDXeOFsaAODKvpg== + version "1.17.6" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.17.6.tgz#9142071707857b2cacc7b89ecb670316c3e2d52a" + integrity sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw== dependencies: es-to-primitive "^1.2.1" function-bind "^1.1.1" has "^1.0.3" has-symbols "^1.0.1" - is-callable "^1.1.5" - is-regex "^1.0.5" + is-callable "^1.2.0" + is-regex "^1.1.0" object-inspect "^1.7.0" object-keys "^1.1.1" object.assign "^4.1.0" - string.prototype.trimleft "^2.1.1" - string.prototype.trimright "^2.1.1" + string.prototype.trimend "^1.0.1" + string.prototype.trimstart "^1.0.1" es-to-primitive@^1.2.1: version "1.2.1" @@ -3836,6 +4089,11 @@ es6-promise@^4.2.8: resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.8.tgz#4eb21594c972bc40553d276e510539143db53e0a" integrity sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w== +escalade@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.0.2.tgz#6a580d70edb87880f22b4c91d0d56078df6962c4" + integrity sha512-gPYAU37hYCUhW5euPeR+Y74F7BL+IBsV93j5cvGriSaD1aG6MGsqsV1yamRdrWrb2j3aiZvb0X+UBOWpx3JWtQ== + escape-html@~1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" @@ -3852,9 +4110,9 @@ escape-string-regexp@^2.0.0: integrity sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w== escodegen@^1.11.1: - version "1.14.1" - resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.14.1.tgz#ba01d0c8278b5e95a9a45350142026659027a457" - integrity sha512-Bmt7NcRySdIfNPfU2ZoXDrrXsG9ZjvDxcAlMfDUgRBjLOWTuIACXPBFJH7Z+cLb40JeQco5toikyc9t9P8E9SQ== + version "1.14.3" + resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.14.3.tgz#4e7b81fba61581dc97582ed78cab7f0e8d63f503" + integrity sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw== dependencies: esprima "^4.0.1" estraverse "^4.2.0" @@ -4025,15 +4283,15 @@ expand-range@^1.8.1: fill-range "^2.1.0" expect@*: - version "26.0.1" - resolved "https://registry.yarnpkg.com/expect/-/expect-26.0.1.tgz#18697b9611a7e2725e20ba3ceadda49bc9865421" - integrity sha512-QcCy4nygHeqmbw564YxNbHTJlXh47dVID2BUP52cZFpLU9zHViMFK6h07cC1wf7GYCTIigTdAXhVua8Yl1FkKg== + version "26.4.0" + resolved "https://registry.yarnpkg.com/expect/-/expect-26.4.0.tgz#34a0aae523343b0931ff1cf0aa972dfe40edfab4" + integrity sha512-dbYDJhFcqQsamlos6nEwAMe+ahdckJBk5fmw1DYGLQGabGSlUuT+Fm2jHYw5119zG3uIhP+lCQbjJhFEdZMJtg== dependencies: - "@jest/types" "^26.0.1" + "@jest/types" "^26.3.0" ansi-styles "^4.0.0" - jest-get-type "^26.0.0" - jest-matcher-utils "^26.0.1" - jest-message-util "^26.0.1" + jest-get-type "^26.3.0" + jest-matcher-utils "^26.4.0" + jest-message-util "^26.3.0" jest-regex-util "^26.0.0" expect@^25.5.0: @@ -4158,9 +4416,9 @@ extsprintf@^1.2.0: integrity sha1-4mifjzVvrWLMplo6kcXfX5VRaS8= fast-deep-equal@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz#545145077c501491e33b15ec408c294376e94ae4" - integrity sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA== + version "3.1.3" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" + integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== fast-diff@^1.1.1: version "1.2.0" @@ -4195,9 +4453,9 @@ fast-levenshtein@~2.0.6: integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= fast-text-encoding@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/fast-text-encoding/-/fast-text-encoding-1.0.2.tgz#ff1ad5677bde049e0f8656aa6083a7ef2c5836e2" - integrity sha512-5rQdinSsycpzvAoHga2EDn+LRX1d5xLFsuNG0Kg61JrAT/tASXcLL0nf/33v+sAxlQcfYmWbTURa1mmAf55jGw== + version "1.0.3" + resolved "https://registry.yarnpkg.com/fast-text-encoding/-/fast-text-encoding-1.0.3.tgz#ec02ac8e01ab8a319af182dae2681213cfe9ce53" + integrity sha512-dtm4QZH9nZtcDt8qJiOH9fcQd1NAgi+K1O2DbE6GG1PPCK/BWfOH3idCTRQ4ImXRUOyopDEgDEnVEE7Y/2Wrig== faye-websocket@~0.10.0: version "0.10.0" @@ -4542,6 +4800,17 @@ gaxios@^2.0.0, gaxios@^2.0.1, gaxios@^2.1.0: is-stream "^2.0.0" node-fetch "^2.3.0" +gaxios@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/gaxios/-/gaxios-3.1.0.tgz#95f65f5a335f61aff602fe124cfdba8524f765fa" + integrity sha512-DDTn3KXVJJigtz+g0J3vhcfbDbKtAroSTxauWsdnP57sM5KZ3d2c/3D9RKFJ86s43hfw6WULg6TXYw/AYiBlpA== + dependencies: + abort-controller "^3.0.0" + extend "^3.0.2" + https-proxy-agent "^5.0.0" + is-stream "^2.0.0" + node-fetch "^2.3.0" + gaze@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/gaze/-/gaze-1.1.3.tgz#c441733e13b927ac8c0ff0b4c3b033f28812924a" @@ -4557,6 +4826,14 @@ gcp-metadata@^3.4.0: gaxios "^2.1.0" json-bigint "^0.3.0" +gcp-metadata@^4.1.0: + version "4.1.4" + resolved "https://registry.yarnpkg.com/gcp-metadata/-/gcp-metadata-4.1.4.tgz#3adadb9158c716c325849ee893741721a3c09e7e" + integrity sha512-5J/GIH0yWt/56R3dNaNWPGQ/zXsZOddYECfJaqxFWgrZ9HC2Kvc5vl9upOgUUHKzURjAVf2N+f6tEJiojqXUuA== + dependencies: + gaxios "^3.0.0" + json-bigint "^1.0.0" + gcs-resumable-upload@^2.2.4: version "2.3.3" resolved "https://registry.yarnpkg.com/gcs-resumable-upload/-/gcs-resumable-upload-2.3.3.tgz#02c616ed17eff6676e789910aeab3907d412c5f8" @@ -4576,7 +4853,7 @@ gcstats.js@1.0.0: dependencies: nan "^2.0.5" -generic-pool@^3.6.1: +generic-pool@^3.7.1: version "3.7.1" resolved "https://registry.yarnpkg.com/generic-pool/-/generic-pool-3.7.1.tgz#36fe5bb83e7e0e032e5d32cd05dc00f5ff119aa8" integrity sha512-ug6DAZoNgWm6q5KhPFA+hzXfBLFQu5sTXxPpv44DmE0A2g+CiHoq9LTVdkXpZMkYVMoGw83F6W+WT0h0MFMK/w== @@ -4591,6 +4868,11 @@ get-caller-file@^2.0.1: resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== +get-package-type@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/get-package-type/-/get-package-type-0.1.0.tgz#8de2d803cff44df3bc6c456e6668b36c3926e11a" + integrity sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q== + get-proxy@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/get-proxy/-/get-proxy-2.1.0.tgz#349f2b4d91d44c4d4d4e9cba2ad90143fac5ef93" @@ -4624,9 +4906,9 @@ get-stream@^4.0.0: pump "^3.0.0" get-stream@^5.0.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.1.0.tgz#01203cdc92597f9b909067c3e656cc1f4d3c4dc9" - integrity sha512-EXr1FOzrzTfGeL0gQdeFEvOMm2mzMOglyiOXSTpPC+iAjAKftbr3jpCMWynogwYnM+eSj9sHGc6wjIcDvYiygw== + version "5.2.0" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.2.0.tgz#4966a1795ee5ace65e706c4b7beb71257d6e22d3" + integrity sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA== dependencies: pump "^3.0.0" @@ -4730,12 +5012,12 @@ globby@8.0.2, globby@^8.0.1: slash "^1.0.0" globule@^1.0.0: - version "1.3.1" - resolved "https://registry.yarnpkg.com/globule/-/globule-1.3.1.tgz#90a25338f22b7fbeb527cee63c629aea754d33b9" - integrity sha512-OVyWOHgw29yosRHCHo7NncwR1hW5ew0W/UrvtwvjefVJeQ26q4/8r8FmPsSF1hJ93IgWkyv16pCTz6WblMzm/g== + version "1.3.2" + resolved "https://registry.yarnpkg.com/globule/-/globule-1.3.2.tgz#d8bdd9e9e4eef8f96e245999a5dee7eb5d8529c4" + integrity sha512-7IDTQTIu2xzXkT+6mlluidnWo+BypnbSoEVVQCGfzqnl5Ik8d3e1d4wycb8Rj9tWW+Z39uPWsdlquqiqPCd/pA== dependencies: glob "~7.1.1" - lodash "~4.17.12" + lodash "~4.17.10" minimatch "~3.0.2" good-listener@^1.2.2: @@ -4760,6 +5042,41 @@ google-auth-library@^5.0.0, google-auth-library@^5.5.0: jws "^4.0.0" lru-cache "^5.0.0" +google-auth-library@^6.0.0: + version "6.0.6" + resolved "https://registry.yarnpkg.com/google-auth-library/-/google-auth-library-6.0.6.tgz#5102e5c643baab45b4c16e9752cd56b8861f3a82" + integrity sha512-fWYdRdg55HSJoRq9k568jJA1lrhg9i2xgfhVIMJbskUmbDpJGHsbv9l41DGhCDXM21F9Kn4kUwdysgxSYBYJUw== + dependencies: + arrify "^2.0.0" + base64-js "^1.3.0" + ecdsa-sig-formatter "^1.0.11" + fast-text-encoding "^1.0.0" + gaxios "^3.0.0" + gcp-metadata "^4.1.0" + gtoken "^5.0.0" + jws "^4.0.0" + lru-cache "^6.0.0" + +google-gax@^2.1.0: + version "2.7.0" + resolved "https://registry.yarnpkg.com/google-gax/-/google-gax-2.7.0.tgz#5aaff7bdbe32730f975f416dd4897c558c89ab84" + integrity sha512-0dBATy8mMVlfOBrT85Q+NzBpZ4OJZUMrPI9wJULpiIDq2w1zlN30Duor+fQUcMEjanYEc72G58M4iUVve0jfXw== + dependencies: + "@grpc/grpc-js" "~1.1.1" + "@grpc/proto-loader" "^0.5.1" + "@types/long" "^4.0.0" + abort-controller "^3.0.0" + duplexify "^3.6.0" + google-auth-library "^6.0.0" + is-stream-ended "^0.1.4" + lodash.at "^4.6.0" + lodash.has "^4.5.2" + node-fetch "^2.6.0" + protobufjs "^6.9.0" + retry-request "^4.0.0" + semver "^6.0.0" + walkdir "^0.4.0" + google-p12-pem@^2.0.0: version "2.0.4" resolved "https://registry.yarnpkg.com/google-p12-pem/-/google-p12-pem-2.0.4.tgz#036462394e266472632a78b685f0cc3df4ef337b" @@ -4767,6 +5084,13 @@ google-p12-pem@^2.0.0: dependencies: node-forge "^0.9.0" +google-p12-pem@^3.0.0: + version "3.0.2" + resolved "https://registry.yarnpkg.com/google-p12-pem/-/google-p12-pem-3.0.2.tgz#12d443994b6f4cd8c9e4ac479f2f18d4694cbdb8" + integrity sha512-tbjzndQvSIHGBLzHnhDs3cL4RBjLbLXc2pYvGH+imGVu5b4RMAttUTdnmW2UH0t11QeBTXZ7wlXPS7hrypO/tg== + dependencies: + node-forge "^0.9.0" + google-protobuf@3.6.1: version "3.6.1" resolved "https://registry.yarnpkg.com/google-protobuf/-/google-protobuf-3.6.1.tgz#7ef58e2bea137a93cdaf5cfd5afa5f6abdd92025" @@ -4815,16 +5139,11 @@ got@^8.3.1, got@^8.3.2: url-parse-lax "^3.0.0" url-to-options "^1.0.1" -graceful-fs@^4.1.10, graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.1.9, graceful-fs@^4.2.0, graceful-fs@^4.2.4: +graceful-fs@^4.1.10, graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.1.9, graceful-fs@^4.2.0, graceful-fs@^4.2.2, graceful-fs@^4.2.4: version "4.2.4" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.4.tgz#2256bde14d3632958c465ebc96dc467ca07a29fb" integrity sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw== -"graceful-readlink@>= 1.0.0": - version "1.0.1" - resolved "https://registry.yarnpkg.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725" - integrity sha1-TK+tdrxi8C+gObL5Tpo906ORpyU= - gray-matter@^2.1.0: version "2.1.1" resolved "https://registry.yarnpkg.com/gray-matter/-/gray-matter-2.1.1.tgz#3042d9adec2a1ded6a7707a9ed2380f8a17a430e" @@ -4841,16 +5160,16 @@ growly@^1.3.0: resolved "https://registry.yarnpkg.com/growly/-/growly-1.3.0.tgz#f10748cbe76af964b7c96c93c6bcc28af120c081" integrity sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE= -grpc@1.24.2: - version "1.24.2" - resolved "https://registry.yarnpkg.com/grpc/-/grpc-1.24.2.tgz#76d047bfa7b05b607cbbe3abb99065dcefe0c099" - integrity sha512-EG3WH6AWMVvAiV15d+lr+K77HJ/KV/3FvMpjKjulXHbTwgDZkhkcWbwhxFAoTdxTkQvy0WFcO3Nog50QBbHZWw== +grpc@1.24.3: + version "1.24.3" + resolved "https://registry.yarnpkg.com/grpc/-/grpc-1.24.3.tgz#92efe28dfc1250dca179b8133e40b4f2341473d9" + integrity sha512-EDemzuZTfhM0hgrXqC4PtR76O3t+hTIYJYR5vgiW0yt2WJqo4mhxUqZUirzUQz34Psz7dbLp38C6Cl7Ij2vXRQ== dependencies: "@types/bytebuffer" "^5.0.40" lodash.camelcase "^4.3.0" lodash.clone "^4.5.0" nan "^2.13.2" - node-pre-gyp "^0.14.0" + node-pre-gyp "^0.15.0" protobufjs "^5.0.3" gtoken@^4.1.0: @@ -4863,6 +5182,16 @@ gtoken@^4.1.0: jws "^4.0.0" mime "^2.2.0" +gtoken@^5.0.0: + version "5.0.3" + resolved "https://registry.yarnpkg.com/gtoken/-/gtoken-5.0.3.tgz#b76ef8e9a2fed6fef165e47f7d05b60c498e4d05" + integrity sha512-Nyd1wZCMRc2dj/mAD0LlfQLcAO06uKdpKJXvK85SGrF5+5+Bpfil9u/2aw35ltvEHjvl0h5FMKN5knEU+9JrOg== + dependencies: + gaxios "^3.0.0" + google-p12-pem "^3.0.0" + jws "^4.0.0" + mime "^2.2.0" + gulp-header@^1.7.1: version "1.8.12" resolved "https://registry.yarnpkg.com/gulp-header/-/gulp-header-1.8.12.tgz#ad306be0066599127281c4f8786660e705080a84" @@ -4886,11 +5215,11 @@ har-schema@^2.0.0: integrity sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI= har-validator@~5.1.3: - version "5.1.3" - resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.3.tgz#1ef89ebd3e4996557675eed9893110dc350fa080" - integrity sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g== + version "5.1.5" + resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.5.tgz#1f0803b9f8cb20c0fa13822df1ecddb36bde1efd" + integrity sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w== dependencies: - ajv "^6.5.5" + ajv "^6.12.3" har-schema "^2.0.0" has-ansi@^2.0.0: @@ -4980,9 +5309,9 @@ hash-base@^3.0.0: safe-buffer "^5.2.0" hash-stream-validation@^0.2.2: - version "0.2.2" - resolved "https://registry.yarnpkg.com/hash-stream-validation/-/hash-stream-validation-0.2.2.tgz#6b34c4fce5e9fce265f1d3380900049d92a10090" - integrity sha512-cMlva5CxWZOrlS/cY0C+9qAzesn5srhFA8IT1VPiHc9bWWBLkJfEUIZr7MWoi89oOOGmpg8ymchaOjiArsGu5A== + version "0.2.3" + resolved "https://registry.yarnpkg.com/hash-stream-validation/-/hash-stream-validation-0.2.3.tgz#44e3479d1767c4f1d6924cc2da61eca08ebba8af" + integrity sha512-OEohGLoUOh+bwsIpHpdvhIXFyRGjeLqJbT8Yc5QTZPbRM7LKywagTQxnX/6mghLDOrD9YGz88hy5mLN2eKflYQ== dependencies: through2 "^2.0.0" @@ -5004,20 +5333,30 @@ hex2dec@1.0.1: resolved "https://registry.yarnpkg.com/hex2dec/-/hex2dec-1.0.1.tgz#949bb33f1fdbbeab20e06403a00fc7d5ff284207" integrity sha1-lJuzPx/bvqsg4GQDoA/H1f8oQgc= +hexer@^1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/hexer/-/hexer-1.5.0.tgz#b86ce808598e8a9d1892c571f3cedd86fc9f0653" + integrity sha1-uGzoCFmOip0YksVx887dhvyfBlM= + dependencies: + ansi-color "^0.2.1" + minimist "^1.1.0" + process "^0.10.0" + xtend "^4.0.0" + highlight.js@^9.15.8: - version "9.18.1" - resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-9.18.1.tgz#ed21aa001fe6252bb10a3d76d47573c6539fe13c" - integrity sha512-OrVKYz70LHsnCgmbXctv/bfuvntIKDz177h0Co37DQ5jamGZLVmoCVMtjMtNZY3X9DrCcKfklHPNeA0uPZhSJg== + version "9.18.3" + resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-9.18.3.tgz#a1a0a2028d5e3149e2380f8a865ee8516703d634" + integrity sha512-zBZAmhSupHIl5sITeMqIJnYCDfAEc3Gdkqj65wC1lpI468MMQeeQkhcIAvk+RylAkxrCcI9xy9piHiXeQ1BdzQ== hosted-git-info@^2.1.4: version "2.8.8" resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.8.tgz#7539bd4bc1e0e0a895815a2e0262420b12858488" integrity sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg== -hot-shots@7.4.2: - version "7.4.2" - resolved "https://registry.yarnpkg.com/hot-shots/-/hot-shots-7.4.2.tgz#45e98fd4e86b71def59b4b17b25f5f9badf46c51" - integrity sha512-oy+ZkKq+jwsuA2FXnSAXCTqdONC8hbqOTwRwRze2ALZedPUpJIs5fvSzxIola3uSIiw488fZiz7gr5PyAtjOow== +hot-shots@7.8.0: + version "7.8.0" + resolved "https://registry.yarnpkg.com/hot-shots/-/hot-shots-7.8.0.tgz#c270f8c263ac7ee8f023e49fcb5e76a1c04dec73" + integrity sha512-27bQMXnjLnvgVnk8Bv1xFmGahL0d4HXxFYFVv3VdvvE8DkwNkFGxJary7qnY0ZDV7+OHAn3mcuvperTsZcyB/w== optionalDependencies: unix-dgram "2.0.x" @@ -5087,10 +5426,10 @@ http-errors@~1.7.2: statuses ">= 1.5.0 < 2" toidentifier "1.0.0" -"http-parser-js@>=0.4.0 <0.4.11": - version "0.4.10" - resolved "https://registry.yarnpkg.com/http-parser-js/-/http-parser-js-0.4.10.tgz#92c9c1374c35085f75db359ec56cc257cbb93fa4" - integrity sha1-ksnBN0w1CF912zWexWzCV8u5P6Q= +http-parser-js@>=0.5.1: + version "0.5.2" + resolved "https://registry.yarnpkg.com/http-parser-js/-/http-parser-js-0.5.2.tgz#da2e31d237b393aae72ace43882dd7e270a8ff77" + integrity sha512-opCO9ASqg5Wy2FNo7A0sxy71yGbbkJJXLdgMK04Tcypw9jr2MgWbyubb0+WdmDmGnFflO7fRbqbaihh/ENDlRQ== http-proxy-agent@^4.0.0: version "4.0.1" @@ -5304,9 +5643,9 @@ inquirer@7.1.0: through "^2.3.6" interpret@^1.0.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.2.0.tgz#d5061a6224be58e8083985f5014d844359576296" - integrity sha512-mT34yGKMNceBQUoVn7iCDKDntA7SC6gycMAWzGx1z/CMCTV7b2AAtXlo3nRyHZ1FelRkQbQjprHSYGwzLtkVbw== + version "1.4.0" + resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.4.0.tgz#665ab8bc4da27a774a40584e812e3e0fa45b1a1e" + integrity sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA== into-stream@^3.1.0: version "3.1.0" @@ -5396,10 +5735,10 @@ is-buffer@^1.1.5: resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== -is-callable@^1.1.4, is-callable@^1.1.5: - version "1.1.5" - resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.5.tgz#f7e46b596890456db74e7f6e976cb3273d06faab" - integrity sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q== +is-callable@^1.1.4, is-callable@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.0.tgz#83336560b54a38e35e3a2df7afd0454d691468bb" + integrity sha512-pyVD9AaGLxtg6srb2Ng6ynWJqkHU9bEM087AKck0w8QwDarTfNcpIYoU8x8Hv2Icm8u6kFJM18Dag8lyqGkviw== is-ci@^2.0.0: version "2.0.0" @@ -5463,9 +5802,9 @@ is-directory@^0.3.1: integrity sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE= is-docker@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.0.0.tgz#2cb0df0e75e2d064fe1864c37cdeacb7b2dcf25b" - integrity sha512-pJEdRugimx4fBMra5z2/5iRdZ63OhYV0vr0Dwm5+xtW4D1FvRkB8hamMIhnWfyJeDdyr/aa7BDyNbtG38VxgoQ== + version "2.1.1" + resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.1.1.tgz#4125a88e44e450d384e09047ede71adc2d144156" + integrity sha512-ZOoqiXfEwtGknTiuDEy8pN2CfE3TxMHprvNer1mXiqwkOT77Rw3YVrUQ52EqAOU3QAWDQ+bQdx7HJzrv7LS2Hw== is-extendable@^0.1.0, is-extendable@^0.1.1: version "0.1.1" @@ -5593,12 +5932,12 @@ is-png@^1.0.0: resolved "https://registry.yarnpkg.com/is-png/-/is-png-1.1.0.tgz#d574b12bf275c0350455570b0e5b57ab062077ce" integrity sha1-1XSxK/J1wDUEVVcLDltXqwYgd84= -is-regex@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.5.tgz#39d589a358bf18967f726967120b8fc1aed74eae" - integrity sha512-vlKW17SNq44owv5AQR3Cq0bQPEb8+kF3UKZ2fiZNOWtztYE5i0CzCZxFDwO58qAOWtxdBRVO/V5Qin1wjCqFYQ== +is-regex@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.1.tgz#c6f98aacc546f6cec5468a07b7b153ab564a57b9" + integrity sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg== dependencies: - has "^1.0.3" + has-symbols "^1.0.1" is-resolvable@^1.0.0: version "1.1.0" @@ -5615,6 +5954,11 @@ is-root@2.1.0: resolved "https://registry.yarnpkg.com/is-root/-/is-root-2.1.0.tgz#809e18129cf1129644302a4f8544035d51984a9c" integrity sha512-AGOriNp96vNBd3HtU+RzFEc75FfR5ymiYv8E553I71SCeXBiMsVDUtdio1OEFvrPyLIQ9tVR5RxXIFe5PUFjMg== +is-stream-ended@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/is-stream-ended/-/is-stream-ended-0.1.4.tgz#f50224e95e06bce0e356d440a4827cd35b267eda" + integrity sha512-xj0XPvmr7bQFTvirqnFr50o0hQIh6ZItDqloxt5aJrR4NQsYeSsyFQERYGCAzfindAcnKjINnwEEgLx4IqVzQw== + is-stream@^1.0.0, is-stream@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" @@ -5692,6 +6036,11 @@ is@^3.3.0: resolved "https://registry.yarnpkg.com/is/-/is-3.3.0.tgz#61cff6dd3c4193db94a3d62582072b44e5645d79" integrity sha512-nW24QBoPcFGGHJGUwnfpI7Yc5CdqWNdsyHQszVE/z2pKHXzh7FZ5GWhJqSyaQ9wMkQnsTx+kAI8bHlCX4tKdbg== +isarray@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" + integrity sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8= + isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" @@ -5773,6 +6122,17 @@ isurl@^1.0.0-alpha5: has-to-string-tag-x "^1.2.0" is-object "^1.0.1" +jaeger-client@^3.18.1: + version "3.18.1" + resolved "https://registry.yarnpkg.com/jaeger-client/-/jaeger-client-3.18.1.tgz#a8c7a778244ba117f4fb8775eb6aa5508703564e" + integrity sha512-eZLM2U6rJvYo0XbzQYFeMYfp29gQix7SKlmDReorp9hJkUwXZtTyxW81AcKdmFCjLHO5tFysTX+394BnjEnUZg== + dependencies: + node-int64 "^0.4.0" + opentracing "^0.14.4" + thriftrw "^3.5.0" + uuid "^3.2.1" + xorshift "^0.2.0" + jest-changed-files@^25.5.0: version "25.5.0" resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-25.5.0.tgz#141cc23567ceb3f534526f8614ba39421383634c" @@ -5837,15 +6197,15 @@ jest-diff@^25.2.1, jest-diff@^25.5.0: jest-get-type "^25.2.6" pretty-format "^25.5.0" -jest-diff@^26.0.1: - version "26.0.1" - resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-26.0.1.tgz#c44ab3cdd5977d466de69c46929e0e57f89aa1de" - integrity sha512-odTcHyl5X+U+QsczJmOjWw5tPvww+y9Yim5xzqxVl/R1j4z71+fHW4g8qu1ugMmKdFdxw+AtQgs5mupPnzcIBQ== +jest-diff@^26.4.0: + version "26.4.0" + resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-26.4.0.tgz#d073a0a11952b5bd9f1ff39bb9ad24304a0c55f7" + integrity sha512-wwC38HlOW+iTq6j5tkj/ZamHn6/nrdcEOc/fKaVILNtN2NLWGdkfRaHWwfNYr5ehaLvuoG2LfCZIcWByVj0gjg== dependencies: chalk "^4.0.0" - diff-sequences "^26.0.0" - jest-get-type "^26.0.0" - pretty-format "^26.0.1" + diff-sequences "^26.3.0" + jest-get-type "^26.3.0" + pretty-format "^26.4.0" jest-docblock@^21.0.0: version "21.2.0" @@ -5904,10 +6264,10 @@ jest-get-type@^25.2.6: resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-25.2.6.tgz#0b0a32fab8908b44d508be81681487dbabb8d877" integrity sha512-DxjtyzOHjObRM+sM1knti6or+eOgcGU4xVSb2HNP1TqO4ahsT+rqZg+nyqHWJSvWgKC5cG3QjGFBqxLghiF/Ig== -jest-get-type@^26.0.0: - version "26.0.0" - resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-26.0.0.tgz#381e986a718998dbfafcd5ec05934be538db4039" - integrity sha512-zRc1OAPnnws1EVfykXOj19zo2EMw5Hi6HLbFCSjpuJiXtOWAYIjNsHVSbpQ8bDX7L5BGYGI8m+HmKdjHYFF0kg== +jest-get-type@^26.3.0: + version "26.3.0" + resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-26.3.0.tgz#e97dc3c3f53c2b406ca7afaed4493b1d099199e0" + integrity sha512-TpfaviN1R2pQWkIihlfEanwOXK0zcxrKEE4MlU6Tn7keoXdN6/3gK/xl0yEh8DOunn5pOVGKf8hB4R9gVh04ig== jest-haste-map@^25.5.1: version "25.5.1" @@ -5981,15 +6341,15 @@ jest-matcher-utils@^25.5.0: jest-get-type "^25.2.6" pretty-format "^25.5.0" -jest-matcher-utils@^26.0.1: - version "26.0.1" - resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-26.0.1.tgz#12e1fc386fe4f14678f4cc8dbd5ba75a58092911" - integrity sha512-PUMlsLth0Azen8Q2WFTwnSkGh2JZ8FYuwijC8NR47vXKpsrKmA1wWvgcj1CquuVfcYiDEdj985u5Wmg7COEARw== +jest-matcher-utils@^26.4.0: + version "26.4.0" + resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-26.4.0.tgz#2bce9a939e008b894faf1bd4b5bb58facd00c252" + integrity sha512-u+xdCdq+F262DH+PutJKXLGr2H5P3DImdJCir51PGSfi3TtbLQ5tbzKaN8BkXbiTIU6ayuAYBWTlU1nyckVdzA== dependencies: chalk "^4.0.0" - jest-diff "^26.0.1" - jest-get-type "^26.0.0" - pretty-format "^26.0.1" + jest-diff "^26.4.0" + jest-get-type "^26.3.0" + pretty-format "^26.4.0" jest-message-util@^25.5.0: version "25.5.0" @@ -6005,13 +6365,13 @@ jest-message-util@^25.5.0: slash "^3.0.0" stack-utils "^1.0.1" -jest-message-util@^26.0.1: - version "26.0.1" - resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-26.0.1.tgz#07af1b42fc450b4cc8e90e4c9cef11b33ce9b0ac" - integrity sha512-CbK8uQREZ8umUfo8+zgIfEt+W7HAHjQCoRaNs4WxKGhAYBGwEyvxuK81FXa7VeB9pwDEXeeKOB2qcsNVCAvB7Q== +jest-message-util@^26.3.0: + version "26.3.0" + resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-26.3.0.tgz#3bdb538af27bb417f2d4d16557606fd082d5841a" + integrity sha512-xIavRYqr4/otGOiLxLZGj3ieMmjcNE73Ui+LdSW/Y790j5acqCsAdDiLIbzHCZMpN07JOENRWX5DcU+OQ+TjTA== dependencies: "@babel/code-frame" "^7.0.0" - "@jest/types" "^26.0.1" + "@jest/types" "^26.3.0" "@types/stack-utils" "^1.0.1" chalk "^4.0.0" graceful-fs "^4.2.4" @@ -6027,9 +6387,9 @@ jest-mock@^25.5.0: "@jest/types" "^25.5.0" jest-pnp-resolver@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/jest-pnp-resolver/-/jest-pnp-resolver-1.2.1.tgz#ecdae604c077a7fbc70defb6d517c3c1c898923a" - integrity sha512-pgFw2tm54fzgYvc/OHrnysABEObZCUNFnhjoRjaVOCN8NYc032/gVjPaHD4Aq6ApkSieWtfKAFQtmDKAmhupnQ== + version "1.2.2" + resolved "https://registry.yarnpkg.com/jest-pnp-resolver/-/jest-pnp-resolver-1.2.2.tgz#b704ac0ae028a89108a4d040b3f919dfddc8e33c" + integrity sha512-olV41bKSMm8BdnuMsewT4jqlZ8+3TCARAXjZGT9jcoSnrfUnRCqnMoF9XEeoWjbzObpqF9dRhHQj0Xb9QdF6/w== jest-regex-util@^25.2.6: version "25.2.6" @@ -6239,9 +6599,9 @@ js-tokens@^3.0.2: integrity sha1-mGbfOVECEw449/mWvOtlRDIJwls= js-yaml@^3.13.1, js-yaml@^3.8.1: - version "3.13.1" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847" - integrity sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw== + version "3.14.0" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.0.tgz#a7a34170f26a21bb162424d8adacb4113a69e482" + integrity sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A== dependencies: argparse "^1.0.7" esprima "^4.0.0" @@ -6253,6 +6613,11 @@ js2xmlparser@~3.0.0: dependencies: xmlcreate "^1.0.1" +jsbi@^3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/jsbi/-/jsbi-3.1.3.tgz#f024b340032f7c7caaa6ca4b32b55e8d33f6e897" + integrity sha512-nBJqA0C6Qns+ZxurbEoIR56wyjiUszpNy70FHvxO5ervMoCbZVE3z3kxr5nKGhlxr/9MhKTSUBs7cAwwuf3g9w== + jsbn@~0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" @@ -6319,11 +6684,18 @@ jsesc@~0.5.0: integrity sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0= json-bigint@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/json-bigint/-/json-bigint-0.3.0.tgz#0ccd912c4b8270d05f056fbd13814b53d3825b1e" - integrity sha1-DM2RLEuCcNBfBW+9E4FLU9OCWx4= + version "0.3.1" + resolved "https://registry.yarnpkg.com/json-bigint/-/json-bigint-0.3.1.tgz#0c1729d679f580d550899d6a2226c228564afe60" + integrity sha512-DGWnSzmusIreWlEupsUelHrhwmPPE+FiQvg+drKfk2p+bdEYa5mp4PJ8JsCWqae0M2jQNb0HPvnwvf1qOTThzQ== dependencies: - bignumber.js "^7.0.0" + bignumber.js "^9.0.0" + +json-bigint@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/json-bigint/-/json-bigint-1.0.0.tgz#ae547823ac0cad8398667f8cd9ef4730f5b01ff1" + integrity sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ== + dependencies: + bignumber.js "^9.0.0" json-buffer@3.0.0: version "3.0.0" @@ -6611,6 +6983,11 @@ lodash.assignin@^4.0.9: resolved "https://registry.yarnpkg.com/lodash.assignin/-/lodash.assignin-4.2.0.tgz#ba8df5fb841eb0a3e8044232b0e263a8dc6a28a2" integrity sha1-uo31+4QesKPoBEIysOJjqNxqKKI= +lodash.at@^4.6.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/lodash.at/-/lodash.at-4.6.0.tgz#93cdce664f0a1994ea33dd7cd40e23afd11b0ff8" + integrity sha1-k83OZk8KGZTqM9181A4jr9EbD/g= + lodash.bind@^4.1.4: version "4.2.1" resolved "https://registry.yarnpkg.com/lodash.bind/-/lodash.bind-4.2.1.tgz#7ae3017e939622ac31b7d7d7dcb1b34db1690d35" @@ -6651,6 +7028,11 @@ lodash.foreach@^4.3.0: resolved "https://registry.yarnpkg.com/lodash.foreach/-/lodash.foreach-4.5.0.tgz#1a6a35eace401280c7f06dddec35165ab27e3e53" integrity sha1-Gmo16s5AEoDH8G3d7DUWWrJ+PlM= +lodash.has@^4.5.2: + version "4.5.2" + resolved "https://registry.yarnpkg.com/lodash.has/-/lodash.has-4.5.2.tgz#d19f4dc1095058cccbe2b0cdf4ee0fe4aa37c862" + integrity sha1-0Z9NwQlQWMzL4rDN9O4P5Ko3yGI= + lodash.map@^4.4.0: version "4.6.0" resolved "https://registry.yarnpkg.com/lodash.map/-/lodash.map-4.6.0.tgz#771ec7839e3473d9c4cde28b19394c3562f4f6d3" @@ -6686,6 +7068,11 @@ lodash.reject@^4.4.0: resolved "https://registry.yarnpkg.com/lodash.reject/-/lodash.reject-4.6.0.tgz#80d6492dc1470864bbf583533b651f42a9f52415" integrity sha1-gNZJLcFHCGS79YNTO2UfQqn1JBU= +lodash.snakecase@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/lodash.snakecase/-/lodash.snakecase-4.1.1.tgz#39d714a35357147837aefd64b5dcbb16becd8f8d" + integrity sha1-OdcUo1NXFHg3rv1ktdy7Fr7Nj40= + lodash.some@^4.4.0: version "4.6.0" resolved "https://registry.yarnpkg.com/lodash.some/-/lodash.some-4.6.0.tgz#1bb9f314ef6b8baded13b549169b2a945eb68e4d" @@ -6716,10 +7103,10 @@ lodash.uniq@^4.5.0: resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M= -lodash@4.17.15, lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@~4.17.12: - version "4.17.15" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" - integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A== +lodash@4.17.20, lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@~4.17.12: + version "4.17.20" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.20.tgz#b44a9b6297bcb698f1c51a3545a2b3b368d59c52" + integrity sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA== logalot@^2.0.0: version "2.1.0" @@ -6741,6 +7128,11 @@ long@4.0.0, long@^4.0.0: resolved "https://registry.yarnpkg.com/long/-/long-4.0.0.tgz#9a7b71cfb7d361a194ea555241c92f7468d5bf28" integrity sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA== +long@^2.4.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/long/-/long-2.4.0.tgz#9fa180bb1d9500cdc29c4156766a1995e1f4524f" + integrity sha1-n6GAux2VAM3CnEFWdmoZleH0Uk8= + long@~3: version "3.2.0" resolved "https://registry.yarnpkg.com/long/-/long-3.2.0.tgz#d821b7138ca1cb581c172990ef14db200b5c474b" @@ -6808,7 +7200,14 @@ lru-cache@^4.0.1: pseudomap "^1.0.2" yallist "^2.1.2" -lz4@~0.6.0: +lru-cache@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" + integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== + dependencies: + yallist "^4.0.0" + +lz4@0.6.3, lz4@~0.6.0: version "0.6.3" resolved "https://registry.yarnpkg.com/lz4/-/lz4-0.6.3.tgz#78df6bb69a36d7db6c2e849494876ba6e38e66d6" integrity sha512-NEs7p58fnU69P6mGl1slL5I+FVhYIUXXfZRXNBIFvmTkEsHh+TMpO1BPcQREwFpThHNC5wa61d7vQdZ0zz9aUg== @@ -6819,9 +7218,9 @@ lz4@~0.6.0: xxhashjs "^0.2.2" macos-release@^2.2.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/macos-release/-/macos-release-2.3.0.tgz#eb1930b036c0800adebccd5f17bc4c12de8bb71f" - integrity sha512-OHhSbtcviqMPt7yfw5ef5aghS2jzFVKEFyCJndQt2YpSQ9qRVSEv2axSJI1paVThEu+FFGs584h/1YhxjVqajA== + version "2.4.1" + resolved "https://registry.yarnpkg.com/macos-release/-/macos-release-2.4.1.tgz#64033d0ec6a5e6375155a74b1a1eba8e509820ac" + integrity sha512-H/QHeBIN1fIGJX517pvK8IEK53yQOW7YcEI55oYtgjDdoCQQz7eJS94qt5kNrscReEyuD/JcdFCm2XBEcGOITg== make-dir@^1.0.0, make-dir@^1.2.0: version "1.3.0" @@ -6957,9 +7356,9 @@ merge-stream@^2.0.0: integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== merge2@^1.2.3: - version "1.3.0" - resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.3.0.tgz#5b366ee83b2f1582c48f87e47cf1a9352103ca81" - integrity sha512-2j4DAdlBOkiSZIsaXk4mTE3sRS02yBHAtfy127xRV3bQUFqXkjHCHLW6Scv7DwNRbIWNHH8zpnz9zMaKXIdvYw== + version "1.4.1" + resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" + integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== methods@^1.1.2, methods@~1.1.2: version "1.1.2" @@ -7016,9 +7415,9 @@ mime@1.6.0: integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== mime@^2.2.0: - version "2.4.5" - resolved "https://registry.yarnpkg.com/mime/-/mime-2.4.5.tgz#d8de2ecb92982dedbb6541c9b6841d7f218ea009" - integrity sha512-3hQhEUF027BuxZjQA3s7rIv/7VCQPa27hN9u9g87sEkWaKwQPuXOkVKtOeiyUrnWqTDiOs8Ed2rwg733mB0R5w== + version "2.4.6" + resolved "https://registry.yarnpkg.com/mime/-/mime-2.4.6.tgz#e5b407c90db442f2beb5b162373d07b69affa4d1" + integrity sha512-RZKhC3EmpBchfTGBVb8fb+RL2cWyw/32lshnsETttkBAyAUXSGHxbEJWWRXc751DrIxG1q04b8QwMbAwkRPpUA== mimic-fn@^1.0.0: version "1.2.0" @@ -7042,7 +7441,7 @@ mimic-response@^1.0.0: dependencies: brace-expansion "^1.1.7" -minimist@^1.1.1, minimist@^1.1.3, minimist@^1.2.0, minimist@^1.2.5: +minimist@^1.1.0, minimist@^1.1.1, minimist@^1.1.3, minimist@^1.2.0, minimist@^1.2.5: version "1.2.5" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== @@ -7070,17 +7469,17 @@ mixin-deep@^1.1.3, mixin-deep@^1.2.0: for-in "^1.0.2" is-extendable "^1.0.1" -mkdirp@0.x, mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@^0.5.3, mkdirp@~0.5.1: +mkdirp@0.x, mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@^0.5.3, mkdirp@^0.5.5, mkdirp@~0.5.1: version "0.5.5" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def" integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ== dependencies: minimist "^1.2.5" -moment@^2.10.6: - version "2.25.3" - resolved "https://registry.yarnpkg.com/moment/-/moment-2.25.3.tgz#252ff41319cf41e47761a1a88cab30edfe9808c0" - integrity sha512-PuYv0PHxZvzc15Sp8ybUCoQ+xpyPWvjOuK72a5ovzp2LI32rJXOiIfyoFoYvG3s6EwwrdkMyWuRiEHSZRLJNdg== +moment@^2.19.3: + version "2.27.0" + resolved "https://registry.yarnpkg.com/moment/-/moment-2.27.0.tgz#8bff4e3e26a236220dfe3e36de756b6ebaa0105d" + integrity sha512-al0MUK7cpIcglMv3YF13qSgdAIqxHTO7brRtaz3DlSULbqfazqkc5kEjNrLDOM7fsjshoFIihnU8snrP7zUvhQ== ms@2.0.0: version "2.0.0" @@ -7097,13 +7496,13 @@ ms@2.1.2, ms@^2.1.1: resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== -mssql@4.3.7: - version "4.3.7" - resolved "https://registry.yarnpkg.com/mssql/-/mssql-4.3.7.tgz#cfc60e6f48db7471172158b9878fbb9a910c98ca" - integrity sha512-+cs1uBD2Hut6UNeCnJHUeikWKIEhMTlr8s1bOw2BaVTPcyau1fFUqt1rQRilEq/GsyGkkzrE+TKw0jlvbW5cWQ== +mssql@4.3.9: + version "4.3.9" + resolved "https://registry.yarnpkg.com/mssql/-/mssql-4.3.9.tgz#e84713909d5c404d261df67173639294bacb26d2" + integrity sha512-Qy/ewvlCHIJ13bPXTXaP7ZTskWMB0gwcYUtVedt7HvEAbRneYfggUe5mbRc/e9I12mdvepGKAXfm1bn20X4S8g== dependencies: debug "^3.2.6" - generic-pool "^3.6.1" + generic-pool "^3.7.1" tedious "^2.7.1" murmurhash@1.0.0: @@ -7130,16 +7529,16 @@ mv@~2: ncp "~2.0.0" rimraf "~2.4.0" -nan@2.14.0: - version "2.14.0" - resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.0.tgz#7818f722027b2459a86f0295d434d1fc2336c52c" - integrity sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg== - -nan@^2.0.5, nan@^2.12.1, nan@^2.13.2, nan@^2.14.0, nan@^2.14.1: +nan@2.14.1, nan@^2.0.5, nan@^2.12.1, nan@^2.13.2, nan@^2.14.0: version "2.14.1" resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.1.tgz#d7be34dfa3105b91494c3147089315eff8874b01" integrity sha512-isWHgVjnFjh2x2yuJ/tj3JbwoHu3UC2dX5G/88Cm24yB6YopVgxvBObDY7n5xW6ExmFhJpSEQqFPvq9zaXc8Jw== +nanoid@^2.1.0: + version "2.1.11" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-2.1.11.tgz#ec24b8a758d591561531b4176a01e3ab4f0f0280" + integrity sha512-s/snB+WGm6uwi0WjsZdaVcuf3KJXlfGl2LcxgwkEwJF0D/BWzVWAZW/XY4bFaiR7s0Jk3FPvlnepg1H1b1UwlA== + nanomatch@^1.2.9: version "1.2.13" resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119" @@ -7172,10 +7571,10 @@ ncp@~2.0.0: resolved "https://registry.yarnpkg.com/ncp/-/ncp-2.0.0.tgz#195a21d6c46e361d2fb1281ba38b91e9df7bdbb3" integrity sha1-GVoh1sRuNh0vsSgbo4uR6d9727M= -needle@^2.2.1: - version "2.4.1" - resolved "https://registry.yarnpkg.com/needle/-/needle-2.4.1.tgz#14af48732463d7475696f937626b1b993247a56a" - integrity sha512-x/gi6ijr4B7fwl6WYL9FwlCvRQKGlUNvnceho8wxkwXqN8jvVmmmATTmZPRRG7b/yC1eode26C2HO9jl78Du9g== +needle@^2.5.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/needle/-/needle-2.5.0.tgz#e6fc4b3cc6c25caed7554bd613a5cf0bac8c31c0" + integrity sha512-o/qITSDR0JCyCKEQ1/1bnUXMmznxabbwi/Y4WwJElf+evwJNFNwIDMCCt5IigFVxgeGBJESLohGtIS9gEzo1fA== dependencies: debug "^3.2.6" iconv-lite "^0.4.4" @@ -7186,13 +7585,13 @@ negotiator@0.6.2: resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb" integrity sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw== -netlinkwrapper@^1.1.2: - version "1.2.0" - resolved "https://registry.yarnpkg.com/netlinkwrapper/-/netlinkwrapper-1.2.0.tgz#231301e3b6ad3b0d2378113f3f665666a1252fa1" - integrity sha512-PtL6AeqUn9MhIrPutCAMWxG0mMK69yAcr70dVDUj1PvIwKU3qKR/2PeA7pchoJVZ8E5JO0BDAbGx/bRfC2nBLA== +netlinkwrapper@^1.2.0: + version "1.2.1" + resolved "https://registry.yarnpkg.com/netlinkwrapper/-/netlinkwrapper-1.2.1.tgz#eea73889b60f7690f03e533e6a202fa3d7c02a12" + integrity sha512-rh3hl2EPZOCC0ddEyJOQRb0bmJgAxuCW3dlhJFZ/V/pAQbLHyLy8TJ4EvS8aFOdUGJunvasepIuSDwgs2c37fA== dependencies: bindings "1.5.0" - nan "2.14.0" + nan "2.14.1" nice-try@^1.0.4: version "1.0.5" @@ -7207,25 +7606,44 @@ no-case@^3.0.3: lower-case "^2.0.1" tslib "^1.10.0" +node-abi@^2.19.1: + version "2.19.1" + resolved "https://registry.yarnpkg.com/node-abi/-/node-abi-2.19.1.tgz#6aa32561d0a5e2fdb6810d8c25641b657a8cea85" + integrity sha512-HbtmIuByq44yhAzK7b9j/FelKlHYISKQn0mtvcBrU5QBkhoCMp5bu8Hv5AI34DcKfOAcJBcOEMwLlwO62FFu9A== + dependencies: + semver "^5.4.1" + node-abort-controller@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/node-abort-controller/-/node-abort-controller-1.0.4.tgz#4095e41d58b2fae169d2f9892904d603e11c7a39" - integrity sha512-7cNtLKTAg0LrW3ViS2C7UfIzbL3rZd8L0++5MidbKqQVJ8yrH6+1VRSHl33P0ZjBTbOJd37d9EYekvHyKkB0QQ== + version "1.1.0" + resolved "https://registry.yarnpkg.com/node-abort-controller/-/node-abort-controller-1.1.0.tgz#8a734a631b022af29963be7245c1483cbb9e070d" + integrity sha512-dEYmUqjtbivotqjraOe8UvhT/poFfog1BQRNsZm/MSEDDESk2cQ1tvD8kGyuN07TM/zoW+n42odL8zTeJupYdQ== -node-fetch@2.6.0, node-fetch@^2.2.0, node-fetch@^2.3.0, node-fetch@^2.6.0: - version "2.6.0" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.0.tgz#e633456386d4aa55863f676a7ab0daa8fdecb0fd" - integrity sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA== +node-fetch@2.6.1, node-fetch@^2.2.0, node-fetch@^2.3.0, node-fetch@^2.6.0, node-fetch@^2.6.1: + version "2.6.1" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052" + integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw== -node-forge@^0.8.5: - version "0.8.5" - resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.8.5.tgz#57906f07614dc72762c84cef442f427c0e1b86ee" - integrity sha512-vFMQIWt+J/7FLNyKouZ9TazT74PRV3wgv9UT4cRjC8BffxFbKXkgIWR42URCPSnHm/QDz6BOlb2Q0U4+VQT67Q== +node-forge@^0.10, node-forge@^0.8.5, node-forge@^0.9.0: + version "0.10.0" + resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.10.0.tgz#32dea2afb3e9926f02ee5ce8794902691a676bf3" + integrity sha512-PPmu8eEeG9saEUvI97fm4OYxXVB6bFvyNTyiUOBichBpFG8A1Ljw3bY62+5oOjDEMHRnd0Y7HQ+x7uzxOzC6JA== -node-forge@^0.9.0: - version "0.9.1" - resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.9.1.tgz#775368e6846558ab6676858a4d8c6e8d16c677b5" - integrity sha512-G6RlQt5Sb4GMBzXvhfkeFmbqR6MzhtnT7VTHuLadjkii3rdYHNdw0m8zA4BTxVIh68FicCQ2NSUANpsqkr9jvQ== +node-gyp@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-6.1.0.tgz#64e31c61a4695ad304c1d5b82cf6b7c79cc79f3f" + integrity sha512-h4A2zDlOujeeaaTx06r4Vy+8MZ1679lU+wbCKDS4ZtvY2A37DESo37oejIw0mtmR3+rvNwts5B6Kpt1KrNYdNw== + dependencies: + env-paths "^2.2.0" + glob "^7.1.4" + graceful-fs "^4.2.2" + mkdirp "^0.5.1" + nopt "^4.0.1" + npmlog "^4.1.2" + request "^2.88.0" + rimraf "^2.6.3" + semver "^5.7.1" + tar "^4.4.12" + which "^1.3.1" node-int64@0.4.0, node-int64@^0.4.0: version "0.4.0" @@ -7264,30 +7682,14 @@ node-notifier@^6.0.0: shellwords "^0.1.1" which "^1.3.1" -node-pre-gyp@^0.13.0: - version "0.13.0" - resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.13.0.tgz#df9ab7b68dd6498137717838e4f92a33fc9daa42" - integrity sha512-Md1D3xnEne8b/HGVQkZZwV27WUi1ZRuZBij24TNaZwUPU3ZAFtvT6xxJGaUVillfmMKnn5oD1HoGsp2Ftik7SQ== - dependencies: - detect-libc "^1.0.2" - mkdirp "^0.5.1" - needle "^2.2.1" - nopt "^4.0.1" - npm-packlist "^1.1.6" - npmlog "^4.0.2" - rc "^1.2.7" - rimraf "^2.6.1" - semver "^5.3.0" - tar "^4" - -node-pre-gyp@^0.14.0: - version "0.14.0" - resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.14.0.tgz#9a0596533b877289bcad4e143982ca3d904ddc83" - integrity sha512-+CvDC7ZttU/sSt9rFjix/P05iS43qHCOOGzcr3Ry99bXG7VX953+vFyEuph/tfqoYu8dttBkE86JSKBO2OzcxA== +node-pre-gyp@^0.15.0: + version "0.15.0" + resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.15.0.tgz#c2fc383276b74c7ffa842925241553e8b40f1087" + integrity sha512-7QcZa8/fpaU/BKenjcaeFF9hLz2+7S9AqyXFhlH/rilsQ/hPZKK32RtR5EQHJElgu+q5RfbJ34KriI79UWaorA== dependencies: detect-libc "^1.0.2" - mkdirp "^0.5.1" - needle "^2.2.1" + mkdirp "^0.5.3" + needle "^2.5.0" nopt "^4.0.1" npm-packlist "^1.1.6" npmlog "^4.0.2" @@ -7296,10 +7698,10 @@ node-pre-gyp@^0.14.0: semver "^5.3.0" tar "^4.4.2" -node-releases@^1.1.29, node-releases@^1.1.53: - version "1.1.55" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.55.tgz#8af23b7c561d8e2e6e36a46637bab84633b07cee" - integrity sha512-H3R3YR/8TjT5WPin/wOoHOUPHgvj8leuU/Keta/rwelEQN9pA/S2Dx8/se4pZ2LBxSd0nAGzsNzhqwa77v7F1w== +node-releases@^1.1.29, node-releases@^1.1.60: + version "1.1.60" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.60.tgz#6948bdfce8286f0b5d0e5a88e8384e954dfe7084" + integrity sha512-gsO4vjEdQaTusZAEebUWp2a5d7dF5DYoIpDG7WySnk7BuZDW+GPpHXoXXuYawRBr/9t5q54tirPz79kFIWg4dA== nopt@^4.0.1, nopt@~4.0: version "4.0.3" @@ -7393,7 +7795,7 @@ npm-run-path@^4.0.0: dependencies: path-key "^3.0.0" -npmlog@^4.0.2: +npmlog@^4.0.2, npmlog@^4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b" integrity sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg== @@ -7450,9 +7852,9 @@ object-hash@^1.3.1: integrity sha512-OSuu/pU4ENM9kmREg0BdNrUDIl1heYa4mBZacJc+vVWz4GtAwu7jO8s4AIt2aGRUTqxykpWzI3Oqnsm13tTMDA== object-inspect@^1.7.0: - version "1.7.0" - resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.7.0.tgz#f4f6bd181ad77f006b5ece60bd0b6f398ff74a67" - integrity sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw== + version "1.8.0" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.8.0.tgz#df807e5ecf53a609cc6bfe93eac3cc7be5b3a9d0" + integrity sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA== object-keys@^1.0.11, object-keys@^1.0.12, object-keys@^1.1.1: version "1.1.1" @@ -7528,9 +7930,9 @@ onetime@^2.0.0: mimic-fn "^1.0.0" onetime@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.0.tgz#fff0f3c91617fe62bb50189636e99ac8a6df7be5" - integrity sha512-5NcSkPHhwTVFIQN+TUqXoS5+dlElHXdpAWu9I0HP20YOtIi+aZ0Ct82jdlILDxjLEAWwvm+qj1m6aEtsDVmm6Q== + version "5.1.2" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" + integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg== dependencies: mimic-fn "^2.1.0" @@ -7555,7 +7957,7 @@ openid-client@2.5.0: oidc-token-hash "^3.0.1" p-any "^1.1.0" -opentracing@0.14.4, opentracing@^0.14.3, opentracing@^0.14.4: +opentracing@0.14.4, opentracing@^0.14.3, opentracing@^0.14.4, opentracing@~0.14.3: version "0.14.4" resolved "https://registry.yarnpkg.com/opentracing/-/opentracing-0.14.4.tgz#a113408ea740da3a90fde5b3b0011a375c2e4268" integrity sha512-nNnZDkUNExBwEpb7LZaeMeQgvrlO8l4bgY/LvGNZCR0xG/dGWqHqjKrAmR5GUoYo0FIz38kxasvA1aevxWs2CA== @@ -7650,6 +8052,11 @@ p-cancelable@^0.4.0: resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-0.4.1.tgz#35f363d67d52081c8d9585e37bcceb7e0bbcb2a0" integrity sha512-HNa1A8LvB1kie7cERyy21VNeHb2CWJJYqyyC2o3klWFfMGlFmWv2Z7sFgZH8ZiaYL95ydToKTFVXgMV/Os0bBQ== +p-defer@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/p-defer/-/p-defer-3.0.0.tgz#d1dceb4ee9b2b604b1d94ffec83760175d4e6f83" + integrity sha512-ugZxsxmtTln604yeYd29EGrNhazN2lywetzpKhfmQjW/VJmhpDmWbiX+h0zL8V91R0UXkhb3KtPmyq9PZw3aYw== + p-each-series@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/p-each-series/-/p-each-series-2.1.0.tgz#961c8dd3f195ea96c747e636b262b800a6b1af48" @@ -7796,9 +8203,9 @@ parse-json@^4.0.0: json-parse-better-errors "^1.0.1" parse-json@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.0.0.tgz#73e5114c986d143efa3712d4ea24db9a4266f60f" - integrity sha512-OOY5b7PAEFV0E2Fir1KOkxchnZNCdowAJgQ5NuxjpBKTRP3pQhwkrkxqQjeoKJ+fO7bCpmIZaogI4eZGDMEGOw== + version "5.0.1" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.0.1.tgz#7cfe35c1ccd641bce3981467e6c2ece61b3b3878" + integrity sha512-ztoZ4/DYeXQq4E21v169sC8qWINGpcosGv9XhTDvg9/hWvx/zrFkc9BiWxR58OJLHGk28j5BL0SDLeV2WmFZlQ== dependencies: "@babel/code-frame" "^7.0.0" error-ex "^1.3.1" @@ -7962,7 +8369,7 @@ pkg-dir@^4.2.0: dependencies: find-up "^4.0.0" -pkg-up@2.0.0, pkg-up@^2.0.0: +pkg-up@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/pkg-up/-/pkg-up-2.0.0.tgz#c819ac728059a461cab1c3889a2be3c49a004d7f" integrity sha1-yBmscoBZpGHKscOImivjxJoATX8= @@ -7975,13 +8382,13 @@ pn@^1.1.0: integrity sha512-2qHaIQr2VLRFoxe2nASzsV6ef4yOOH+Fi9FBOVH6cqeSgUnoyySPZkxzLuzd+RYOQTRpROA0ztTMqxROKSb/nA== portfinder@^1.0.21: - version "1.0.26" - resolved "https://registry.yarnpkg.com/portfinder/-/portfinder-1.0.26.tgz#475658d56ca30bed72ac7f1378ed350bd1b64e70" - integrity sha512-Xi7mKxJHHMI3rIUrnm/jjUgwhbYMkp/XKEcZX3aG4BrumLpq3nmoQMX+ClYnDZnZ/New7IatC1no5RX0zo1vXQ== + version "1.0.28" + resolved "https://registry.yarnpkg.com/portfinder/-/portfinder-1.0.28.tgz#67c4622852bd5374dd1dd900f779f53462fac778" + integrity sha512-Se+2isanIcEqf2XMHjyUKskczxbPH7dQnlMjXX6+dybayyHvAf/TCgyMRlzf/B6QDhAEFOGes0pzRo3by4AbMA== dependencies: async "^2.6.2" debug "^3.1.1" - mkdirp "^0.5.1" + mkdirp "^0.5.5" posix-character-classes@^0.1.0: version "0.1.1" @@ -7989,9 +8396,9 @@ posix-character-classes@^0.1.0: integrity sha1-AerA/jta9xoqbAL+q7jB/vfgDqs= postcss-calc@^7.0.1: - version "7.0.2" - resolved "https://registry.yarnpkg.com/postcss-calc/-/postcss-calc-7.0.2.tgz#504efcd008ca0273120568b0792b16cdcde8aac1" - integrity sha512-rofZFHUg6ZIrvRwPeFktv06GdbDYLcGqh9EwiMutZg+a0oePCCw1zHOEiji6LCpyRcjTREtPASuUqeAvYlEVvQ== + version "7.0.3" + resolved "https://registry.yarnpkg.com/postcss-calc/-/postcss-calc-7.0.3.tgz#d65cca92a3c52bf27ad37a5f732e0587b74f1623" + integrity sha512-IB/EAEmZhIMEIhG7Ov4x+l47UaXOS1n2f4FBUk/aKllQhtSCxWhTzn0nJgkqN7fo/jcWySvWTSB6Syk9L+31bA== dependencies: postcss "^7.0.27" postcss-selector-parser "^6.0.2" @@ -8258,15 +8665,15 @@ postcss-value-parser@^3.0.0: resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz#9ff822547e2893213cf1c30efa51ac5fd1ba8281" integrity sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ== -postcss-value-parser@^4.0.2, postcss-value-parser@^4.0.3: +postcss-value-parser@^4.0.2, postcss-value-parser@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.1.0.tgz#443f6a20ced6481a2bda4fa8532a6e55d789a2cb" integrity sha512-97DXOFbQJhk71ne5/Mt6cOu6yxsSfM0QGQyl0L25Gca4yGWEGJaig7l7gbCX623VqTBNGLRLaVUCnNkcedlRSQ== -postcss@^7.0.0, postcss@^7.0.1, postcss@^7.0.17, postcss@^7.0.27: - version "7.0.30" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.30.tgz#cc9378beffe46a02cbc4506a0477d05fcea9a8e2" - integrity sha512-nu/0m+NtIzoubO+xdAlwZl/u5S5vi/y6BCsoL8D+8IxsD3XvBS8X4YEADNIVXKVuQvduiucnRv+vPIqj56EGMQ== +postcss@^7.0.0, postcss@^7.0.1, postcss@^7.0.17, postcss@^7.0.27, postcss@^7.0.32: + version "7.0.32" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.32.tgz#4310d6ee347053da3433db2be492883d62cec59d" + integrity sha512-03eXong5NLnNCD05xscnGKGDZ98CyzoqPSMjOe6SuoQY7Z2hIj0Ld1g/O/UQRuOle2aRtiIRDg9tDcTGAkLfKw== dependencies: chalk "^2.4.2" source-map "^0.6.1" @@ -8312,12 +8719,12 @@ pretty-format@^25.2.1, pretty-format@^25.5.0: ansi-styles "^4.0.0" react-is "^16.12.0" -pretty-format@^26.0.1: - version "26.0.1" - resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-26.0.1.tgz#a4fe54fe428ad2fd3413ca6bbd1ec8c2e277e197" - integrity sha512-SWxz6MbupT3ZSlL0Po4WF/KujhQaVehijR2blyRDCzk9e45EaYMVhMBn49fnRuHxtkSpXTes1GxNpVmH86Bxfw== +pretty-format@^26.4.0: + version "26.4.0" + resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-26.4.0.tgz#c08073f531429e9e5024049446f42ecc9f933a3b" + integrity sha512-mEEwwpCseqrUtuMbrJG4b824877pM5xald3AkilJ47Po2YLr97/siejYQHqj2oDQBeJNbu+Q0qUuekJ8F0NAPg== dependencies: - "@jest/types" "^26.0.1" + "@jest/types" "^26.3.0" ansi-regex "^5.0.0" ansi-styles "^4.0.0" react-is "^16.12.0" @@ -8328,17 +8735,12 @@ priorityqueuejs@^1.0.0: integrity sha1-LuTyPCVgkT4IwHzlzN1t498sWvg= prismjs@^1.16.0: - version "1.20.0" - resolved "https://registry.yarnpkg.com/prismjs/-/prismjs-1.20.0.tgz#9b685fc480a3514ee7198eac6a3bf5024319ff03" - integrity sha512-AEDjSrVNkynnw6A+B1DsFkd6AVdTnp+/WoUixFRULlCLZVRZlVQMVWio/16jv7G1FscUxQxOQhWwApgbnxr6kQ== + version "1.21.0" + resolved "https://registry.yarnpkg.com/prismjs/-/prismjs-1.21.0.tgz#36c086ec36b45319ec4218ee164c110f9fc015a3" + integrity sha512-uGdSIu1nk3kej2iZsLyDoJ7e9bnPzIgY0naW/HdknGj61zScaprVEVGHrPoXqI+M9sP0NDnTK2jpkvmldpuqDw== optionalDependencies: clipboard "^2.0.0" -private@^0.1.8: - version "0.1.8" - resolved "https://registry.yarnpkg.com/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff" - integrity sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg== - process-nextick-args@~1.0.6: version "1.0.7" resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-1.0.7.tgz#150e20b756590ad3f91093f25a4f2ad8bff30ba3" @@ -8349,11 +8751,23 @@ process-nextick-args@~2.0.0: resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== +process@^0.10.0: + version "0.10.1" + resolved "https://registry.yarnpkg.com/process/-/process-0.10.1.tgz#842457cc51cfed72dc775afeeafb8c6034372725" + integrity sha1-hCRXzFHP7XLcd1r+6vuMYDQ3JyU= + process@^0.11.10: version "0.11.10" resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" integrity sha1-czIwDoQBYb2j5podHZGn1LwW8YI= +prom-client@~11.3.0: + version "11.3.0" + resolved "https://registry.yarnpkg.com/prom-client/-/prom-client-11.3.0.tgz#fe93f360182f1ec1921722efc211a6c0e68e0253" + integrity sha512-OqSf5WOvpGZXkfqPXUHNHpjrbEE/q8jxjktO0i7zg1cnULAtf0ET67/J5R4e4iA4MZx2260tzTzSFSWgMdTZmQ== + dependencies: + tdigest "^0.1.1" + prompts@^2.0.1: version "2.3.2" resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.3.2.tgz#480572d89ecf39566d2bd3fe2c9fccb7c4c0b068" @@ -8405,6 +8819,25 @@ protobufjs@^5.0.3: glob "^7.0.5" yargs "^3.10.0" +protobufjs@^6.8.1, protobufjs@^6.8.6, protobufjs@^6.9.0: + version "6.10.1" + resolved "https://registry.yarnpkg.com/protobufjs/-/protobufjs-6.10.1.tgz#e6a484dd8f04b29629e9053344e3970cccf13cd2" + integrity sha512-pb8kTchL+1Ceg4lFd5XUpK8PdWacbvV5SK2ULH2ebrYtl4GjJmS24m6CKME67jzV53tbJxHlnNOSqQHbTsR9JQ== + dependencies: + "@protobufjs/aspromise" "^1.1.2" + "@protobufjs/base64" "^1.1.2" + "@protobufjs/codegen" "^2.0.4" + "@protobufjs/eventemitter" "^1.1.0" + "@protobufjs/fetch" "^1.1.0" + "@protobufjs/float" "^1.0.2" + "@protobufjs/inquire" "^1.1.0" + "@protobufjs/path" "^1.1.2" + "@protobufjs/pool" "^1.1.0" + "@protobufjs/utf8" "^1.1.0" + "@types/long" "^4.0.1" + "@types/node" "^13.7.0" + long "^4.0.0" + proxy-addr@~2.0.5: version "2.0.6" resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.6.tgz#fdc2336505447d3f2f2c638ed272caf614bbb2bf" @@ -8632,6 +9065,16 @@ read-pkg@^5.2.0: parse-json "^5.0.0" type-fest "^0.6.0" +"readable-stream@1.x >=1.1.9": + version "1.1.14" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.14.tgz#7cf4c54ef648e3813084c636dd2079e166c081d9" + integrity sha1-fPTFTvZI44EwhMY23SB54WbAgdk= + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.1" + isarray "0.0.1" + string_decoder "~0.10.x" + "readable-stream@2 || 3", readable-stream@^3.0.2, readable-stream@^3.1.1, readable-stream@^3.4.0, readable-stream@^3.6.0: version "3.6.0" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" @@ -8641,7 +9084,7 @@ read-pkg@^5.2.0: string_decoder "^1.1.1" util-deprecate "^1.0.1" -readable-stream@^2.0.0, readable-stream@^2.0.2, readable-stream@^2.0.6, readable-stream@^2.2.2, readable-stream@^2.3.0, readable-stream@^2.3.5, readable-stream@^2.3.6, readable-stream@~2.3.6: +readable-stream@^2.0.0, readable-stream@^2.0.2, readable-stream@^2.0.6, readable-stream@^2.2.2, readable-stream@^2.3.0, readable-stream@^2.3.6, readable-stream@~2.3.6: version "2.3.7" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== @@ -8710,9 +9153,9 @@ redent@^1.0.0: strip-indent "^1.0.1" redis-commands@^1.3.5, redis-commands@^1.5.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/redis-commands/-/redis-commands-1.5.0.tgz#80d2e20698fe688f227127ff9e5164a7dd17e785" - integrity sha512-6KxamqpZ468MeQC3bkWmCB1fp56XL64D4Kf0zJSwDZbVLLm7KFkoIcHrgRvQ+sk8dnhySs7+yBg94yIkAK7aJg== + version "1.6.0" + resolved "https://registry.yarnpkg.com/redis-commands/-/redis-commands-1.6.0.tgz#36d4ca42ae9ed29815cdb30ad9f97982eba1ce23" + integrity sha512-2jnZ0IkjZxvguITjFTrGiLyzQZcTvaw8DAaCXxZq/dsHXz7KfMQ3OUJy7Tz9vnRtZRVz6VRCPDvruvU8Ts44wQ== redis-errors@^1.0.0, redis-errors@^1.2.0: version "1.2.0" @@ -8744,9 +9187,9 @@ regenerate-unicode-properties@^8.2.0: regenerate "^1.4.0" regenerate@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.0.tgz#4a856ec4b56e4077c557589cae85e7a4c8869a11" - integrity sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg== + version "1.4.1" + resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.1.tgz#cad92ad8e6b591773485fbe05a485caf4f457e6f" + integrity sha512-j2+C8+NtXQgEKWk49MMP5P/u2GhnahTtVkRIHr5R5lVRlbKvmQ+oS+A5aLKWp2ma5VkT8sh6v+v4hbH0YHR66A== regenerator-runtime@^0.11.0: version "0.11.1" @@ -8754,17 +9197,16 @@ regenerator-runtime@^0.11.0: integrity sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg== regenerator-runtime@^0.13.4: - version "0.13.5" - resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.5.tgz#d878a1d094b4306d10b9096484b33ebd55e26697" - integrity sha512-ZS5w8CpKFinUzOwW3c83oPeVXoNsrLsaCoLtJvAClH135j/R77RuymhiSErhm2lKcwSCIpmvIWSbDkIfAqKQlA== + version "0.13.7" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz#cac2dacc8a1ea675feaabaeb8ae833898ae46f55" + integrity sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew== regenerator-transform@^0.14.2: - version "0.14.4" - resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.14.4.tgz#5266857896518d1616a78a0479337a30ea974cc7" - integrity sha512-EaJaKPBI9GvKpvUz2mz4fhx7WPgvwRLY9v3hlNHWmAuJHI13T4nwKnNvm5RWJzEdnI5g5UwtOww+S8IdoUC2bw== + version "0.14.5" + resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.14.5.tgz#c98da154683671c9c4dcb16ece736517e1b7feb4" + integrity sha512-eOf6vka5IO151Jfsw2NO9WpGX58W6wWmefK3I1zEGr0lOD0u8rwPaNqQL1aRxUaxLeKO3ArNh3VYg1KbaD+FFw== dependencies: "@babel/runtime" "^7.8.4" - private "^0.1.8" regex-not@^1.0.0, regex-not@^1.0.2: version "1.0.2" @@ -8787,9 +9229,9 @@ regexpu-core@^4.7.0: unicode-match-property-value-ecmascript "^1.2.0" regjsgen@^0.5.1: - version "0.5.1" - resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.5.1.tgz#48f0bf1a5ea205196929c0d9798b42d1ed98443c" - integrity sha512-5qxzGZjDs9w4tzT3TPhCJqWdCc3RLYwy9J2NB0nm5Lz+S273lvWcpjaTGHsT1dc6Hhfq41uSEOw8wBmxrKOuyg== + version "0.5.2" + resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.5.2.tgz#92ff295fb1deecbf6ecdab2543d207e91aa33733" + integrity sha512-OFFT3MfrH90xIW8OOSyUrk6QHD5E9JOTeGodiJeBS3J6IwlgzJMNE/1bZklWz5oTg+9dCMyEetclvCVXOPoN3A== regjsparser@^0.6.4: version "0.6.4" @@ -8833,19 +9275,19 @@ replace-ext@^1.0.0: resolved "https://registry.yarnpkg.com/replace-ext/-/replace-ext-1.0.1.tgz#2d6d996d04a15855d967443631dd5f77825b016a" integrity sha512-yD5BHCe7quCgBph4rMQ+0KkIRKwWCrHDOX1p1Gp6HwjPM5kVoCdKGNhN7ydqqsX6lJEnQDKZ/tFMiEdQ1dvPEw== -request-promise-core@1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/request-promise-core/-/request-promise-core-1.1.3.tgz#e9a3c081b51380dfea677336061fea879a829ee9" - integrity sha512-QIs2+ArIGQVp5ZYbWD5ZLCY29D5CfWizP8eWnm8FoGD1TX61veauETVQbrV60662V0oFBkrDOuaBI8XgtuyYAQ== +request-promise-core@1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/request-promise-core/-/request-promise-core-1.1.4.tgz#3eedd4223208d419867b78ce815167d10593a22f" + integrity sha512-TTbAfBBRdWD7aNNOoVOBH4pN/KigV6LyapYNNlAPA8JwbovRti1E88m3sYAwsLi5ryhPKsE9APwnjFTgdUjTpw== dependencies: - lodash "^4.17.15" + lodash "^4.17.19" -request-promise-native@1.0.8, request-promise-native@^1.0.7: - version "1.0.8" - resolved "https://registry.yarnpkg.com/request-promise-native/-/request-promise-native-1.0.8.tgz#a455b960b826e44e2bf8999af64dff2bfe58cb36" - integrity sha512-dapwLGqkHtwL5AEbfenuzjTYg35Jd6KPytsC2/TLkVMz8rm+tNt72MGUWT1RP/aYawMpN6HqbNGBQaRcBtjQMQ== +request-promise-native@1.0.9, request-promise-native@^1.0.7: + version "1.0.9" + resolved "https://registry.yarnpkg.com/request-promise-native/-/request-promise-native-1.0.9.tgz#e407120526a5efdc9a39b28a5679bf47b9d9dc28" + integrity sha512-wcW+sIUiWnKgNY0dqCpOZkUbF/I+YPi+f09JZIDa39Ec+q82CpSYniDp+ISgTTbKmnpJWASeJBPZmoxH84wt3g== dependencies: - request-promise-core "1.1.3" + request-promise-core "1.1.4" stealthy-require "^1.1.1" tough-cookie "^2.3.3" @@ -8965,17 +9407,17 @@ ret@~0.1.10: integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg== retry-request@^4.0.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/retry-request/-/retry-request-4.1.1.tgz#f676d0db0de7a6f122c048626ce7ce12101d2bd8" - integrity sha512-BINDzVtLI2BDukjWmjAIRZ0oglnCAkpP2vQjM3jdLhmT62h0xnQgciPwBRDAvHqpkPT2Wo1XuUyLyn6nbGrZQQ== + version "4.1.2" + resolved "https://registry.yarnpkg.com/retry-request/-/retry-request-4.1.2.tgz#88eb28ba5b0b81c3692f03dd9f2f91868be2a30b" + integrity sha512-fa4OwUcplhOYIhTm7zt6xsUfoApWo+auhvxbpPR4XLxHj0k67MhPItpCzYWzOEjtJlCH4MJ5V0qUrXiu/pOpag== dependencies: debug "^4.1.1" through2 "^3.0.1" rfc4648@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/rfc4648/-/rfc4648-1.3.0.tgz#2a69c76f05bc0e388feab933672de9b492af95f1" - integrity sha512-x36K12jOflpm1V8QjPq3I+pt7Z1xzeZIjiC8J2Oxd7bE1efTrOG241DTYVJByP/SxR9jl1t7iZqYxDX864jgBQ== + version "1.4.0" + resolved "https://registry.yarnpkg.com/rfc4648/-/rfc4648-1.4.0.tgz#c75b2856ad2e2d588b6ddb985d556f1f7f2a2abd" + integrity sha512-3qIzGhHlMHA6PoT6+cdPKZ+ZqtxkIvg8DZGKA5z6PQ33/uuhoJ+Ws/D/J9rXW6gXodgH8QYlz2UCl+sdUDmNIg== rgb-regex@^1.0.1: version "1.0.1" @@ -8987,7 +9429,7 @@ rgba-regex@^1.0.0: resolved "https://registry.yarnpkg.com/rgba-regex/-/rgba-regex-1.0.0.tgz#43374e2e2ca0968b0ef1523460b7d730ff22eeb3" integrity sha1-QzdOLiyglosO8VI0YLfXMP8i7rM= -rimraf@^2.5.4, rimraf@^2.6.1: +rimraf@^2.5.4, rimraf@^2.6.1, rimraf@^2.6.3: version "2.7.1" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== @@ -9019,13 +9461,13 @@ run-async@^2.2.0, run-async@^2.4.0: integrity sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ== rxjs@^6.4.0, rxjs@^6.5.3: - version "6.5.5" - resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.5.5.tgz#c5c884e3094c8cfee31bf27eb87e54ccfc87f9ec" - integrity sha512-WfQI+1gohdf0Dai/Bbmk5L5ItH5tYqm3ki2c5GdWhKjalzjg93N3avFjVStyZZz+A2Em+ZxKH5bNghw9UeylGQ== + version "6.6.2" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.6.2.tgz#8096a7ac03f2cc4fe5860ef6e572810d9e01c0d2" + integrity sha512-BHdBMVoWC2sL26w//BCu3YzKT4s2jip/WhwsGEDmeKYBhKDZeYezVUnHatYB7L85v5xs0BAQmg6BEYJEKxBabg== dependencies: tslib "^1.9.0" -safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: +safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1, safe-buffer@~5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== @@ -9103,11 +9545,11 @@ scheduler@^0.19.1: object-assign "^4.1.1" seek-bzip@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/seek-bzip/-/seek-bzip-1.0.5.tgz#cfe917cb3d274bcffac792758af53173eb1fabdc" - integrity sha1-z+kXyz0nS8/6x5J1ivUxc+sfq9w= + version "1.0.6" + resolved "https://registry.yarnpkg.com/seek-bzip/-/seek-bzip-1.0.6.tgz#35c4171f55a680916b52a07859ecf3b5857f21c4" + integrity sha512-e1QtP3YL5tWww8uKaOCQ18UxIT2laNBXHjV/S2WYCiK4udiv8lkG89KRIoCjUagnAmCBurjF4zEVX2ByBbnCjQ== dependencies: - commander "~2.8.1" + commander "^2.8.1" select@^1.1.2: version "1.1.2" @@ -9131,7 +9573,7 @@ semver-truncate@^1.1.2: dependencies: semver "^5.3.0" -"semver@2 || 3 || 4 || 5", semver@^5.3.0, semver@^5.4.1, semver@^5.5.0, semver@^5.6.0: +"semver@2 || 3 || 4 || 5", semver@^5.3.0, semver@^5.4.1, semver@^5.5.0, semver@^5.6.0, semver@^5.7.1: version "5.7.1" resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== @@ -9141,7 +9583,7 @@ semver@5.5.1: resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.1.tgz#7dfdd8814bdb7cabc7be0fb1d734cfb66c940477" integrity sha512-PqpAxfrEhlSUWge8dwIp4tZnQ25DIOthpiaHNIthsjEFQD6EvqUKUDM7L8O2rShkFccYo1VjJR0coWfNkCubRw== -semver@6.x, semver@^6.0.0, semver@^6.3.0: +semver@6.x, semver@^6.0.0, semver@^6.2.0, semver@^6.3.0: version "6.3.0" resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== @@ -9279,6 +9721,13 @@ shimmer@^1.1.0, shimmer@^1.2.0: resolved "https://registry.yarnpkg.com/shimmer/-/shimmer-1.2.1.tgz#610859f7de327b587efebf501fb43117f9aff337" integrity sha512-sQTKC1Re/rM6XyFM6fIAGHRPVGvyXfgzIDvzoq608vM+jeyVD0Tu1E6Np0Kc2zAIFWIj963V2800iF/9LPieQw== +shortid@^2.2.15: + version "2.2.15" + resolved "https://registry.yarnpkg.com/shortid/-/shortid-2.2.15.tgz#2b902eaa93a69b11120373cd42a1f1fe4437c122" + integrity sha512-5EaCy2mx2Jgc/Fdn9uuDuNIIfWBpzY4XIlhoqtXF6qsf+/+SGZ+FxDdX/ZsMZiWupIWNqAEmiNY4RC+LSmCeOw== + dependencies: + nanoid "^2.1.0" + signal-exit@^3.0.0, signal-exit@^3.0.2: version "3.0.3" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.3.tgz#a1410c2edd8f077b08b4e253c8eacfcaf057461c" @@ -9451,9 +9900,9 @@ source-map@^0.7.3: integrity sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ== spdx-correct@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.1.0.tgz#fb83e504445268f154b074e218c87c003cd31df4" - integrity sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q== + version "3.1.1" + resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.1.1.tgz#dece81ac9c1e6713e5f7d1b6f17d468fa53d89a9" + integrity sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w== dependencies: spdx-expression-parse "^3.0.0" spdx-license-ids "^3.0.0" @@ -9464,9 +9913,9 @@ spdx-exceptions@^2.1.0: integrity sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A== spdx-expression-parse@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz#99e119b7a5da00e05491c9fa338b7904823b41d0" - integrity sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg== + version "3.0.1" + resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz#cf70f50482eefdc98e3ce0a6833e4a53ceeba679" + integrity sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q== dependencies: spdx-exceptions "^2.1.0" spdx-license-ids "^3.0.0" @@ -9618,7 +10067,7 @@ string-width@^4.1.0, string-width@^4.2.0: is-fullwidth-code-point "^3.0.0" strip-ansi "^6.0.0" -string.prototype.trimend@^1.0.0: +string.prototype.trimend@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.1.tgz#85812a6b847ac002270f5808146064c995fb6913" integrity sha512-LRPxFUaTtpqYsTeNKaFOw3R4bxIzWOnbQ837QfBylo8jIxtcbK/A/sMV7Q+OAV/vWo+7s25pOE10KYSjaSO06g== @@ -9626,25 +10075,7 @@ string.prototype.trimend@^1.0.0: define-properties "^1.1.3" es-abstract "^1.17.5" -string.prototype.trimleft@^2.1.1: - version "2.1.2" - resolved "https://registry.yarnpkg.com/string.prototype.trimleft/-/string.prototype.trimleft-2.1.2.tgz#4408aa2e5d6ddd0c9a80739b087fbc067c03b3cc" - integrity sha512-gCA0tza1JBvqr3bfAIFJGqfdRTyPae82+KTnm3coDXkZN9wnuW3HjGgN386D7hfv5CHQYCI022/rJPVlqXyHSw== - dependencies: - define-properties "^1.1.3" - es-abstract "^1.17.5" - string.prototype.trimstart "^1.0.0" - -string.prototype.trimright@^2.1.1: - version "2.1.2" - resolved "https://registry.yarnpkg.com/string.prototype.trimright/-/string.prototype.trimright-2.1.2.tgz#c76f1cef30f21bbad8afeb8db1511496cfb0f2a3" - integrity sha512-ZNRQ7sY3KroTaYjRS6EbNiiHrOkjihL9aQE/8gfQ4DtAC/aEBRHFJa44OmoWxGGqXuJlfKkZW4WcXErGr+9ZFg== - dependencies: - define-properties "^1.1.3" - es-abstract "^1.17.5" - string.prototype.trimend "^1.0.0" - -string.prototype.trimstart@^1.0.0: +string.prototype.trimstart@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.1.tgz#14af6d9f34b053f7cfc89b72f8f2ee14b9039a54" integrity sha512-XxZn+QpvrBI1FOcg6dIpxUPgWCPuNXvMD72aaRaUQv1eD4e/Qy8i/hFTe0BUmD60p/QA6bh1avmuPTfNjqVWRw== @@ -9847,7 +10278,7 @@ tar-stream@^1.5.2: to-buffer "^1.1.1" xtend "^4.0.0" -tar@^4, tar@^4.4.2: +tar@^4.4.12, tar@^4.4.2: version "4.4.13" resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.13.tgz#43b364bc52888d555298637b10d60790254ab525" integrity sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA== @@ -9868,6 +10299,13 @@ tcp-port-used@^1.0.1: debug "4.1.0" is2 "2.0.1" +tdigest@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/tdigest/-/tdigest-0.1.1.tgz#2e3cb2c39ea449e55d1e6cd91117accca4588021" + integrity sha1-Ljyyw56kSeVdHmzZEReszKRYgCE= + dependencies: + bintrees "1.0.1" + tedious@^2.7.1: version "2.7.1" resolved "https://registry.yarnpkg.com/tedious/-/tedious-2.7.1.tgz#5308edebdd33767ca67b36fc71b2ab9c54675278" @@ -9938,6 +10376,15 @@ thrift@0.13.0: json-int64 "~1.0" nopt "~4.0" +thriftrw@^3.5.0: + version "3.12.0" + resolved "https://registry.yarnpkg.com/thriftrw/-/thriftrw-3.12.0.tgz#30857847755e7f036b2e0a79d11c9f55075539d9" + integrity sha512-4YZvR4DPEI41n4Opwr4jmrLGG4hndxr7387kzRFIIzxHQjarPusH4lGXrugvgb7TtPrfZVTpZCVe44/xUxowEw== + dependencies: + bufrw "^1.3.0" + error "7.0.2" + long "^2.4.0" + throat@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/throat/-/throat-5.0.0.tgz#c5199235803aad18754a667d659b5e72ce16764b" @@ -9952,10 +10399,11 @@ through2@^2.0.0: xtend "~4.0.1" through2@^3.0.0, through2@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/through2/-/through2-3.0.1.tgz#39276e713c3302edf9e388dd9c812dd3b825bd5a" - integrity sha512-M96dvTalPT3YbYLaKaCuwu+j06D/8Jfib0o/PxbVt6Amhv3dUAtW6rTV1jPgJSBG83I/e04Y6xkVdVhSRhi0ww== + version "3.0.2" + resolved "https://registry.yarnpkg.com/through2/-/through2-3.0.2.tgz#99f88931cfc761ec7678b41d5d7336b5b6a07bf4" + integrity sha512-enaDQ4MUyP2W6ZyT6EsMzqBPZaM/avg8iuo+l2d3QCs0J+6RaqkHV/2/lOwDTueBHeJ/2LG9lrLW3d5rWPucuQ== dependencies: + inherits "^2.0.4" readable-stream "2 || 3" through@^2.3.6, through@^2.3.8: @@ -10079,9 +10527,9 @@ tr46@^1.0.1: punycode "^2.1.0" tree-node-cli@^1.2.5: - version "1.3.0" - resolved "https://registry.yarnpkg.com/tree-node-cli/-/tree-node-cli-1.3.0.tgz#f7c03e4d14c7b7c42412d3d2a605940102f192cd" - integrity sha512-7B5IvFiDQMnBjmxHQ4YMdIqklofqla1mINa/ddlxUHC4seEJHdig19C49NONVHmAom/O9dByGvN0PLReCCqqqQ== + version "1.4.0" + resolved "https://registry.yarnpkg.com/tree-node-cli/-/tree-node-cli-1.4.0.tgz#8f4028554610d6ee1cdeb98554a60841a3cfa3ac" + integrity sha512-hBc/cp7rTSHFSFvaTzmHNYyJv87UJBsxsfCoq2DtDQuMES4vhnLuvXZit/asGtZG8edWTCydWeFWoBz9LYkJdQ== dependencies: commander "^5.0.0" @@ -10121,10 +10569,15 @@ ts-jest@25.5.1: semver "6.x" yargs-parser "18.x" -tslib@^1.10.0, tslib@^1.7.1, tslib@^1.8.1, tslib@^1.9.0, tslib@^1.9.3: - version "1.11.2" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.11.2.tgz#9c79d83272c9a7aaf166f73915c9667ecdde3cc9" - integrity sha512-tTSkux6IGPnUGUd1XAZHcpu85MOkIl5zX49pO+jfsie3eP0B6pyhOlLXm3cAC6T7s+euSDDUUV+Acop5WmtkVg== +tslib@^1.10.0, tslib@^1.13.0, tslib@^1.7.1, tslib@^1.8.1, tslib@^1.9.0, tslib@^1.9.3: + version "1.13.0" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.13.0.tgz#c881e13cc7015894ed914862d276436fa9a47043" + integrity sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q== + +tslib@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.0.1.tgz#410eb0d113e5b6356490eec749603725b021b43e" + integrity sha512-SgIkNheinmEBgx1IUNirK0TUD4X9yjjBRTqqjggWCU3pUEqIk3/Uwl3yRixYKT6WjQuGiwDv4NomL3wqRCj+CQ== tslint-config-prettier@1.18.0: version "1.18.0" @@ -10140,10 +10593,10 @@ tslint-plugin-prettier@2.3.0: lines-and-columns "^1.1.6" tslib "^1.7.1" -tslint@6.1.2: - version "6.1.2" - resolved "https://registry.yarnpkg.com/tslint/-/tslint-6.1.2.tgz#2433c248512cc5a7b2ab88ad44a6b1b34c6911cf" - integrity sha512-UyNrLdK3E0fQG/xWNqAFAC5ugtFyPO4JJR1KyyfQAyzR8W0fTRrC91A8Wej4BntFzcvETdCSDa/4PnNYJQLYiA== +tslint@6.1.3: + version "6.1.3" + resolved "https://registry.yarnpkg.com/tslint/-/tslint-6.1.3.tgz#5c23b2eccc32487d5523bd3a470e9aa31789d904" + integrity sha512-IbR4nkT96EQOvKE2PW/djGz8iGNeJ4rF2mBfiYaR/nvUWYKJhLwimoJKgjIFEIDibBtOevj7BqCRL4oHeWWUCg== dependencies: "@babel/code-frame" "^7.0.0" builtin-modules "^1.1.1" @@ -10156,7 +10609,7 @@ tslint@6.1.2: mkdirp "^0.5.3" resolve "^1.3.2" semver "^5.3.0" - tslib "^1.10.0" + tslib "^1.13.0" tsutils "^2.29.0" tsutils@^2.29.0: @@ -10230,15 +10683,15 @@ typedarray@^0.0.6: resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= -typescript@3.8.3: - version "3.8.3" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.8.3.tgz#409eb8544ea0335711205869ec458ab109ee1061" - integrity sha512-MYlEfn5VrLNsgudQTVJeNaQFUAI7DkhnOjdpAp4T+ku1TfQClewlbSuTVHiA+8skNBgaf02TL/kLOvig4y3G8w== +typescript@3.9.4: + version "3.9.4" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.9.4.tgz#5aa0a54904b51b96dfd67870ce2db70251802f10" + integrity sha512-9OL+r0KVHqsYVH7K18IBR9hhC82YwLNlpSZfQDupGcfg8goB9p/s/9Okcy+ztnTeHR2U68xq21/igW9xpoGTgA== unbzip2-stream@^1.0.9: - version "1.4.2" - resolved "https://registry.yarnpkg.com/unbzip2-stream/-/unbzip2-stream-1.4.2.tgz#84eb9e783b186d8fb397515fbb656f312f1a7dbf" - integrity sha512-pZMVAofMrrHX6Ik39hCk470kulCbmZ2SWfQLPmTWqfJV/oUm0gn1CblvHdUu4+54Je6Jq34x8kY6XjTy6dMkOg== + version "1.4.3" + resolved "https://registry.yarnpkg.com/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz#b0da04c4371311df771cdc215e87f2130991ace7" + integrity sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg== dependencies: buffer "^5.2.1" through "^2.3.8" @@ -10379,7 +10832,7 @@ url-parse-lax@^3.0.0: dependencies: prepend-http "^2.0.0" -url-parse@^1.4.3: +url-parse@^1.4.3, url-parse@~1.4.3: version "1.4.7" resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.4.7.tgz#a8a83535e8c00a316e403a5db4ac1b9b853ae278" integrity sha512-d3uaVyzDB9tQoSXFvuSUNFibTd9zxd2bkVrDRvF5TmvWWQwqE4lgYJ5m+x1DbecWkw+LK4RNl2CU1hHuOKPVlg== @@ -10430,12 +10883,12 @@ uuid@3.3.2: resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.2.tgz#1b4af4955eb3077c501c23872fc6513811587131" integrity sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA== -uuid@8.0.0: - version "8.0.0" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.0.0.tgz#bc6ccf91b5ff0ac07bbcdbf1c7c4e150db4dbb6c" - integrity sha512-jOXGuXZAWdsTH7eZLtyXMqUb9EcWMGZNbL9YcGBJl4MH4nrxHmZJhEHvyLFrkxo+28uLb/NYRcStH48fnD0Vzw== +uuid@8.3.0, uuid@^8.1.0: + version "8.3.0" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.0.tgz#ab738085ca22dc9a8c92725e459b1d507df5d6ea" + integrity sha512-fX6Z5o4m6XsXBdli9g7DtWgAx+osMsRRZFKma1mIUsLCz6vRvv+pz5VNbyu9UEDzpMWulZfvpgb/cmDXVulYFQ== -uuid@^3.0.0, uuid@^3.0.1, uuid@^3.3.2, uuid@^3.3.3: +uuid@^3.0.0, uuid@^3.0.1, uuid@^3.2.1, uuid@^3.3.2, uuid@^3.3.3: version "3.4.0" resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== @@ -10445,14 +10898,6 @@ uuid@^7.0.0: resolved "https://registry.yarnpkg.com/uuid/-/uuid-7.0.3.tgz#c5c9f2c8cf25dc0a372c4df1441c41f5bd0c680b" integrity sha512-DPSke0pXhTZgoF/d+WSt2QaKMCFSfx7QegxEWT+JOuHF5aWrKEn0G+ztjuJg/gG8/ItK+rbPCD/yNv8yyih6Cg== -v8-profiler-node8@^6.0.1: - version "6.2.0" - resolved "https://registry.yarnpkg.com/v8-profiler-node8/-/v8-profiler-node8-6.2.0.tgz#f500344634788a3cac0424bc880f702a34899e9f" - integrity sha512-LfkC7i277+2EUZ0AzWV03ic09Kvd6cSs9c3A/XjhEu/QNFqpO2PqbSiJcN8dNR1aSa3in+jO8+vgj8Zjc77UPA== - dependencies: - nan "^2.14.1" - node-pre-gyp "^0.13.0" - v8-to-istanbul@^4.1.3: version "4.1.4" resolved "https://registry.yarnpkg.com/v8-to-istanbul/-/v8-to-istanbul-4.1.4.tgz#b97936f21c0e2d9996d4985e5c5156e9d4e49cd6" @@ -10515,6 +10960,11 @@ w3c-xmlserializer@^1.1.2: webidl-conversions "^4.0.2" xml-name-validator "^3.0.0" +walkdir@^0.4.0: + version "0.4.1" + resolved "https://registry.yarnpkg.com/walkdir/-/walkdir-0.4.1.tgz#dc119f83f4421df52e3061e514228a2db20afa39" + integrity sha512-3eBwRyEln6E1MSzcxcVpQIhRG8Q1jLvEqRmCZqS3dsfXEDR/AhOF4d+jHg1qvDCpYaVRZjENPQyrVxAkQqxPgQ== + walker@^1.0.7, walker@~1.0.5: version "1.0.7" resolved "https://registry.yarnpkg.com/walker/-/walker-1.0.7.tgz#2f7f9b8fd10d677262b18a884e28d19618e028fb" @@ -10528,18 +10978,18 @@ webidl-conversions@^4.0.2: integrity sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg== websocket-driver@>=0.5.1: - version "0.7.3" - resolved "https://registry.yarnpkg.com/websocket-driver/-/websocket-driver-0.7.3.tgz#a2d4e0d4f4f116f1e6297eba58b05d430100e9f9" - integrity sha512-bpxWlvbbB459Mlipc5GBzzZwhoZgGEZLuqPaR0INBGnPAY1vdBX6hPnoFXiw+3yWxDuHyQjO2oXTMyS8A5haFg== + version "0.7.4" + resolved "https://registry.yarnpkg.com/websocket-driver/-/websocket-driver-0.7.4.tgz#89ad5295bbf64b480abcba31e4953aca706f5760" + integrity sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg== dependencies: - http-parser-js ">=0.4.0 <0.4.11" + http-parser-js ">=0.5.1" safe-buffer ">=5.1.0" websocket-extensions ">=0.1.1" websocket-extensions@>=0.1.1: - version "0.1.3" - resolved "https://registry.yarnpkg.com/websocket-extensions/-/websocket-extensions-0.1.3.tgz#5d2ff22977003ec687a4b87073dfbbac146ccf29" - integrity sha512-nqHUnMXmBzT0w570r2JpJxfiSD1IzoI+HGVdd3aZ0yNi3ngvQ4jv1dtHt5VGxfI2yj5yqImPhOK4vmIh2xMbGg== + version "0.1.4" + resolved "https://registry.yarnpkg.com/websocket-extensions/-/websocket-extensions-0.1.4.tgz#7f8473bc839dfd87608adb95d7eb075211578a42" + integrity sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg== whatwg-encoding@^1.0.1, whatwg-encoding@^1.0.5: version "1.0.5" @@ -10594,9 +11044,9 @@ window-size@^0.1.4: integrity sha1-+OGqHuWlPsW/FR/6CXQqatdpeHY= windows-release@^3.1.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/windows-release/-/windows-release-3.3.0.tgz#dce167e9f8be733f21c849ebd4d03fe66b29b9f0" - integrity sha512-2HetyTg1Y+R+rUgrKeUEhAG/ZuOmTrI1NBb3ZyAGQMYmOJjBBPe4MTodghRkmLJZHwkuPi02anbeGP+Zf401LQ== + version "3.3.3" + resolved "https://registry.yarnpkg.com/windows-release/-/windows-release-3.3.3.tgz#1c10027c7225743eec6b89df160d64c2e0293999" + integrity sha512-OSOGH1QYiW5yVor9TtmXKQvt2vjQqbYS+DqmsZw+r7xDwLXEeT3JGW0ZppFmHx4diyXmxt238KFR3N9jzevBRg== dependencies: execa "^1.0.0" @@ -10657,14 +11107,14 @@ ws@^6.1.0: async-limiter "~1.0.0" ws@^7.0.0: - version "7.3.0" - resolved "https://registry.yarnpkg.com/ws/-/ws-7.3.0.tgz#4b2f7f219b3d3737bc1a2fbf145d825b94d38ffd" - integrity sha512-iFtXzngZVXPGgpTlP1rBqsUK82p9tKqsWRPg5L56egiljujJT3vGAYnHANvFxBieXrTFavhzhxW52jnaWV+w2w== + version "7.3.1" + resolved "https://registry.yarnpkg.com/ws/-/ws-7.3.1.tgz#d0547bf67f7ce4f12a72dfe31262c68d7dc551c8" + integrity sha512-D3RuNkynyHmEJIpD2qrgVkc9DQ23OrN/moAwZX4L8DfvszsJxpjQuUq3LMx6HoYji9fbIOBY18XWBsAux1ZZUA== -wtfnode@0.8.1: - version "0.8.1" - resolved "https://registry.yarnpkg.com/wtfnode/-/wtfnode-0.8.1.tgz#d16593ae9b39b252dff6931f95569d9365162389" - integrity sha512-S7S7D8CGHVCtlTn1IWX+nEbxavpL9+fk3vk02RPZHiExyZFb9oKTTig3nEnMCL2yaJ4047V5lAkuulXuO2OsOw== +wtfnode@0.8.3: + version "0.8.3" + resolved "https://registry.yarnpkg.com/wtfnode/-/wtfnode-0.8.3.tgz#39c40830555c9eb69e8bc2c57d6be5abe8bf5d0b" + integrity sha512-Ll7iH8MbRQTE+QTw20Xax/0PM5VeSVSOhsmoR3+knWuJkEWTV5d9yPO6Sb+IDbt9I4UCrKpvHuF9T9zteRNOuA== xdg-basedir@^4.0.0: version "4.0.0" @@ -10716,6 +11166,11 @@ xmlcreate@^1.0.1: resolved "https://registry.yarnpkg.com/xmlcreate/-/xmlcreate-1.0.2.tgz#fa6bf762a60a413fb3dd8f4b03c5b269238d308f" integrity sha1-+mv3YqYKQT+z3Y9LA8WyaSONMI8= +xorshift@^0.2.0: + version "0.2.1" + resolved "https://registry.yarnpkg.com/xorshift/-/xorshift-0.2.1.tgz#fcd82267e9351c13f0fb9c73307f25331d29c63a" + integrity sha1-/NgiZ+k1HBPw+5xzMH8lMx0pxjo= + xtend@^4.0.0, xtend@~4.0.1: version "4.0.2" resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" @@ -10748,6 +11203,11 @@ yallist@^3.0.0, yallist@^3.0.2, yallist@^3.0.3: resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== +yallist@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" + integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== + yamljs@^0.2.1: version "0.2.10" resolved "https://registry.yarnpkg.com/yamljs/-/yamljs-0.2.10.tgz#481cc7c25ca73af59f591f0c96e3ce56c757a40f" @@ -10756,7 +11216,7 @@ yamljs@^0.2.1: argparse "^1.0.7" glob "^7.0.5" -yargs-parser@18.x, yargs-parser@^18.1.1: +yargs-parser@18.x, yargs-parser@^18.1.2: version "18.1.3" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-18.1.3.tgz#be68c4975c6b2abf469236b0c870362fab09a7b0" integrity sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ== @@ -10765,9 +11225,9 @@ yargs-parser@18.x, yargs-parser@^18.1.1: decamelize "^1.2.0" yargs@^15.3.1: - version "15.3.1" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-15.3.1.tgz#9505b472763963e54afe60148ad27a330818e98b" - integrity sha512-92O1HWEjw27sBfgmXiixJWT5hRBp2eobqXicLtPBIDBhYB+1HpwZlXmbW2luivBJHBzki+7VyCLRtAkScbTBQA== + version "15.4.1" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-15.4.1.tgz#0d87a16de01aee9d8bec2bfbf74f67851730f4f8" + integrity sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A== dependencies: cliui "^6.0.0" decamelize "^1.2.0" @@ -10779,7 +11239,7 @@ yargs@^15.3.1: string-width "^4.2.0" which-module "^2.0.0" y18n "^4.0.0" - yargs-parser "^18.1.1" + yargs-parser "^18.1.2" yargs@^2.3.0: version "2.3.0"