diff --git a/THIRD_PARTY_NOTICES.md b/THIRD_PARTY_NOTICES.md index 46798d4f52..fdd57eee50 100644 --- a/THIRD_PARTY_NOTICES.md +++ b/THIRD_PARTY_NOTICES.md @@ -16,7 +16,6 @@ code, the source code can be found at [https://github.com/newrelic/node-newrelic * [@grpc/grpc-js](#grpcgrpc-js) * [@grpc/proto-loader](#grpcproto-loader) -* [@newrelic/aws-sdk](#newrelicaws-sdk) * [@newrelic/ritm](#newrelicritm) * [@newrelic/security-agent](#newrelicsecurity-agent) * [@tyriar/fibonacci-heap](#tyriarfibonacci-heap) @@ -32,14 +31,19 @@ code, the source code can be found at [https://github.com/newrelic/node-newrelic **[devDependencies](#devDependencies)** +* [@aws-sdk/client-s3](#aws-sdkclient-s3) +* [@aws-sdk/s3-request-presigner](#aws-sdks3-request-presigner) * [@koa/router](#koarouter) * [@newrelic/eslint-config](#newreliceslint-config) * [@newrelic/newrelic-oss-cli](#newrelicnewrelic-oss-cli) * [@newrelic/test-utilities](#newrelictest-utilities) * [@octokit/rest](#octokitrest) * [@slack/bolt](#slackbolt) +* [@smithy/eventstream-codec](#smithyeventstream-codec) +* [@smithy/util-utf8](#smithyutil-utf8) * [ajv](#ajv) * [async](#async) +* [aws-sdk](#aws-sdk) * [c8](#c8) * [clean-jsdoc-theme](#clean-jsdoc-theme) * [commander](#commander) @@ -89,7 +93,7 @@ code, the source code can be found at [https://github.com/newrelic/node-newrelic ### @grpc/grpc-js -This product includes source derived from [@grpc/grpc-js](https://github.com/grpc/grpc-node/tree/master/packages/grpc-js) ([v1.10.6](https://github.com/grpc/grpc-node/tree/master/packages/grpc-js/tree/v1.10.6)), distributed under the [Apache-2.0 License](https://github.com/grpc/grpc-node/tree/master/packages/grpc-js/blob/v1.10.6/LICENSE): +This product includes source derived from [@grpc/grpc-js](https://github.com/grpc/grpc-node/tree/master/packages/grpc-js) ([v1.10.0](https://github.com/grpc/grpc-node/tree/master/packages/grpc-js/tree/v1.10.0)), distributed under the [Apache-2.0 License](https://github.com/grpc/grpc-node/tree/master/packages/grpc-js/blob/v1.10.0/LICENSE): ``` Apache License @@ -298,7 +302,7 @@ This product includes source derived from [@grpc/grpc-js](https://github.com/grp ### @grpc/proto-loader -This product includes source derived from [@grpc/proto-loader](https://github.com/grpc/grpc-node) ([v0.7.12](https://github.com/grpc/grpc-node/tree/v0.7.12)), distributed under the [Apache-2.0 License](https://github.com/grpc/grpc-node/blob/v0.7.12/LICENSE): +This product includes source derived from [@grpc/proto-loader](https://github.com/grpc/grpc-node) ([v0.7.10](https://github.com/grpc/grpc-node/tree/v0.7.10)), distributed under the [Apache-2.0 License](https://github.com/grpc/grpc-node/blob/v0.7.10/LICENSE): ``` Apache License @@ -505,214 +509,6 @@ This product includes source derived from [@grpc/proto-loader](https://github.co ``` -### @newrelic/aws-sdk - -This product includes source derived from [@newrelic/aws-sdk](https://github.com/newrelic/node-newrelic-aws-sdk) ([v7.4.1](https://github.com/newrelic/node-newrelic-aws-sdk/tree/v7.4.1)), distributed under the [Apache-2.0 License](https://github.com/newrelic/node-newrelic-aws-sdk/blob/v7.4.1/LICENSE): - -``` - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -``` - ### @newrelic/ritm This product includes source derived from [@newrelic/ritm](https://github.com/newrelic-forks/require-in-the-middle) ([v7.2.0](https://github.com/newrelic-forks/require-in-the-middle/tree/v7.2.0)), distributed under the [MIT License](https://github.com/newrelic-forks/require-in-the-middle/blob/v7.2.0/LICENSE): @@ -745,7 +541,7 @@ SOFTWARE. ### @newrelic/security-agent -This product includes source derived from [@newrelic/security-agent](https://github.com/newrelic/csec-node-agent) ([v1.2.0](https://github.com/newrelic/csec-node-agent/tree/v1.2.0)), distributed under the [UNKNOWN License](https://github.com/newrelic/csec-node-agent/blob/v1.2.0/LICENSE): +This product includes source derived from [@newrelic/security-agent](https://github.com/newrelic/csec-node-agent) ([v1.1.1](https://github.com/newrelic/csec-node-agent/tree/v1.1.1)), distributed under the [UNKNOWN License](https://github.com/newrelic/csec-node-agent/blob/v1.1.1/LICENSE): ``` ## New Relic Software License v1.0 @@ -851,31 +647,18 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ### https-proxy-agent -This product includes source derived from [https-proxy-agent](https://github.com/TooTallNate/proxy-agents) ([v7.0.4](https://github.com/TooTallNate/proxy-agents/tree/v7.0.4)), distributed under the [MIT License](https://github.com/TooTallNate/proxy-agents/blob/v7.0.4/LICENSE): +This product includes source derived from [https-proxy-agent](https://github.com/TooTallNate/proxy-agents) ([v7.0.2](https://github.com/TooTallNate/proxy-agents/tree/v7.0.2)), distributed under the [MIT License](https://github.com/TooTallNate/proxy-agents/blob/v7.0.2/README.md): ``` -(The MIT License) +MIT License -Copyright (c) 2013 Nathan Rajlich +Copyright (c) -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -'Software'), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ``` ### import-in-the-middle @@ -1038,33 +821,1140 @@ IN THE SOFTWARE. This product includes source derived from [semver](https://github.com/npm/node-semver) ([v7.6.0](https://github.com/npm/node-semver/tree/v7.6.0)), distributed under the [ISC License](https://github.com/npm/node-semver/blob/v7.6.0/LICENSE): -``` -The ISC License +``` +The ISC License + +Copyright (c) Isaac Z. Schlueter and Contributors + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR +IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +``` + +### winston-transport + +This product includes source derived from [winston-transport](https://github.com/winstonjs/winston-transport) ([v4.7.0](https://github.com/winstonjs/winston-transport/tree/v4.7.0)), distributed under the [MIT License](https://github.com/winstonjs/winston-transport/blob/v4.7.0/LICENSE): + +``` +The MIT License (MIT) + +Copyright (c) 2015 Charlie Robbins & the contributors. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +``` + + +## devDependencies + +### @aws-sdk/client-s3 + +This product includes source derived from [@aws-sdk/client-s3](https://github.com/aws/aws-sdk-js-v3) ([v3.556.0](https://github.com/aws/aws-sdk-js-v3/tree/v3.556.0)), distributed under the [Apache-2.0 License](https://github.com/aws/aws-sdk-js-v3/blob/v3.556.0/LICENSE): + +``` + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2018-2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +``` + +### @aws-sdk/s3-request-presigner + +This product includes source derived from [@aws-sdk/s3-request-presigner](https://github.com/aws/aws-sdk-js-v3) ([v3.556.0](https://github.com/aws/aws-sdk-js-v3/tree/v3.556.0)), distributed under the [Apache-2.0 License](https://github.com/aws/aws-sdk-js-v3/blob/v3.556.0/LICENSE): + +``` + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +``` + +### @koa/router + +This product includes source derived from [@koa/router](https://github.com/koajs/router) ([v12.0.1](https://github.com/koajs/router/tree/v12.0.1)), distributed under the [MIT License](https://github.com/koajs/router/blob/v12.0.1/LICENSE): + +``` +The MIT License (MIT) + +Copyright (c) 2015 Alexander C. Mingoia and @koajs contributors + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +``` + +### @newrelic/eslint-config + +This product includes source derived from [@newrelic/eslint-config](https://github.com/newrelic/eslint-config-newrelic) ([v0.3.0](https://github.com/newrelic/eslint-config-newrelic/tree/v0.3.0)), distributed under the [Apache-2.0 License](https://github.com/newrelic/eslint-config-newrelic/blob/v0.3.0/LICENSE): + +``` + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +``` + +### @newrelic/newrelic-oss-cli + +This product includes source derived from [@newrelic/newrelic-oss-cli](https://github.com/newrelic/newrelic-oss-cli) ([v0.1.2](https://github.com/newrelic/newrelic-oss-cli/tree/v0.1.2)), distributed under the [Apache-2.0 License](https://github.com/newrelic/newrelic-oss-cli/blob/v0.1.2/LICENSE): + +``` + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +``` + +### @newrelic/test-utilities + +This product includes source derived from [@newrelic/test-utilities](https://github.com/newrelic/node-test-utilities) ([v8.5.0](https://github.com/newrelic/node-test-utilities/tree/v8.5.0)), distributed under the [Apache-2.0 License](https://github.com/newrelic/node-test-utilities/blob/v8.5.0/LICENSE): + +``` + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] -Copyright (c) Isaac Z. Schlueter and Contributors + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at -Permission to use, copy, modify, and/or distribute this software for any -purpose with or without fee is hereby granted, provided that the above -copyright notice and this permission notice appear in all copies. + http://www.apache.org/licenses/LICENSE-2.0 -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR -IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. ``` -### winston-transport +### @octokit/rest -This product includes source derived from [winston-transport](https://github.com/winstonjs/winston-transport) ([v4.7.0](https://github.com/winstonjs/winston-transport/tree/v4.7.0)), distributed under the [MIT License](https://github.com/winstonjs/winston-transport/blob/v4.7.0/LICENSE): +This product includes source derived from [@octokit/rest](https://github.com/octokit/rest.js) ([v18.12.0](https://github.com/octokit/rest.js/tree/v18.12.0)), distributed under the [MIT License](https://github.com/octokit/rest.js/blob/v18.12.0/LICENSE): ``` -The MIT License (MIT) +The MIT License -Copyright (c) 2015 Charlie Robbins & the contributors. +Copyright (c) 2012 Cloud9 IDE, Inc. (Mike de Boer) +Copyright (c) 2017-2018 Octokit contributors Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -1073,31 +1963,28 @@ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. ``` +### @slack/bolt -## devDependencies - -### @koa/router - -This product includes source derived from [@koa/router](https://github.com/koajs/router) ([v12.0.1](https://github.com/koajs/router/tree/v12.0.1)), distributed under the [MIT License](https://github.com/koajs/router/blob/v12.0.1/LICENSE): +This product includes source derived from [@slack/bolt](https://github.com/slackapi/bolt) ([v3.17.1](https://github.com/slackapi/bolt/tree/v3.17.1)), distributed under the [MIT License](https://github.com/slackapi/bolt/blob/v3.17.1/LICENSE): ``` The MIT License (MIT) -Copyright (c) 2015 Alexander C. Mingoia and @koajs contributors +Copyright (c) 2016-2018 Robots & Pencils +Copyright (c) 2019- Slack Technologies, LLC Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -1106,25 +1993,25 @@ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. ``` -### @newrelic/eslint-config +### @smithy/eventstream-codec -This product includes source derived from [@newrelic/eslint-config](https://github.com/newrelic/eslint-config-newrelic) ([v0.3.0](https://github.com/newrelic/eslint-config-newrelic/tree/v0.3.0)), distributed under the [Apache-2.0 License](https://github.com/newrelic/eslint-config-newrelic/blob/v0.3.0/LICENSE): +This product includes source derived from [@smithy/eventstream-codec](https://github.com/awslabs/smithy-typescript) ([v2.2.0](https://github.com/awslabs/smithy-typescript/tree/v2.2.0)), distributed under the [Apache-2.0 License](https://github.com/awslabs/smithy-typescript/blob/v2.2.0/LICENSE): ``` - Apache License + Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -1304,7 +2191,7 @@ This product includes source derived from [@newrelic/eslint-config](https://gith APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" + boilerplate notice, with the fields enclosed by brackets "{}" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a @@ -1312,7 +2199,7 @@ This product includes source derived from [@newrelic/eslint-config](https://gith same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright [yyyy] [name of copyright owner] + Copyright 2018-2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -1328,12 +2215,12 @@ This product includes source derived from [@newrelic/eslint-config](https://gith ``` -### @newrelic/newrelic-oss-cli +### @smithy/util-utf8 -This product includes source derived from [@newrelic/newrelic-oss-cli](https://github.com/newrelic/newrelic-oss-cli) ([v0.1.2](https://github.com/newrelic/newrelic-oss-cli/tree/v0.1.2)), distributed under the [Apache-2.0 License](https://github.com/newrelic/newrelic-oss-cli/blob/v0.1.2/LICENSE): +This product includes source derived from [@smithy/util-utf8](https://github.com/awslabs/smithy-typescript) ([v2.3.0](https://github.com/awslabs/smithy-typescript/tree/v2.3.0)), distributed under the [Apache-2.0 License](https://github.com/awslabs/smithy-typescript/blob/v2.3.0/LICENSE): ``` - Apache License +Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -1513,7 +2400,7 @@ This product includes source derived from [@newrelic/newrelic-oss-cli](https://g APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" + boilerplate notice, with the fields enclosed by brackets "{}" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a @@ -1521,7 +2408,7 @@ This product includes source derived from [@newrelic/newrelic-oss-cli](https://g same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright [yyyy] [name of copyright owner] + Copyright 2018-2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -1536,11 +2423,69 @@ This product includes source derived from [@newrelic/newrelic-oss-cli](https://g limitations under the License. ``` -### @newrelic/test-utilities +### ajv -This product includes source derived from [@newrelic/test-utilities](https://github.com/newrelic/node-test-utilities) ([v8.5.0](https://github.com/newrelic/node-test-utilities/tree/v8.5.0)), distributed under the [Apache-2.0 License](https://github.com/newrelic/node-test-utilities/blob/v8.5.0/LICENSE): +This product includes source derived from [ajv](https://github.com/ajv-validator/ajv) ([v6.12.6](https://github.com/ajv-validator/ajv/tree/v6.12.6)), distributed under the [MIT License](https://github.com/ajv-validator/ajv/blob/v6.12.6/LICENSE): + +``` +The MIT License (MIT) + +Copyright (c) 2015-2017 Evgeny Poberezkin + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +``` + +### async + +This product includes source derived from [async](https://github.com/caolan/async) ([v3.2.5](https://github.com/caolan/async/tree/v3.2.5)), distributed under the [MIT License](https://github.com/caolan/async/blob/v3.2.5/LICENSE): + +``` +Copyright (c) 2010-2018 Caolan McMahon + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +``` + +### aws-sdk + +This product includes source derived from [aws-sdk](https://github.com/aws/aws-sdk-js) ([v2.1604.0](https://github.com/aws/aws-sdk-js/tree/v2.1604.0)), distributed under the [Apache-2.0 License](https://github.com/aws/aws-sdk-js/blob/v2.1604.0/LICENSE.txt): ``` + Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -1729,7 +2674,7 @@ This product includes source derived from [@newrelic/test-utilities](https://git same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright [yyyy] [name of copyright owner] + Copyright 2012-2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -1745,123 +2690,6 @@ This product includes source derived from [@newrelic/test-utilities](https://git ``` -### @octokit/rest - -This product includes source derived from [@octokit/rest](https://github.com/octokit/rest.js) ([v18.12.0](https://github.com/octokit/rest.js/tree/v18.12.0)), distributed under the [MIT License](https://github.com/octokit/rest.js/blob/v18.12.0/LICENSE): - -``` -The MIT License - -Copyright (c) 2012 Cloud9 IDE, Inc. (Mike de Boer) -Copyright (c) 2017-2018 Octokit contributors - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -``` - -### @slack/bolt - -This product includes source derived from [@slack/bolt](https://github.com/slackapi/bolt) ([v3.17.1](https://github.com/slackapi/bolt/tree/v3.17.1)), distributed under the [MIT License](https://github.com/slackapi/bolt/blob/v3.17.1/LICENSE): - -``` -The MIT License (MIT) - -Copyright (c) 2016-2018 Robots & Pencils -Copyright (c) 2019- Slack Technologies, LLC - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - -``` - -### ajv - -This product includes source derived from [ajv](https://github.com/ajv-validator/ajv) ([v6.12.6](https://github.com/ajv-validator/ajv/tree/v6.12.6)), distributed under the [MIT License](https://github.com/ajv-validator/ajv/blob/v6.12.6/LICENSE): - -``` -The MIT License (MIT) - -Copyright (c) 2015-2017 Evgeny Poberezkin - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - - -``` - -### async - -This product includes source derived from [async](https://github.com/caolan/async) ([v3.2.5](https://github.com/caolan/async/tree/v3.2.5)), distributed under the [MIT License](https://github.com/caolan/async/blob/v3.2.5/LICENSE): - -``` -Copyright (c) 2010-2018 Caolan McMahon - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -``` - ### c8 This product includes source derived from [c8](https://github.com/bcoe/c8) ([v8.0.1](https://github.com/bcoe/c8/tree/v8.0.1)), distributed under the [ISC License](https://github.com/bcoe/c8/blob/v8.0.1/LICENSE.txt): @@ -2053,7 +2881,7 @@ THE SOFTWARE. ### eslint-plugin-jsdoc -This product includes source derived from [eslint-plugin-jsdoc](https://github.com/gajus/eslint-plugin-jsdoc) ([v48.2.3](https://github.com/gajus/eslint-plugin-jsdoc/tree/v48.2.3)), distributed under the [BSD-3-Clause License](https://github.com/gajus/eslint-plugin-jsdoc/blob/v48.2.3/LICENSE): +This product includes source derived from [eslint-plugin-jsdoc](https://github.com/gajus/eslint-plugin-jsdoc) ([v48.0.6](https://github.com/gajus/eslint-plugin-jsdoc/tree/v48.0.6)), distributed under the [BSD-3-Clause License](https://github.com/gajus/eslint-plugin-jsdoc/blob/v48.0.6/LICENSE): ``` Copyright (c) 2018, Gajus Kuizinas (http://gajus.com/) @@ -2258,7 +3086,7 @@ Library. ### eslint -This product includes source derived from [eslint](https://github.com/eslint/eslint) ([v8.57.0](https://github.com/eslint/eslint/tree/v8.57.0)), distributed under the [MIT License](https://github.com/eslint/eslint/blob/v8.57.0/LICENSE): +This product includes source derived from [eslint](https://github.com/eslint/eslint) ([v8.56.0](https://github.com/eslint/eslint/tree/v8.56.0)), distributed under the [MIT License](https://github.com/eslint/eslint/blob/v8.56.0/LICENSE): ``` Copyright OpenJS Foundation and other contributors, @@ -2635,7 +3463,7 @@ SOFTWARE. ### lockfile-lint -This product includes source derived from [lockfile-lint](https://github.com/lirantal/lockfile-lint) ([v4.13.2](https://github.com/lirantal/lockfile-lint/tree/v4.13.2)), distributed under the [Apache-2.0 License](https://github.com/lirantal/lockfile-lint/blob/v4.13.2/LICENSE): +This product includes source derived from [lockfile-lint](https://github.com/lirantal/lockfile-lint) ([v4.12.1](https://github.com/lirantal/lockfile-lint/tree/v4.12.1)), distributed under the [Apache-2.0 License](https://github.com/lirantal/lockfile-lint/blob/v4.12.1/LICENSE): ``` @@ -3188,7 +4016,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ### @newrelic/native-metrics -This product includes source derived from [@newrelic/native-metrics](https://github.com/newrelic/node-native-metrics) ([v10.1.1](https://github.com/newrelic/node-native-metrics/tree/v10.1.1)), distributed under the [Apache-2.0 License](https://github.com/newrelic/node-native-metrics/blob/v10.1.1/LICENSE): +This product includes source derived from [@newrelic/native-metrics](https://github.com/newrelic/node-native-metrics) ([v10.0.1](https://github.com/newrelic/node-native-metrics/tree/v10.0.1)), distributed under the [Apache-2.0 License](https://github.com/newrelic/node-native-metrics/blob/v10.0.1/LICENSE): ``` Apache License diff --git a/lib/instrumentation/aws-sdk/nr-hooks.js b/lib/instrumentation/aws-sdk/nr-hooks.js new file mode 100644 index 0000000000..b15f850a98 --- /dev/null +++ b/lib/instrumentation/aws-sdk/nr-hooks.js @@ -0,0 +1,29 @@ +/* + * Copyright 2020 New Relic Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +'use strict' +const InstrumentationDescriptor = require('../../instrumentation-descriptor') + +const instrumentations = [ + { + type: InstrumentationDescriptor.TYPE_CONGLOMERATE, + moduleName: 'aws-sdk', + onRequire: require('./v2/instrumentation') + }, + { + type: InstrumentationDescriptor.TYPE_CONGLOMERATE, + moduleName: '@aws-sdk/smithy-client', + onRequire: require('./v3/smithy-client'), + shimName: 'aws-sdk' + }, + { + type: InstrumentationDescriptor.TYPE_CONGLOMERATE, + moduleName: '@smithy/smithy-client', + onRequire: require('./v3/smithy-client'), + shimName: 'aws-sdk' + } +] + +module.exports = instrumentations diff --git a/lib/instrumentation/aws-sdk/util.js b/lib/instrumentation/aws-sdk/util.js new file mode 100644 index 0000000000..c5b4912a8a --- /dev/null +++ b/lib/instrumentation/aws-sdk/util.js @@ -0,0 +1,38 @@ +/* + * Copyright 2020 New Relic Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +'use strict' +const UNKNOWN = 'Unknown' +const { + params: { DatastoreParameters } +} = require('../../shim/specs') + +function grabLastUrlSegment(url = '/') { + // cast URL as string, and an empty + // string for null, undefined, NaN etc. + url = '' + (url || '/') + const lastSlashIndex = url.lastIndexOf('/') + return url.substr(lastSlashIndex + 1) +} + +/** + * Retrieves the db segment params from endpoint and command parameters + * + * @param {Object} endpoint instance of ddb endpoint + * @param {Object} params parameters passed to a ddb command + * @returns {Object} + */ +function setDynamoParameters(endpoint, params) { + return new DatastoreParameters({ + host: endpoint && (endpoint.host || endpoint.hostname), + port_path_or_id: (endpoint && endpoint.port) || 443, + collection: (params && params.TableName) || UNKNOWN + }) +} + +module.exports = { + grabLastUrlSegment, + setDynamoParameters +} diff --git a/lib/instrumentation/aws-sdk/v2/core.js b/lib/instrumentation/aws-sdk/v2/core.js new file mode 100644 index 0000000000..3ae3635f3f --- /dev/null +++ b/lib/instrumentation/aws-sdk/v2/core.js @@ -0,0 +1,105 @@ +/* + * Copyright 2020 New Relic Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +'use strict' + +const UNKNOWN = 'Unknown' +const symbols = require('../../../symbols') +const InstrumentationDescriptor = require('../../../instrumentation-descriptor') + +function validate(shim, AWS) { + if (!shim.isFunction(AWS.NodeHttpClient)) { + shim.logger.debug('Could not find NodeHttpClient, not instrumenting.') + return false + } + if (!shim.isFunction(AWS.Service) || !shim.isFunction(AWS.Service.prototype.makeRequest)) { + shim.logger.debug('Could not find AWS.Service#makeRequest, not instrumenting.') + return false + } + return true +} + +function instrument(shim, AWS) { + shim.wrap(AWS.NodeHttpClient.prototype, 'handleRequest', wrapHandleRequest) + shim.wrapReturn(AWS.Service.prototype, 'makeRequest', wrapMakeRequest) +} + +function wrapHandleRequest(shim, handleRequest) { + return function wrappedHandleRequest(httpRequest) { + if (httpRequest) { + if (!httpRequest.headers) { + httpRequest.headers = Object.create(null) + } + httpRequest.headers[symbols.disableDT] = true + } else { + shim.logger.debug('Unknown arguments to AWS.NodeHttpClient#handleRequest!') + } + + return handleRequest.apply(this, arguments) + } +} + +function wrapMakeRequest(shim, fn, name, request) { + if (!request) { + shim.logger.trace('No request object returned from Service#makeRequest') + return + } + + const service = getServiceName(this) + const region = this?.config?.region + request.on('complete', function onAwsRequestComplete() { + const httpRequest = request.httpRequest && request.httpRequest.stream + const segment = shim.getSegment(httpRequest) + if (!httpRequest || !segment) { + shim.logger.trace('No segment found for request, not extracting information.') + return + } + + const requestRegion = request?.httpRequest?.region + const requestId = request?.response?.requestId + + segment.addAttribute('aws.operation', request.operation || UNKNOWN) + segment.addAttribute('aws.requestId', requestId || UNKNOWN) + segment.addAttribute('aws.service', service || UNKNOWN) + segment.addAttribute('aws.region', requestRegion || region || UNKNOWN) + }) + + shim.wrap(request, 'promise', function wrapPromiseFunc(shim, original) { + const activeSegment = shim.getActiveSegment() + + return function wrappedPromiseFunc() { + if (!activeSegment) { + return original.apply(this, arguments) + } + + const promise = shim.applySegment(original, activeSegment, false, this, arguments) + + return shim.bindPromise(promise, activeSegment) + } + }) +} + +function getServiceName(service) { + if (service.api && (service.api.abbreviation || service.api.serviceId)) { + return service.api.abbreviation || service.api.serviceId + } + + // In theory, getting the `constructor.prototype` should be redundant with + // checking `service`. However, the aws-sdk dynamically generates classes and + // doing this deep check was the recommended method by the maintainers. + const constructor = service.constructor + const api = constructor && constructor.prototype && constructor.prototype.api + if (api) { + return api.abbreviation || api.serviceId + } + return null +} + +module.exports = { + name: 'core', + type: InstrumentationDescriptor.TYPE_GENERIC, + validate, + instrument +} diff --git a/lib/instrumentation/aws-sdk/v2/dynamodb.js b/lib/instrumentation/aws-sdk/v2/dynamodb.js new file mode 100644 index 0000000000..9a16b5ac70 --- /dev/null +++ b/lib/instrumentation/aws-sdk/v2/dynamodb.js @@ -0,0 +1,103 @@ +/* + * Copyright 2020 New Relic Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +'use strict' +const InstrumentationDescriptor = require('../../../instrumentation-descriptor') + +const DDB_OPERATIONS = [ + 'putItem', + 'getItem', + 'updateItem', + 'deleteItem', + 'createTable', + 'deleteTable', + 'query', + 'scan' +] + +const DOC_CLIENT_OPERATIONS = [ + 'get', + 'put', + 'update', + 'delete', + 'batchGet', + 'batchWrite', + 'transactGet', + 'transactWrite', + 'query', + 'scan' +] +const { + OperationSpec, + params: { DatastoreParameters } +} = require('../../../shim/specs') + +const { setDynamoParameters } = require('../util') + +function instrument(shim, AWS) { + shim.setDatastore(shim.DYNAMODB) + + // DynamoDB's service API methods are dynamically generated + // in the constructor so we have to wrap the return. + shim.wrapReturn(AWS, 'DynamoDB', function wrapDynamo(shim, fn, name, ddb) { + shim.recordOperation( + ddb, + DDB_OPERATIONS, + function wrapMethod(shim, original, operationName, args) { + const params = args[0] + + return new OperationSpec({ + name: operationName, + parameters: setDynamoParameters(this.endpoint, params), + callback: shim.LAST, + opaque: true + }) + } + ) + }) + + // DocumentClient's API is predefined so we can instrument the prototype. + // DocumentClient does defer to DynamoDB but it also does enough individual + // steps for the request we want to hide that instrumenting specifically and + // setting to opaque is currently required. + const docClientProto = AWS.DynamoDB.DocumentClient.prototype + shim.recordOperation( + docClientProto, + DOC_CLIENT_OPERATIONS, + function wrapOperation(shim, original, operationName, args) { + const params = args[0] + const dynamoOperation = this.serviceClientOperationsMap[operationName] + + // DocumentClient can be defined with a different service such as AmazonDaxClient. + // In these cases, an endpoint property may not exist. In the DAX case, + // the eventual cached endpoint to be hit is not known at this point. + const endpoint = this.service && this.service.endpoint + + return new OperationSpec({ + name: dynamoOperation, + parameters: new DatastoreParameters({ + host: endpoint?.host, + port_path_or_id: endpoint?.port, + collection: params?.TableName || 'Unknown' + }), + callback: shim.LAST, + opaque: true + }) + } + ) +} + +module.exports = { + name: 'dynamodb', + type: InstrumentationDescriptor.TYPE_DATASTORE, + instrument, + validate: (shim, AWS) => { + if (!shim.isFunction(AWS.DynamoDB)) { + shim.logger.debug('Could not find DynamoDB, not instrumenting.') + return false + } + return true + } +} diff --git a/lib/instrumentation/aws-sdk/v2/instrumentation-helper.js b/lib/instrumentation/aws-sdk/v2/instrumentation-helper.js new file mode 100644 index 0000000000..ff951118f9 --- /dev/null +++ b/lib/instrumentation/aws-sdk/v2/instrumentation-helper.js @@ -0,0 +1,31 @@ +/* + * Copyright 2020 New Relic Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +'use strict' + +/** + * Series of tests to determine if the library + * has the features needed to provide instrumentation + * @param AWS + */ +const instrumentationSupported = function instrumentationSupported(AWS) { + // instrumentation requires the serviceClientOperationsMap property + /* eslint-disable-next-line */ + if ( + !AWS || + !AWS.DynamoDB || + !AWS.DynamoDB.DocumentClient || + !AWS.DynamoDB.DocumentClient.prototype || + !AWS.DynamoDB.DocumentClient.prototype.serviceClientOperationsMap + ) { + return false + } + + return true +} + +module.exports = { + instrumentationSupported +} diff --git a/lib/instrumentation/aws-sdk/v2/instrumentation.js b/lib/instrumentation/aws-sdk/v2/instrumentation.js new file mode 100644 index 0000000000..a9f002da40 --- /dev/null +++ b/lib/instrumentation/aws-sdk/v2/instrumentation.js @@ -0,0 +1,34 @@ +/* + * Copyright 2020 New Relic Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +'use strict' + +const INSTRUMENTATIONS = [ + require('./core'), + require('./dynamodb'), + require('./sqs'), + require('./sns') +] + +const helper = require('./instrumentation-helper') + +module.exports = function initialize(shim, AWS) { + if (!helper.instrumentationSupported(AWS)) { + return false + } + // Validate every instrumentation before attempting to run any of them. + for (const instrumentation of INSTRUMENTATIONS) { + if (!instrumentation.validate(shim, AWS)) { + return false + } + } + + for (const instrumentation of INSTRUMENTATIONS) { + const subshim = shim.makeSpecializedShim(instrumentation.type, instrumentation.name) + instrumentation.instrument(subshim, AWS) + } + + return true +} diff --git a/lib/instrumentation/aws-sdk/v2/sns.js b/lib/instrumentation/aws-sdk/v2/sns.js new file mode 100644 index 0000000000..7cd9635036 --- /dev/null +++ b/lib/instrumentation/aws-sdk/v2/sns.js @@ -0,0 +1,42 @@ +/* + * Copyright 2020 New Relic Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +'use strict' +const { MessageSpec } = require('../../../shim/specs') +const InstrumentationDescriptor = require('../../../instrumentation-descriptor') + +module.exports = { + name: 'sns', + type: InstrumentationDescriptor.TYPE_MESSAGE, + validate: (shim, AWS) => { + if (!shim.isFunction(AWS.SNS)) { + shim.logger.debug('Could not find SNS, not instrumenting.') + return false + } + return true + }, + instrument +} + +function instrument(shim, AWS) { + shim.setLibrary(shim.SNS) + + shim.wrapReturn(AWS, 'SNS', function wrapSns(shim, original, name, sns) { + shim.recordProduce(sns, 'publish', wrapPublish) + }) +} + +function wrapPublish(shim, original, name, args) { + return new MessageSpec({ + callback: shim.LAST, + destinationName: getDestinationName(args[0]), + destinationType: shim.TOPIC, + opaque: true + }) +} + +function getDestinationName({ TopicArn, TargetArn }) { + return TopicArn || TargetArn || 'PhoneNumber' // We don't want the value of PhoneNumber +} diff --git a/lib/instrumentation/aws-sdk/v2/sqs.js b/lib/instrumentation/aws-sdk/v2/sqs.js new file mode 100644 index 0000000000..da820f8857 --- /dev/null +++ b/lib/instrumentation/aws-sdk/v2/sqs.js @@ -0,0 +1,50 @@ +/* + * Copyright 2020 New Relic Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +'use strict' + +const { grabLastUrlSegment } = require('../util') +const { MessageSpec } = require('../../../shim/specs') +const InstrumentationDescriptor = require('../../../instrumentation-descriptor') + +module.exports = { + name: 'sqs', + type: InstrumentationDescriptor.TYPE_MESSAGE, + validate, + instrument +} + +function validate(shim, AWS) { + if (!shim.isFunction(AWS.SQS)) { + shim.logger.debug('Could not find AWS.SQS') + + return false + } + + return true +} + +function instrument(shim, AWS) { + // This needs to happen before any instrumentation + shim.setLibrary(shim.SQS) + + shim.wrapReturn(AWS, 'SQS', function wrapSqs(shim, original, name, sqs) { + shim.recordProduce(sqs, 'sendMessage', recordMessageApi) + shim.recordProduce(sqs, 'sendMessageBatch', recordMessageApi) + shim.recordConsume(sqs, 'receiveMessage', recordMessageApi) + }) +} + +function recordMessageApi(shim, original, name, args) { + const params = args[0] + const queueName = grabLastUrlSegment(params.QueueUrl) + + return new MessageSpec({ + callback: shim.LAST, + destinationName: queueName, + destinationType: shim.QUEUE, + opaque: true + }) +} diff --git a/lib/instrumentation/aws-sdk/v3/bedrock.js b/lib/instrumentation/aws-sdk/v3/bedrock.js new file mode 100644 index 0000000000..f20b2a6f1c --- /dev/null +++ b/lib/instrumentation/aws-sdk/v3/bedrock.js @@ -0,0 +1,301 @@ +/* + * Copyright 2024 New Relic Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +'use strict' +const { + LlmChatCompletionMessage, + LlmChatCompletionSummary, + LlmEmbedding, + LlmError, + BedrockCommand, + BedrockResponse, + StreamHandler +} = require('../../../llm-events/aws-bedrock') + +const { DESTINATIONS } = require('../../../config/attribute-filter') +const { AI } = require('../../../metrics/names') +const { RecorderSpec } = require('../../../shim/specs') +const InstrumentationDescriptor = require('../../../instrumentation-descriptor') + +let TRACKING_METRIC + +/** + * Helper to determine if we should instrument the bedrock middleware call + * + * @param {Object} config agent configuration + * @returns {boolean} to instrument or not to instrument + */ +function shouldSkipInstrumentation(config) { + return !config?.ai_monitoring?.enabled === true +} + +/** + * Helper to determine if streaming is enabled + * + * @param {object} params to function + * @param {string} params.commandName name of command + * @param {object} params.config agent configuration + * @returns {boolean} if streaming command and `ai_monitoring.streaming.enabled` is truthy + */ +function isStreamingEnabled({ commandName, config }) { + return ( + commandName === 'InvokeModelWithResponseStreamCommand' && + config.ai_monitoring?.streaming?.enabled + ) +} + +/** + * Enqueues a LLM event to the custom event aggregator + * @param {object} params input params + * @param {Agent} params.agent NR agent instance + * @param {string} params.type LLM event type + * @param {object} params.msg LLM event + */ +function recordEvent({ agent, type, msg }) { + msg.serialize() + agent.customEventAggregator.add([{ type, timestamp: Date.now() }, msg]) +} + +/** + * Increments the tracking metric and sets the llm attribute on transactions + * + * @param {object} params input params + * @param {Agent} params.agent NR agent instance + * @param {TraceSegment} params.segment active segment + */ +function addLlmMeta({ agent, segment }) { + agent.metrics.getOrCreateMetric(TRACKING_METRIC).incrementCallCount() + segment.transaction.trace.attributes.addAttribute(DESTINATIONS.TRANS_EVENT, 'llm', true) + // end segment to get a consistent segment duration + // for both the LLM events and the segment + segment.end() +} + +/** + * Creates and enqueues the LlmChatCompletionSummary and + * LlmChatCompletionMessage events and adds an error to transaction if it + * exists. It will also assign the request, conversation and messages ids by + * the response id. + * + * @param {object} params function params + * @param {object} params.agent instance of agent + * @param {object} params.segment active segment + * @param {BedrockCommand} params.bedrockCommand parsed input + * @param {Error|null} params.err error from request if exists + * @param params.bedrockResponse + */ +function recordChatCompletionMessages({ agent, segment, bedrockCommand, bedrockResponse, err }) { + const summary = new LlmChatCompletionSummary({ + agent, + bedrockResponse, + bedrockCommand, + segment, + isError: err !== null + }) + + const msg = new LlmChatCompletionMessage({ + agent, + segment, + bedrockCommand, + bedrockResponse, + index: 0, + completionId: summary.id + }) + recordEvent({ agent, type: 'LlmChatCompletionMessage', msg }) + + bedrockResponse.completions.forEach((content, index) => { + const chatCompletionMessage = new LlmChatCompletionMessage({ + agent, + segment, + bedrockCommand, + bedrockResponse, + isResponse: true, + index: index + 1, + content, + completionId: summary.id + }) + recordEvent({ agent, type: 'LlmChatCompletionMessage', msg: chatCompletionMessage }) + }) + + recordEvent({ agent, type: 'LlmChatCompletionSummary', msg: summary }) + + if (err) { + const llmError = new LlmError({ bedrockResponse, err, summary }) + agent.errors.add(segment.transaction, err, llmError) + } +} + +/** + * Creates and enqueues the LlmEmbedding event and adds an error to transaction + * if it exists. + * + * @param {object} params function params + * @param {object} params.agent instance of agent + * @param {object} params.segment active segment + * @param {BedrockCommand} params.bedrockCommand parsed input + * @param {Error|null} params.err error from request if exists + * @param params.bedrockResponse + */ +function recordEmbeddingMessage({ agent, segment, bedrockCommand, bedrockResponse, err }) { + const embedding = new LlmEmbedding({ + agent, + segment, + bedrockCommand, + bedrockResponse, + isError: err !== null + }) + + recordEvent({ agent, type: 'LlmEmbedding', msg: embedding }) + if (err) { + const llmError = new LlmError({ bedrockResponse, err, embedding }) + agent.errors.add(segment.transaction, err, llmError) + } +} + +/** + * Creates and instance of BedrockResponse + * + * @param {object} params function params + * @param {BedrockCommand} params.bedrockCommand parsed input + * @param {object} params.response response from bedrock + * @param {Error|null} params.err error from request if exists + * + * @returns {BedrockResponse} parsed response from bedrock + */ +function createBedrockResponse({ bedrockCommand, response, err }) { + let bedrockResponse + + if (err) { + bedrockResponse = new BedrockResponse({ bedrockCommand, response: err, isError: err !== null }) + } else { + bedrockResponse = new BedrockResponse({ bedrockCommand, response }) + } + return bedrockResponse +} + +/** + * Registers the specification for instrumentation bedrock calls + * + * @param {object} params { config, commandName } aws config and command name + * @param {Shim} _shim instance of shim + * @param params.commandName + * @param shim + * @param {function} _original original middleware function + * @param {string} _name function name + * @param {array} args argument passed to middleware + * @returns {object} specification object that records middleware as promise + * with an after hook to create LLM events + */ +function getBedrockSpec({ commandName }, shim, _original, _name, args) { + const { agent } = shim + const { input } = args[0] + const bedrockCommand = new BedrockCommand(input) + const { modelType } = bedrockCommand + + return new RecorderSpec({ + promise: true, + name: `Llm/${modelType}/Bedrock/${commandName}`, + // eslint-disable-next-line max-params + after: (shim, _fn, _fnName, err, response, segment) => { + const passThroughParams = { + shim, + err, + response, + segment, + bedrockCommand, + modelType + } + + if (err && !response) { + handleResponse(passThroughParams) + } else if (response.output.body instanceof Uint8Array) { + // non-streamed response + handleResponse(passThroughParams) + } else if (isStreamingEnabled({ commandName, config: agent.config })) { + // stream response + const handler = new StreamHandler({ + stream: response.output.body, + onComplete: handleResponse, + passThroughParams + }) + response.output.body = handler.generator(handleResponse) + } else if (!isStreamingEnabled({ commandName, config: agent.config })) { + shim.logger.warn( + 'ai_monitoring.streaming.enabled is set to `false`, stream will not be instrumented.' + ) + agent.metrics.getOrCreateMetric(AI.STREAMING_DISABLED).incrementCallCount() + addLlmMeta({ agent, segment }) + } + } + }) +} + +function handleResponse({ shim, err, response, segment, bedrockCommand, modelType }) { + const { agent } = shim + const bedrockResponse = createBedrockResponse({ bedrockCommand, response, err }) + + addLlmMeta({ agent, segment }) + if (modelType === 'completion') { + recordChatCompletionMessages({ + agent, + segment, + bedrockCommand, + bedrockResponse, + err + }) + } else if (modelType === 'embedding') { + recordEmbeddingMessage({ + agent, + segment, + bedrockCommand, + bedrockResponse, + err + }) + } +} + +/** + * Middleware function that either instruments when InvokeModelCommand or + * InvokeModelWithResponseStreamCommand or returns existing middleware chain + * + * @param {Shim} shim instance of shim + * @param {object} config AWS configuration object + * @param {function} next the next middleware function in stack + * @param {object} context AWS client context info + */ +function bedrockMiddleware(shim, config, next, context) { + const { commandName } = context + if ( + commandName === 'InvokeModelCommand' || + commandName === 'InvokeModelWithResponseStreamCommand' + ) { + return shim.record(next, getBedrockSpec.bind(null, { commandName })) + } + + shim.logger.debug(`Not instrumenting command ${commandName}`) + return next +} + +module.exports.bedrockMiddlewareConfig = { + middleware: bedrockMiddleware, + init(shim) { + const { agent, logger } = shim + if (shouldSkipInstrumentation(agent.config)) { + logger.debug( + '@aws-sdk/bedrock-runtime-client instrumentation is disabled. To enable set `config.ai_monitoring.enabled` to true' + ) + return false + } + + TRACKING_METRIC = `${AI.BEDROCK.TRACKING_PREFIX}/${shim.pkgVersion}` + return true + }, + type: InstrumentationDescriptor.TYPE_GENERIC, + config: { + name: 'NewRelicBedrockMiddleware', + step: 'deserialize', + override: true + } +} diff --git a/lib/instrumentation/aws-sdk/v3/common.js b/lib/instrumentation/aws-sdk/v3/common.js new file mode 100644 index 0000000000..164a4d4fb5 --- /dev/null +++ b/lib/instrumentation/aws-sdk/v3/common.js @@ -0,0 +1,101 @@ +/* + * Copyright 2023 New Relic Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +'use strict' + +const UNKNOWN = 'Unknown' +const InstrumentationDescriptor = require('../../../instrumentation-descriptor') + +/** + * Wraps the build middleware step to add the disable DT + * header to all outgoing requests + * + * @param {Shim} shim + * @param config + * @param {function} next next function in middleware chain + * @returns {function} + * + */ +function headerMiddleware(shim, config, next) { + return async function wrappedHeaderMw(args) { + // this is an indicator in the agent http-outbound instrumentation + // to disable DT from AWS requests as they are not necessary + args.request.headers['x-new-relic-disable-dt'] = 'true' + return await next(args) + } +} + +/** + * Wraps the deserialize middleware step to add the + * appropriate segment attributes for the AWS command + * + * @param {Shim} shim + * @param {Object} config AWS command configuration + * @param {function} next next function in middleware chain + * @param {Object} contxt AWS command context + * cons + * @param context + * @returns {function} + */ +function attrMiddleware(shim, config, next, context) { + return async function wrappedMiddleware(args) { + let region + try { + region = await config.region() + } catch (err) { + shim.logger.debug(err, 'Failed to get the AWS region') + } finally { + const result = await next(args) + addAwsAttributes({ result, config, region, shim, context }) + return result + } + } +} + +/** + * Adds the necessary aws.* attributes to either the External or first + * class operation segment + * + * @param {Object} params + * @param {Object} params.result result from middleware + * @param {Object} params.config AWS config + * @param {string} params.region AWS region + * @param {Shim} params.shim + * @param {Object} params.context smithy client context + */ +function addAwsAttributes({ result, config, region, shim, context }) { + try { + const { response } = result + const segment = shim.getSegment(response.body.req) + segment.addAttribute('aws.operation', context.commandName || UNKNOWN) + segment.addAttribute('aws.requestId', response.headers['x-amzn-requestid'] || UNKNOWN) + segment.addAttribute('aws.service', config.serviceId || UNKNOWN) + segment.addAttribute('aws.region', region || UNKNOWN) + } catch (err) { + shim.logger.debug(err, 'Failed to add AWS attributes to segment') + } +} + +module.exports.middlewareConfig = [ + { + middleware: headerMiddleware, + type: InstrumentationDescriptor.TYPE_GENERIC, + config: { + name: 'NewRelicHeader', + step: 'finalizeRequest', + priority: 'low', + override: true + } + }, + { + middleware: attrMiddleware, + type: InstrumentationDescriptor.TYPE_GENERIC, + config: { + name: 'NewRelicDeserialize', + step: 'deserialize', + override: true + } + } +] diff --git a/lib/instrumentation/aws-sdk/v3/dynamodb.js b/lib/instrumentation/aws-sdk/v3/dynamodb.js new file mode 100644 index 0000000000..0d51ed0675 --- /dev/null +++ b/lib/instrumentation/aws-sdk/v3/dynamodb.js @@ -0,0 +1,92 @@ +/* + * Copyright 2021 New Relic Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +'use strict' +const { setDynamoParameters } = require('../util') +const { OperationSpec } = require('../../../shim/specs') +const InstrumentationDescriptor = require('../../../instrumentation-descriptor') + +/** + * Returns the spec for Dynamo commands + * + * @param {Shim} shim + * @param {original} original Original middleware function + * @param {String} name Name of the calling function + * @param {Array} args Arguments for the middleware function + * @returns {Object} + */ +function getDynamoSpec(shim, original, name, args) { + const [{ input }] = args + return new OperationSpec({ + name: this.commandName, + parameters: setDynamoParameters(this.endpoint, input), + callback: shim.LAST, + opaque: true, + promise: true + }) +} + +/** + * AWS sdk v 3.194?.0 released a breaking change. + * See: https://github.com/aws/aws-sdk-js-v3/issues/4122 + * What this means is config.endpoint is not always a function + * unless you provide an endpoint override to your library constructor + * This function will derive the endpoint in that scenario by grabbing the region + * and building the URL + * @param config + */ +async function getEndpoint(config) { + if (typeof config.endpoint === 'function') { + return await config.endpoint() + } + + const region = await config.region() + return new URL(`https://dynamodb.${region}.amazonaws.com`) +} + +/** + * Middleware hook that records the middleware chain + * when command is in a list of monitored commands. + * + * @param {Shim} shim + * @param {Object} config AWS SDK client configuration + * @param {function} next middleware function + * @param {Object} context Context for the running command + * @returns {function} + */ +function dynamoMiddleware(shim, config, next, context) { + const { commandName } = context + return async function wrappedMiddleware(args) { + let endpoint = null + try { + endpoint = await getEndpoint(config) + } catch (err) { + shim.logger.debug(err, 'Failed to get the endpoint.') + } + + const getSpec = getDynamoSpec.bind({ endpoint, commandName }) + const wrappedNext = shim.recordOperation(next, getSpec) + return wrappedNext(args) + } +} + +const dynamoMiddlewareConfig = { + middleware: dynamoMiddleware, + init(shim) { + shim.setDatastore(shim.DYNAMODB) + return true + }, + type: InstrumentationDescriptor.TYPE_DATASTORE, + config: { + name: 'NewRelicDynamoMiddleware', + step: 'initialize', + priority: 'high', + override: true + } +} + +module.exports = { + dynamoMiddlewareConfig +} diff --git a/lib/instrumentation/aws-sdk/v3/smithy-client.js b/lib/instrumentation/aws-sdk/v3/smithy-client.js new file mode 100644 index 0000000000..62a2ff175c --- /dev/null +++ b/lib/instrumentation/aws-sdk/v3/smithy-client.js @@ -0,0 +1,65 @@ +/* + * Copyright 2021 New Relic Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +'use strict' + +const { middlewareConfig } = require('./common') +const { snsMiddlewareConfig } = require('./sns') +const { sqsMiddlewareConfig } = require('./sqs') +const { dynamoMiddlewareConfig } = require('./dynamodb') +const { bedrockMiddlewareConfig } = require('./bedrock') +const MIDDLEWARE = Symbol('nrMiddleware') + +const middlewareByClient = { + Client: middlewareConfig, + BedrockRuntime: [...middlewareConfig, bedrockMiddlewareConfig], + SNS: [...middlewareConfig, snsMiddlewareConfig], + SQS: [...middlewareConfig, sqsMiddlewareConfig], + DynamoDB: [...middlewareConfig, dynamoMiddlewareConfig], + DynamoDBDocument: [...middlewareConfig, dynamoMiddlewareConfig] +} + +module.exports = function instrumentSmithyClient(shim, smithyClientExport) { + if (!shim.isFunction(smithyClientExport?.Client?.prototype?.send)) { + shim.logger.debug('Could not find Smithy Client, not instrumenting.') + } else { + shim.wrap(smithyClientExport.Client.prototype, 'send', wrapSend) + } +} + +function wrapSend(shim, send) { + return function wrappedSend() { + // most clients we want to instrument aside from smithy-client + // extend themselves to provide different names(i.e. - SNS and SNSClient) + // we want to handle these the same by registering the sns middleware + const client = this.constructor.name.replace(/Client$/, '') + shim.logger.trace('Sending with client %s', client) + const config = this.config + const middlewares = middlewareByClient[client] || middlewareByClient.Client + + // only attach the middleware to the stack instance once + // We just assign a symbol indicating this application + // This was refactored when we went from instrumentation when module was resolved + // to compiled which did not allow us to instrument the constructor as it lacked + // at getter. + if (!this[MIDDLEWARE]) { + this[MIDDLEWARE] = true + for (const mw of middlewares) { + shim.logger.trace('Registering middleware %s for %s', mw.config.name, client) + const localShim = shim.makeSpecializedShim(mw.type, client) + // copy the shim id from parent so if you check if something is wrapped + // it will be across all instrumentation + localShim.assignId('aws-sdk') + const shouldRegisterMiddleware = (mw.init && mw.init(localShim)) || !mw.init + if (shouldRegisterMiddleware) { + const middleware = mw.middleware.bind(null, localShim, config) + this.middlewareStack.add(middleware, mw.config) + } + } + } + + return send.apply(this, arguments) + } +} diff --git a/lib/instrumentation/aws-sdk/v3/sns.js b/lib/instrumentation/aws-sdk/v3/sns.js new file mode 100644 index 0000000000..a60aed0049 --- /dev/null +++ b/lib/instrumentation/aws-sdk/v3/sns.js @@ -0,0 +1,74 @@ +/* + * Copyright 2021 New Relic Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +'use strict' +const { MessageSpec } = require('../../../shim/specs') +const InstrumentationDescriptor = require('../../../instrumentation-descriptor') + +/** + * Middleware hook that records the middleware chain + * when command is `PublishCommand` + * + * @param {Shim} shim + * @param config + * @param {function} next middleware function + * @param {Object} context + * @returns {function} + */ +function snsMiddleware(shim, config, next, context) { + if (context.commandName === 'PublishCommand') { + return shim.recordProduce(next, getSnsSpec) + } + shim.logger.debug(`Not instrumenting command ${context.commandName}.`) + + return next +} + +/** + * Returns the spec for PublishCommand + * + * @param {Shim} shim + * @param {original} original original middleware function + * @param name + * @param {Array} args to the middleware function + * @returns {Object} + */ +function getSnsSpec(shim, original, name, args) { + const [command] = args + return new MessageSpec({ + promise: true, + callback: shim.LAST, + destinationName: getDestinationName(command.input), + destinationType: shim.TOPIC, + opaque: true + }) +} + +/** + * Helper to set the appropriate destinationName based on + * the command input + * + * @param root0 + * @param root0.TopicArn + * @param root0.TargetArn + */ +function getDestinationName({ TopicArn, TargetArn }) { + return TopicArn || TargetArn || 'PhoneNumber' // We don't want the value of PhoneNumber +} + +module.exports.snsMiddlewareConfig = { + middleware: snsMiddleware, + init(shim) { + shim.setLibrary(shim.SNS) + return true + }, + type: InstrumentationDescriptor.TYPE_MESSAGE, + config: { + name: 'NewRelicSnsMiddleware', + step: 'initialize', + priority: 'high', + override: true + } +} diff --git a/lib/instrumentation/aws-sdk/v3/sqs.js b/lib/instrumentation/aws-sdk/v3/sqs.js new file mode 100644 index 0000000000..cd1c996103 --- /dev/null +++ b/lib/instrumentation/aws-sdk/v3/sqs.js @@ -0,0 +1,70 @@ +/* + * Copyright 2021 New Relic Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +'use strict' + +const { grabLastUrlSegment } = require('../util') + +const SEND_COMMANDS = ['SendMessageCommand', 'SendMessageBatchCommand'] + +const RECEIVE_COMMANDS = ['ReceiveMessageCommand'] +const { MessageSpec } = require('../../../shim/specs') +const InstrumentationDescriptor = require('../../../instrumentation-descriptor') + +/** + * Middleware hook that records the middleware chain + * when command is `PublishCommand` + * + * @param {Shim} shim + * @param config + * @param {function} next middleware function + * @param {Object} context + * @returns {function} + */ +function sqsMiddleware(shim, config, next, context) { + if (SEND_COMMANDS.includes(context.commandName)) { + return shim.recordProduce(next, getSqsSpec) + } else if (RECEIVE_COMMANDS.includes(context.commandName)) { + return shim.recordConsume(next, getSqsSpec) + } + shim.logger.debug(`Not instrumenting command ${context.commandName}.`) + + return next +} + +/** + * Returns the spec for PublishCommand + * + * @param {Shim} shim + * @param {original} original original middleware function + * @param name + * @param {Array} args to the middleware function + * @returns {Object} + */ +function getSqsSpec(shim, original, name, args) { + const [command] = args + const { QueueUrl } = command.input + return new MessageSpec({ + callback: shim.LAST, + destinationName: grabLastUrlSegment(QueueUrl), + destinationType: shim.QUEUE, + opaque: true + }) +} + +module.exports.sqsMiddlewareConfig = { + middleware: sqsMiddleware, + init(shim) { + shim.setLibrary(shim.SQS) + return true + }, + type: InstrumentationDescriptor.TYPE_MESSAGE, + config: { + name: 'NewRelicSqsMiddleware', + step: 'initialize', + priority: 'high', + override: true + } +} diff --git a/lib/instrumentations.js b/lib/instrumentations.js index aa4aab4703..127a542e02 100644 --- a/lib/instrumentations.js +++ b/lib/instrumentations.js @@ -19,7 +19,7 @@ module.exports = function instrumentations() { '@prisma/client': { type: InstrumentationDescriptor.TYPE_DATASTORE }, '@redis/client': { type: InstrumentationDescriptor.TYPE_DATASTORE }, 'amqplib': { module: './instrumentation/amqplib' }, - 'aws-sdk': { module: '@newrelic/aws-sdk' }, + 'aws-sdk': { module: './instrumentation/aws-sdk' }, 'bluebird': { type: InstrumentationDescriptor.TYPE_PROMISE }, 'bunyan': { type: InstrumentationDescriptor.TYPE_GENERIC }, 'cassandra-driver': { type: InstrumentationDescriptor.TYPE_DATASTORE }, diff --git a/lib/llm-events/aws-bedrock/bedrock-command.js b/lib/llm-events/aws-bedrock/bedrock-command.js new file mode 100644 index 0000000000..e466d3b7e1 --- /dev/null +++ b/lib/llm-events/aws-bedrock/bedrock-command.js @@ -0,0 +1,137 @@ +/* + * Copyright 2024 New Relic Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +'use strict' + +/** + * Parses an AWS invoke command instance into a re-usable entity. + */ +class BedrockCommand { + #input + #body + #modelId + + /** + * @param {object} input The `input` property from an InvokeModelCommand or + * InvokeModelWithResponseStreamCommand instance that is used for the + * conversation. + */ + constructor(input) { + this.#input = input + this.#body = JSON.parse(this.#input.body) + this.#modelId = this.#input.modelId?.toLowerCase() ?? '' + } + + /** + * The maximum number of tokens allowed as defined by the user. + * + * @returns {number|undefined} + */ + get maxTokens() { + let result + if (this.isAi21() === true) { + result = this.#body.maxTokens + } else if (this.isClaude() === true) { + result = this.#body.max_tokens_to_sample + } else if (this.isCohere() === true) { + result = this.#body.max_tokens + } else if (this.isLlama2() === true) { + result = this.#body.max_gen_length + } else if (this.isTitan() === true) { + result = this.#body.textGenerationConfig?.maxTokenCount + } + return result + } + + /** + * The model identifier for the command. + * + * @see https://docs.aws.amazon.com/bedrock/latest/userguide/model-ids-arns.html + * + * @returns {string} + */ + get modelId() { + return this.#modelId + } + + /** + * @returns {string} One of `embedding` or `completion`. + */ + get modelType() { + // At the moment, this is a simple check. If Amazon ever introduces a + // complex identifier, we can implement a more complicated check. + return this.#modelId.toLowerCase().includes('embed') ? 'embedding' : 'completion' + } + + /** + * The question posed to the LLM. + * + * @returns {string|string[]|undefined} + */ + get prompt() { + let result + if (this.isTitan() === true || this.isTitanEmbed() === true) { + result = this.#body.inputText + } else if (this.isCohereEmbed() === true) { + result = this.#body.texts.join(' ') + } else if ( + this.isClaude() === true || + this.isAi21() === true || + this.isCohere() === true || + this.isLlama2() === true + ) { + result = this.#body.prompt + } + return result + } + + /** + * @returns {number|undefined} + */ + get temperature() { + let result + if (this.isTitan() === true) { + result = this.#body.textGenerationConfig?.temperature + } else if ( + this.isClaude() === true || + this.isAi21() === true || + this.isCohere() === true || + this.isLlama2() === true + ) { + result = this.#body.temperature + } + return result + } + + isAi21() { + return this.#modelId.startsWith('ai21.') + } + + isClaude() { + return this.#modelId.startsWith('anthropic.claude') + } + + isCohere() { + return this.#modelId.startsWith('cohere.') && this.isCohereEmbed() === false + } + + isCohereEmbed() { + return this.#modelId.startsWith('cohere.embed') + } + + isLlama2() { + return this.#modelId.startsWith('meta.llama2') + } + + isTitan() { + return this.#modelId.startsWith('amazon.titan') && this.isTitanEmbed() === false + } + + isTitanEmbed() { + return this.#modelId.startsWith('amazon.titan-embed') + } +} + +module.exports = BedrockCommand diff --git a/lib/llm-events/aws-bedrock/bedrock-response.js b/lib/llm-events/aws-bedrock/bedrock-response.js new file mode 100644 index 0000000000..887945186c --- /dev/null +++ b/lib/llm-events/aws-bedrock/bedrock-response.js @@ -0,0 +1,152 @@ +/* + * Copyright 2024 New Relic Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +'use strict' + +/** + * @typedef {object} AwsBedrockMiddlewareResponse + * @property {object} response Has a `body` property that is an IncomingMessage, + * a `headers` property that are the response headers, a `reason` property that + * indicates the status code reason, and a `statusCode` property. + * @property {object} output Has a `$metadata` property that includes the + * `requestId`, and a `body` property that is a Uint8Array representation + * of the response payload. + */ + +/** + * Represents a response from the Bedrock API. Given that the API response + * has as many different shapes as the number of models it supports, and the + * fact that responses require byte array processing, this object provides + * an abstraction that normalizes responses into a known interface and + * simplifies accessing desired fields. + */ +class BedrockResponse { + #innerResponse + #innerOutput + #parsedBody + #command + #completions = [] + #id + + /** + * @param {object} params + * @param {AwsBedrockMiddlewareResponse} params.response + * @param {BedrockCommand} params.bedrockCommand + */ + constructor({ response, bedrockCommand, isError = false }) { + this.#innerResponse = isError ? response.$response : response.response + this.#command = bedrockCommand + this.isError = isError + + if (this.isError) { + return + } + + this.#innerOutput = response.output + + const json = new TextDecoder().decode(this.#innerOutput.body) + this.#parsedBody = JSON.parse(json) + + const cmd = this.#command + const body = this.#parsedBody + if (cmd.isAi21() === true) { + this.#completions = body.completions?.map((c) => c.data.text) ?? [] + this.#id = body.id + } else if (cmd.isClaude() === true) { + // TODO: can we make this thing give more than one completion? + body.completion && this.#completions.push(body.completion) + } else if (cmd.isCohere() === true) { + this.#completions = body.generations?.map((g) => g.text) ?? [] + this.#id = body.id + } else if (cmd.isLlama2() === true) { + body.generation && this.#completions.push(body.generation) + } else if (cmd.isTitan() === true) { + this.#completions = body.results?.map((r) => r.outputText) ?? [] + } + } + + /** + * The prompt responses returned by the model. + * + * @returns {string[]|*[]} Should be an array of string responses to the + * prompt. + */ + get completions() { + return this.#completions + } + + /** + * The reason the model has given for finishing the response. + * + * @returns {string|*} + */ + get finishReason() { + let result + + if (this.isError) { + return result + } + + const cmd = this.#command + if (cmd.isAi21() === true) { + result = this.#parsedBody.completions?.[0]?.finishReason.reason + } else if (cmd.isClaude() === true) { + result = this.#parsedBody.stop_reason + } else if (cmd.isCohere() === true) { + result = this.#parsedBody.generations?.find((r) => r.finish_reason !== null)?.finish_reason + } else if (cmd.isLlama2() === true) { + result = this.#parsedBody.stop_reason + } else if (cmd.isTitan() === true) { + result = this.#parsedBody.results?.find((r) => r.completionReason !== null)?.completionReason + } + return result + } + + /** + * HTTP headers provided in the API response. + * + * @returns {object} Typical key-value set of HTTP headers. + */ + get headers() { + return this.#innerResponse.headers + } + + /** + * Retrieve the response identifier provided by some model responses. + * + * @returns {string|undefined} + */ + get id() { + return this.#id + } + + /** + * UUID assigned to the initial request as returned by the API. + * + * @returns {string} + */ + get requestId() { + return this.headers?.['x-amzn-requestid'] + } + + /** + * The HTTP status code of the response. + * + * @returns {number} + */ + get statusCode() { + return this.#innerResponse.statusCode + } + + #tokenCount(headerName) { + const headerVal = this.headers?.[headerName] + if (headerVal != null) { + return parseInt(headerVal, 10) + } + return undefined + } +} + +module.exports = BedrockResponse diff --git a/lib/llm-events/aws-bedrock/chat-completion-message.js b/lib/llm-events/aws-bedrock/chat-completion-message.js new file mode 100644 index 0000000000..6f0c564794 --- /dev/null +++ b/lib/llm-events/aws-bedrock/chat-completion-message.js @@ -0,0 +1,77 @@ +/* + * Copyright 2023 New Relic Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +'use strict' + +const LlmEvent = require('./event') + +/** + * @typedef {object} LlmChatCompletionParams + * @augments LlmEventParams + * @property {string} completionId An identifier for the completion message. + * @property {string} content The human readable response from the LLM. + * @property {number} [index=0] The order of the message in the conversation. + * @property {boolean} [isResponse=false] Indicates if the message represents + * a response from the LLM. + * @property {object} message The message sent to the LLM. + * @property {OutgoingMessage} request The outgoing HTTP request used in the + * LLM conversation. + */ +/** + * @type {LlmChatCompletionParams} + */ +const defaultParams = { + completionId: '', + content: '', + index: 0, + isResponse: false, + message: {}, + request: {} +} + +/** + * Represents an LLM chat completion. + */ +class LlmChatCompletionMessage extends LlmEvent { + constructor(params = defaultParams) { + params = Object.assign({}, defaultParams, params) + super(params) + + const { agent, content, isResponse, index, completionId } = params + const recordContent = agent.config?.ai_monitoring?.record_content?.enabled + const tokenCB = agent?.llm?.tokenCountCallback + + this.is_response = isResponse + this.completion_id = completionId + this.sequence = index + this.content = recordContent === true ? content : undefined + this.role = '' + + this.#setId(index) + if (this.is_response === true) { + this.role = 'assistant' + if (typeof tokenCB === 'function') { + this.token_count = tokenCB(this.bedrockCommand.modelId, content) + } + } else { + this.role = 'user' + this.content = recordContent === true ? this.bedrockCommand.prompt : undefined + if (typeof tokenCB === 'function') { + this.token_count = tokenCB(this.bedrockCommand.modelId, this.bedrockCommand.prompt) + } + } + } + + #setId(index) { + const cmd = this.bedrockCommand + if (cmd.isTitan() === true || cmd.isClaude() === true) { + this.id = `${this.id}-${index}` + } else if (cmd.isAi21() === true || cmd.isCohere() === true) { + this.id = `${this.bedrockResponse.id || this.id}-${index}` + } + } +} + +module.exports = LlmChatCompletionMessage diff --git a/lib/llm-events/aws-bedrock/chat-completion-summary.js b/lib/llm-events/aws-bedrock/chat-completion-summary.js new file mode 100644 index 0000000000..20c4edd6c2 --- /dev/null +++ b/lib/llm-events/aws-bedrock/chat-completion-summary.js @@ -0,0 +1,42 @@ +/* + * Copyright 2024 New Relic Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +'use strict' + +const LlmEvent = require('./event') + +/** + * @typedef {object} LlmChatCompletionSummaryParams + * @augments LlmEventParams + */ +/** + * @type {LlmChatCompletionSummaryParams} + */ +const defaultParams = {} + +/** + * Represents an LLM chat completion summary. + */ +class LlmChatCompletionSummary extends LlmEvent { + constructor(params = defaultParams) { + super(params) + + const { segment, isError } = params + this.error = isError + this.duration = segment.getDurationInMillis() + this['request.max_tokens'] = this.bedrockCommand.maxTokens + + const nm = 'response.number_of_messages' + const cfr = 'response.choices.finish_reason' + const rt = 'request.temperature' + + const cmd = this.bedrockCommand + this[cfr] = this.bedrockResponse.finishReason + this[rt] = cmd.temperature + this[nm] = 1 + this.bedrockResponse.completions.length + } +} + +module.exports = LlmChatCompletionSummary diff --git a/lib/llm-events/aws-bedrock/embedding.js b/lib/llm-events/aws-bedrock/embedding.js new file mode 100644 index 0000000000..3cfa9e3b88 --- /dev/null +++ b/lib/llm-events/aws-bedrock/embedding.js @@ -0,0 +1,36 @@ +/* + * Copyright 2024 New Relic Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +'use strict' + +const LlmEvent = require('./event') + +/** + * @typedef {object} LlmEmbeddingParams + * @augments LlmEventParams + */ +/** + * @type {LlmEmbeddingParams} + */ +const defaultParams = {} + +class LlmEmbedding extends LlmEvent { + constructor(params = defaultParams) { + super(params) + const { agent } = params + const tokenCb = agent?.llm?.tokenCountCallback + + this.input = agent.config?.ai_monitoring?.record_content?.enabled + ? this.bedrockCommand.prompt + : undefined + this.error = params.isError + this.duration = params.segment.getDurationInMillis() + if (typeof tokenCb === 'function') { + this.token_count = tokenCb(this.bedrockCommand.modelId, this.bedrockCommand.prompt) + } + } +} + +module.exports = LlmEmbedding diff --git a/lib/llm-events/aws-bedrock/error.js b/lib/llm-events/aws-bedrock/error.js new file mode 100644 index 0000000000..991913f33e --- /dev/null +++ b/lib/llm-events/aws-bedrock/error.js @@ -0,0 +1,29 @@ +/* + * Copyright 2024 New Relic Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +'use strict' + +/** + * Represents an error object, to be tracked via `agent.errors`, that is the + * result of some error returned from AWS Bedrock. + */ +module.exports = class LlmError { + /** + * @param {object} params Constructor parameters + * @param {BedrockResponse} [params.bedrockResponse] Instance of an incoming message. + * @param {object} [params.err] AWS error object + * @param {LlmChatCompletionSummary} [params.summary] Details about the + * conversation if it was a chat completion conversation. + * @param {LlmEmbedding} [params.embedding] Details about the conversation + * if it was an embedding conversation. + */ + constructor({ bedrockResponse = {}, err = {}, summary = {}, embedding = {} } = {}) { + this['http.statusCode'] = bedrockResponse.statusCode + this['error.message'] = err.message + this['error.code'] = err.name + this.completion_id = summary.id + this.embedding_id = embedding.id + } +} diff --git a/lib/llm-events/aws-bedrock/event.js b/lib/llm-events/aws-bedrock/event.js new file mode 100644 index 0000000000..d5434b6546 --- /dev/null +++ b/lib/llm-events/aws-bedrock/event.js @@ -0,0 +1,97 @@ +/* + * Copyright 2023 New Relic Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +'use strict' + +const { randomUUID } = require('crypto') +const { DESTINATIONS } = require('../../config/attribute-filter') + +/** + * @typedef {object} LlmEventParams + * @property {object} agent A New Relic agent instance. + * @property {BedrockCommand} bedrockCommand A parsed invoke command. + * @property {BedrockResponse} bedrockResponse A parsed response from the API. + * @property {object} segment The current segment for the trace. + */ +/** + * @type {LlmEventParams} + */ +const defaultParams = { + agent: {}, + bedrockCommand: {}, + bedrockResponse: {}, + segment: { + transaction: {} + } +} + +/** + * Baseline object representing a LLM event. + */ +class LlmEvent { + /** + * All parameters that were passed in to the constructor after they have + * been merged with the constructor's defaults. + */ + constructionParams + + bedrockCommand + bedrockResponse + + /** + * @param {LlmEventParams} params Construction parameters. + */ + constructor(params = defaultParams) { + params = Object.assign({}, defaultParams, params) + this.constructionParams = params + + const { agent, bedrockCommand, bedrockResponse, segment } = params + this.bedrockCommand = bedrockCommand + this.bedrockResponse = bedrockResponse + + this.id = randomUUID() + this.vendor = 'bedrock' + this.ingest_source = 'Node' + this.appName = agent.config.applications()[0] + this.span_id = segment.id + this.trace_id = segment.transaction.traceId + this.request_id = this.bedrockResponse.requestId + this.metadata = agent + + this['response.model'] = this.bedrockCommand.modelId + this['request.model'] = this.bedrockCommand.modelId + this['request.max_tokens'] = null + } + + /** + * Pull user set `llm.*` attributes from the current transaction and + * add them to the event. + * + * @param {object} agent The New Relic agent that provides access to the + * transaction. + */ + set metadata(agent) { + const tx = agent.tracer.getTransaction() + const attrs = tx?.trace?.custom.get(DESTINATIONS.TRANS_SCOPE) || {} + for (const [k, v] of Object.entries(attrs)) { + if (k.startsWith('llm.') === false) { + continue + } + this[k] = v + } + } + + /** + * Removes the complex objects from the event + * This will be called right before the event is enqueued to the custom event aggregator + */ + serialize() { + delete this.bedrockCommand + delete this.bedrockResponse + delete this.constructionParams + } +} + +module.exports = LlmEvent diff --git a/lib/llm-events/aws-bedrock/index.js b/lib/llm-events/aws-bedrock/index.js new file mode 100644 index 0000000000..5dd01856e1 --- /dev/null +++ b/lib/llm-events/aws-bedrock/index.js @@ -0,0 +1,17 @@ +/* + * Copyright 2024 New Relic Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +'use strict' + +module.exports = { + BedrockCommand: require('./bedrock-command'), + BedrockResponse: require('./bedrock-response'), + LlmChatCompletionMessage: require('./chat-completion-message'), + LlmChatCompletionSummary: require('./chat-completion-summary'), + LlmEmbedding: require('./embedding'), + LlmEvent: require('./event'), + LlmError: require('./error'), + StreamHandler: require('./stream-handler') +} diff --git a/lib/llm-events/aws-bedrock/stream-handler.js b/lib/llm-events/aws-bedrock/stream-handler.js new file mode 100644 index 0000000000..9f4f092d9e --- /dev/null +++ b/lib/llm-events/aws-bedrock/stream-handler.js @@ -0,0 +1,281 @@ +/* + * Copyright 2024 New Relic Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +'use strict' + +/** + * A stream handler processes a streamed response from the Bedrock API by + * intercepting each stream event, passing that event unmodified up to the + * consuming client, and then collecting the information into an "API response" + * object that satisfies the requirements of {@link BedrockResponse}. Once the + * stream has reached its end, the handler applies some finalizations to the + * compiled response object, updates the pass through parameters with the new + * object, and then invokes the final response handler passed in through + * `onComplete`. + */ +class StreamHandler { + // We have to make most of the properties of this object public so that + // the at-construction-time attached generator function can access them + // through the `this` reference. See https://jrfom.com/posts/2023/10/31/js-classes/ + // for details on why this is necessary. + + /** + * The parameters to pass through to the `onComplete` function once the + * stream has been processed. The `response` property on this object will + * be overwritten with the response object that has been compiled by the + * stream handler. + */ + passThroughParams + + /** + * The original async iterable returned from the AWS SDK. + */ + stream + + /** + * The New Relic agent's internal trace segment. The `.touch` method will be + * used to mark the end time of the stream processing. + */ + segment + + /** + * Represents an API response object as {@link BedrockResponse} expects. + * It will be updated by the stream handler with information received + * during processing of the stream. Upon stream completion, this object + * will replace the `response` property of `passThroughParams`. + * + * @type {object} + */ + response = { + response: { + headers: {}, + statusCode: 200 + }, + output: { + body: {} + } + } + + /** + * The key on the event object that indicates if it is the last event in the + * stream, and why the stream has ended. If the key is nested, this value + * should be a dot (.) separated string of keys and indices. For example, + * if the key is at `event.results[0].reason`, then the value should be + * `results.0.reason`. + * + * @type {string} + */ + stopReasonKey = '' + + /** + * Used to decode Uint8Array bodies. There should not be any need to update + * this property. + * + * @type {TextDecoder} + */ + decoder = new TextDecoder() + + /** + * The function that will be invoked once the stream processing has finished. + * It will receive `this.passThroughParams` as the only parameter. + */ + onComplete + + constructor({ stream, passThroughParams, onComplete }) { + this.passThroughParams = passThroughParams + this.stream = stream + this.onComplete = onComplete + this.segment = passThroughParams.segment + + const { bedrockCommand } = passThroughParams + + // Each model returns a unique-ish response stream. To handle this, we + // attach a generator specific to the model that will process the stream + // events and collect them into `this.response` such that `this.response` + // ultimately has the shape of a non-streamed response that is expected + // by BedrockResponse. + // + // Important: each of the handler function uses a `try/finally` block + // to process the original stream. Of particular note is that there is NOT + // a `catch` block. As of 2024-01-17, we are not able to determine a viable + // means of inducing an error in the stream such that a `catch` block in + // our wrapping handler would be hit. + if (bedrockCommand.isClaude() === true) { + this.stopReasonKey = 'stop_reason' + this.generator = handleClaude + } else if (bedrockCommand.isCohere() === true) { + this.stopReasonKey = 'generations.0.finish_reason' + this.generator = handleCohere + } else if (bedrockCommand.isCohereEmbed() === true) { + this.stopReasonKey = 'nr_none' + this.generator = handleCohereEmbed + } else if (bedrockCommand.isLlama2() === true) { + this.stopReasonKey = 'stop_reason' + this.generator = handleLlama2 + } else if (bedrockCommand.isTitan() === true) { + this.stopReasonKey = 'completionReason' + this.generator = handleTitan + } else { + // The model doesn't support streaming, or we have not instrumented it. + this.generator = stream + } + } + + /** + * Encodes the output body into a Uint8Array, updates the pass through + * parameters with the compiled response object, and invokes the response + * handler. The trace segment is also updated to mark the end of the stream + * processing and account for the time it took to process the stream within + * the trace. + */ + finish() { + this.response.output.body = new TextEncoder().encode(JSON.stringify(this.response.output.body)) + this.passThroughParams.response = this.response + this.onComplete(this.passThroughParams) + + this.segment.touch() + } + + /** + * Finds the reason for the end of the stream based upon the model's known + * stop reason key. + * + * @param {object} event + * @returns {string} + */ + getStopReason(event) { + if (this.stopReasonKey.includes('.')) { + const parts = this.stopReasonKey.split('.') + let val = event + for (const p of parts) { + val = val[p] + } + return val + } + + return event[this.stopReasonKey] + } + + /** + * Decodes the Uint8Array that represents a model response. + * + * @param {object} event + * + * @returns {object} + */ + parseEvent(event) { + const json = this.decoder.decode(event.chunk.bytes) + return JSON.parse(json) + } + + /** + * If the given event is the last event in the stream, update the response + * headers with the metrics data from the event. + * + * @param {object} parsedEvent + */ + updateHeaders(parsedEvent) { + if (this.getStopReason(parsedEvent) === null) { + return + } + + this.response.response.headers = { + 'x-amzn-requestid': this.passThroughParams.response.response.headers['x-amzn-requestid'] + } + delete parsedEvent['amazon-bedrock-invocationMetrics'] + } +} + +async function* handleClaude() { + let currentBody = {} + let completion = '' + + try { + for await (const event of this.stream) { + yield event + const parsed = this.parseEvent(event) + this.updateHeaders(parsed) + currentBody = parsed + completion += parsed.completion + } + } finally { + currentBody.completion = completion + this.response.output.body = currentBody + this.finish() + } +} + +async function* handleCohere() { + let currentBody = {} + const generations = [] + try { + for await (const event of this.stream) { + yield event + const parsed = this.parseEvent(event) + this.updateHeaders(parsed) + currentBody = parsed + Array.prototype.push.apply(generations, parsed.generations) + } + } finally { + currentBody.generations = generations + this.response.output.body = currentBody + this.finish() + } +} + +async function* handleCohereEmbed() { + let currentBody = {} + const embeddings = [] + try { + for await (const event of this.stream) { + yield event + const parsed = this.parseEvent(event) + this.updateHeaders(parsed) + currentBody = parsed + Array.prototype.push.apply(embeddings, parsed.embeddings) + } + } finally { + currentBody.embeddings = embeddings + this.response.output.body = currentBody + this.finish() + } +} + +async function* handleLlama2() { + let currentBody = {} + let generation = '' + + try { + for await (const event of this.stream) { + yield event + const parsed = this.parseEvent(event) + this.updateHeaders(parsed) + currentBody = parsed + generation += parsed.generation + } + } finally { + currentBody.generation = generation + this.response.output.body = currentBody + this.finish() + } +} + +async function* handleTitan() { + const body = this.response.output.body + body.results = [] + + try { + for await (const event of this.stream) { + yield event // Pass it up to the real consumer of the stream. + const parsed = this.parseEvent(event) + this.updateHeaders(parsed) + body.results.push(parsed) + } + } finally { + this.finish() + } +} + +module.exports = StreamHandler diff --git a/lib/metrics/names.js b/lib/metrics/names.js index 82d6e3a1a3..68321fcb13 100644 --- a/lib/metrics/names.js +++ b/lib/metrics/names.js @@ -180,6 +180,10 @@ AI.OPENAI = { COMPLETION: `${AI.COMPLETION}/OpenAI/create` } +AI.BEDROCK = { + TRACKING_PREFIX: `${AI.TRACKING_PREFIX}/Bedrock` +} + AI.LANGCHAIN = { TRACKING_PREFIX: `${AI.TRACKING_PREFIX}/Langchain`, EMBEDDING: `${AI.EMBEDDING}/Langchain`, diff --git a/lib/shim/shim.js b/lib/shim/shim.js index 1a0a49a307..f3a6ba8f92 100644 --- a/lib/shim/shim.js +++ b/lib/shim/shim.js @@ -55,10 +55,6 @@ module.exports = Shim Shim.defineProperty = defineProperty Shim.defineProperties = defineProperties -// This is for backwards compat for external libraries like aws-sdk that expect the symbol to be defined here -defineProperty(Shim, 'DISABLE_DT', symbols.disableDT) -defineProperty(Shim.prototype, 'DISABLE_DT', symbols.disableDT) - // Copy the argument index enumeration onto the shim. Shim.prototype.ARG_INDEXES = specs.ARG_INDEXES defineProperties(Shim.prototype, specs.ARG_INDEXES) diff --git a/package-lock.json b/package-lock.json index c3d58acfec..abf1ac9e2a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,7 +11,6 @@ "dependencies": { "@grpc/grpc-js": "^1.9.4", "@grpc/proto-loader": "^0.7.5", - "@newrelic/aws-sdk": "^7.3.0", "@newrelic/ritm": "^7.2.0", "@newrelic/security-agent": "^1.1.1", "@tyriar/fibonacci-heap": "^2.0.7", @@ -29,14 +28,19 @@ "newrelic-naming-rules": "bin/test-naming-rules.js" }, "devDependencies": { + "@aws-sdk/client-s3": "^3.556.0", + "@aws-sdk/s3-request-presigner": "^3.556.0", "@koa/router": "^12.0.1", "@newrelic/eslint-config": "^0.3.0", "@newrelic/newrelic-oss-cli": "^0.1.2", "@newrelic/test-utilities": "^8.5.0", "@octokit/rest": "^18.0.15", "@slack/bolt": "^3.7.0", + "@smithy/eventstream-codec": "^2.2.0", + "@smithy/util-utf8": "^2.3.0", "ajv": "^6.12.6", "async": "^3.2.4", + "aws-sdk": "^2.1604.0", "c8": "^8.0.1", "clean-jsdoc-theme": "^4.2.18", "commander": "^7.0.0", @@ -120,1619 +124,1875 @@ "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", "dev": true }, - "node_modules/@aws-crypto/util": { + "node_modules/@aws-crypto/crc32c": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@aws-crypto/util/-/util-3.0.0.tgz", - "integrity": "sha512-2OJlpeJpCR48CC8r+uKVChzs9Iungj9wkZrl8Z041DWEWvyIHILYKCPNzJghKsivj+S3mLo6BVc7mBNzdxA46w==", + "resolved": "https://registry.npmjs.org/@aws-crypto/crc32c/-/crc32c-3.0.0.tgz", + "integrity": "sha512-ENNPPManmnVJ4BTXlOjAgD7URidbAznURqD0KvfREyc4o20DPYdEldU1f5cQ7Jbj0CJJSPaMIk/9ZshdB3210w==", "dev": true, "dependencies": { + "@aws-crypto/util": "^3.0.0", "@aws-sdk/types": "^3.222.0", - "@aws-sdk/util-utf8-browser": "^3.0.0", "tslib": "^1.11.1" } }, - "node_modules/@aws-crypto/util/node_modules/tslib": { + "node_modules/@aws-crypto/crc32c/node_modules/tslib": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", "dev": true }, - "node_modules/@aws-sdk/types": { - "version": "3.511.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.511.0.tgz", - "integrity": "sha512-P03ufufxmkvd7nO46oOeEqYIMPJ8qMCKxAsfJk1JBVPQ1XctVntbail4/UFnrnzij8DTl4Mk/D62uGo7+RolXA==", + "node_modules/@aws-crypto/ie11-detection": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/ie11-detection/-/ie11-detection-3.0.0.tgz", + "integrity": "sha512-341lBBkiY1DfDNKai/wXM3aujNBkXR7tq1URPQDL9wi3AUbI80NR74uF1TXHMm7po1AcnFk8iu2S2IeU/+/A+Q==", "dev": true, "dependencies": { - "@smithy/types": "^2.9.1", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" + "tslib": "^1.11.1" } }, - "node_modules/@aws-sdk/util-utf8-browser": { - "version": "3.259.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-utf8-browser/-/util-utf8-browser-3.259.0.tgz", - "integrity": "sha512-UvFa/vR+e19XookZF8RzFZBrw2EUkQWxiBW0yYQAhvk3C+QVGl0H3ouca8LDBlBfQKXwmW3huo/59H8rwb1wJw==", + "node_modules/@aws-crypto/ie11-detection/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "node_modules/@aws-crypto/sha1-browser": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/sha1-browser/-/sha1-browser-3.0.0.tgz", + "integrity": "sha512-NJth5c997GLHs6nOYTzFKTbYdMNA6/1XlKVgnZoaZcQ7z7UJlOgj2JdbHE8tiYLS3fzXNCguct77SPGat2raSw==", "dev": true, "dependencies": { - "tslib": "^2.3.1" + "@aws-crypto/ie11-detection": "^3.0.0", + "@aws-crypto/supports-web-crypto": "^3.0.0", + "@aws-crypto/util": "^3.0.0", + "@aws-sdk/types": "^3.222.0", + "@aws-sdk/util-locate-window": "^3.0.0", + "@aws-sdk/util-utf8-browser": "^3.0.0", + "tslib": "^1.11.1" } }, - "node_modules/@babel/code-frame": { - "version": "7.23.5", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz", - "integrity": "sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==", + "node_modules/@aws-crypto/sha1-browser/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "node_modules/@aws-crypto/sha256-browser": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-browser/-/sha256-browser-3.0.0.tgz", + "integrity": "sha512-8VLmW2B+gjFbU5uMeqtQM6Nj0/F1bro80xQXCW6CQBWgosFWXTx77aeOF5CAIAmbOK64SdMBJdNr6J41yP5mvQ==", "dev": true, "dependencies": { - "@babel/highlight": "^7.23.4", - "chalk": "^2.4.2" - }, - "engines": { - "node": ">=6.9.0" + "@aws-crypto/ie11-detection": "^3.0.0", + "@aws-crypto/sha256-js": "^3.0.0", + "@aws-crypto/supports-web-crypto": "^3.0.0", + "@aws-crypto/util": "^3.0.0", + "@aws-sdk/types": "^3.222.0", + "@aws-sdk/util-locate-window": "^3.0.0", + "@aws-sdk/util-utf8-browser": "^3.0.0", + "tslib": "^1.11.1" } }, - "node_modules/@babel/compat-data": { - "version": "7.23.5", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.23.5.tgz", - "integrity": "sha512-uU27kfDRlhfKl+w1U6vp16IuvSLtjAxdArVXPa9BvLkrr7CYIsxH5adpHObeAGY/41+syctUWOZ140a2Rvkgjw==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } + "node_modules/@aws-crypto/sha256-browser/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true }, - "node_modules/@babel/core": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.9.tgz", - "integrity": "sha512-5q0175NOjddqpvvzU+kDiSOAk4PfdO6FvwCWoQ6RO7rTzEe8vlo+4HVfcnAREhD4npMs0e9uZypjTwzZPCf/cw==", + "node_modules/@aws-crypto/sha256-js": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-js/-/sha256-js-3.0.0.tgz", + "integrity": "sha512-PnNN7os0+yd1XvXAy23CFOmTbMaDxgxXtTKHybrJ39Y8kGzBATgBFibWJKH6BhytLI/Zyszs87xCOBNyBig6vQ==", "dev": true, "dependencies": { - "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.23.5", - "@babel/generator": "^7.23.6", - "@babel/helper-compilation-targets": "^7.23.6", - "@babel/helper-module-transforms": "^7.23.3", - "@babel/helpers": "^7.23.9", - "@babel/parser": "^7.23.9", - "@babel/template": "^7.23.9", - "@babel/traverse": "^7.23.9", - "@babel/types": "^7.23.9", - "convert-source-map": "^2.0.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.2.3", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/babel" + "@aws-crypto/util": "^3.0.0", + "@aws-sdk/types": "^3.222.0", + "tslib": "^1.11.1" } }, - "node_modules/@babel/core/node_modules/convert-source-map": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "node_modules/@aws-crypto/sha256-js/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", "dev": true }, - "node_modules/@babel/core/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "node_modules/@aws-crypto/supports-web-crypto": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/supports-web-crypto/-/supports-web-crypto-3.0.0.tgz", + "integrity": "sha512-06hBdMwUAb2WFTuGG73LSC0wfPu93xWwo5vL2et9eymgmu3Id5vFAHBbajVWiGhPO37qcsdCap/FqXvJGJWPIg==", "dev": true, - "bin": { - "semver": "bin/semver.js" + "dependencies": { + "tslib": "^1.11.1" } }, - "node_modules/@babel/generator": { - "version": "7.23.6", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.6.tgz", - "integrity": "sha512-qrSfCYxYQB5owCmGLbl8XRpX1ytXlpueOb0N0UmQwA073KZxejgQTzAmJezxvpwQD9uGtK2shHdi55QT+MbjIw==", + "node_modules/@aws-crypto/supports-web-crypto/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "node_modules/@aws-crypto/util": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/util/-/util-3.0.0.tgz", + "integrity": "sha512-2OJlpeJpCR48CC8r+uKVChzs9Iungj9wkZrl8Z041DWEWvyIHILYKCPNzJghKsivj+S3mLo6BVc7mBNzdxA46w==", "dev": true, "dependencies": { - "@babel/types": "^7.23.6", - "@jridgewell/gen-mapping": "^0.3.2", - "@jridgewell/trace-mapping": "^0.3.17", - "jsesc": "^2.5.1" + "@aws-sdk/types": "^3.222.0", + "@aws-sdk/util-utf8-browser": "^3.0.0", + "tslib": "^1.11.1" + } + }, + "node_modules/@aws-crypto/util/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "node_modules/@aws-sdk/client-s3": { + "version": "3.556.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-s3/-/client-s3-3.556.0.tgz", + "integrity": "sha512-6WF9Kuzz1/8zqX8hKBpqj9+FYwQ5uTsVcOKpTW94AMX2qtIeVRlwlnNnYyywWo61yqD3g59CMNHcqSsaqAwglg==", + "dev": true, + "dependencies": { + "@aws-crypto/sha1-browser": "3.0.0", + "@aws-crypto/sha256-browser": "3.0.0", + "@aws-crypto/sha256-js": "3.0.0", + "@aws-sdk/client-sts": "3.556.0", + "@aws-sdk/core": "3.556.0", + "@aws-sdk/credential-provider-node": "3.556.0", + "@aws-sdk/middleware-bucket-endpoint": "3.535.0", + "@aws-sdk/middleware-expect-continue": "3.535.0", + "@aws-sdk/middleware-flexible-checksums": "3.535.0", + "@aws-sdk/middleware-host-header": "3.535.0", + "@aws-sdk/middleware-location-constraint": "3.535.0", + "@aws-sdk/middleware-logger": "3.535.0", + "@aws-sdk/middleware-recursion-detection": "3.535.0", + "@aws-sdk/middleware-sdk-s3": "3.556.0", + "@aws-sdk/middleware-signing": "3.556.0", + "@aws-sdk/middleware-ssec": "3.537.0", + "@aws-sdk/middleware-user-agent": "3.540.0", + "@aws-sdk/region-config-resolver": "3.535.0", + "@aws-sdk/signature-v4-multi-region": "3.556.0", + "@aws-sdk/types": "3.535.0", + "@aws-sdk/util-endpoints": "3.540.0", + "@aws-sdk/util-user-agent-browser": "3.535.0", + "@aws-sdk/util-user-agent-node": "3.535.0", + "@aws-sdk/xml-builder": "3.535.0", + "@smithy/config-resolver": "^2.2.0", + "@smithy/core": "^1.4.2", + "@smithy/eventstream-serde-browser": "^2.2.0", + "@smithy/eventstream-serde-config-resolver": "^2.2.0", + "@smithy/eventstream-serde-node": "^2.2.0", + "@smithy/fetch-http-handler": "^2.5.0", + "@smithy/hash-blob-browser": "^2.2.0", + "@smithy/hash-node": "^2.2.0", + "@smithy/hash-stream-node": "^2.2.0", + "@smithy/invalid-dependency": "^2.2.0", + "@smithy/md5-js": "^2.2.0", + "@smithy/middleware-content-length": "^2.2.0", + "@smithy/middleware-endpoint": "^2.5.1", + "@smithy/middleware-retry": "^2.3.1", + "@smithy/middleware-serde": "^2.3.0", + "@smithy/middleware-stack": "^2.2.0", + "@smithy/node-config-provider": "^2.3.0", + "@smithy/node-http-handler": "^2.5.0", + "@smithy/protocol-http": "^3.3.0", + "@smithy/smithy-client": "^2.5.1", + "@smithy/types": "^2.12.0", + "@smithy/url-parser": "^2.2.0", + "@smithy/util-base64": "^2.3.0", + "@smithy/util-body-length-browser": "^2.2.0", + "@smithy/util-body-length-node": "^2.3.0", + "@smithy/util-defaults-mode-browser": "^2.2.1", + "@smithy/util-defaults-mode-node": "^2.3.1", + "@smithy/util-endpoints": "^1.2.0", + "@smithy/util-retry": "^2.2.0", + "@smithy/util-stream": "^2.2.0", + "@smithy/util-utf8": "^2.3.0", + "@smithy/util-waiter": "^2.2.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=6.9.0" + "node": ">=14.0.0" } }, - "node_modules/@babel/helper-compilation-targets": { - "version": "7.23.6", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.23.6.tgz", - "integrity": "sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ==", - "dev": true, - "dependencies": { - "@babel/compat-data": "^7.23.5", - "@babel/helper-validator-option": "^7.23.5", - "browserslist": "^4.22.2", - "lru-cache": "^5.1.1", - "semver": "^6.3.1" + "node_modules/@aws-sdk/client-sso": { + "version": "3.556.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.556.0.tgz", + "integrity": "sha512-unXdWS7uvHqCcOyC1de+Fr8m3F2vMg2m24GPea0bg7rVGTYmiyn9mhUX11VCt+ozydrw+F50FQwL6OqoqPocmw==", + "dev": true, + "dependencies": { + "@aws-crypto/sha256-browser": "3.0.0", + "@aws-crypto/sha256-js": "3.0.0", + "@aws-sdk/core": "3.556.0", + "@aws-sdk/middleware-host-header": "3.535.0", + "@aws-sdk/middleware-logger": "3.535.0", + "@aws-sdk/middleware-recursion-detection": "3.535.0", + "@aws-sdk/middleware-user-agent": "3.540.0", + "@aws-sdk/region-config-resolver": "3.535.0", + "@aws-sdk/types": "3.535.0", + "@aws-sdk/util-endpoints": "3.540.0", + "@aws-sdk/util-user-agent-browser": "3.535.0", + "@aws-sdk/util-user-agent-node": "3.535.0", + "@smithy/config-resolver": "^2.2.0", + "@smithy/core": "^1.4.2", + "@smithy/fetch-http-handler": "^2.5.0", + "@smithy/hash-node": "^2.2.0", + "@smithy/invalid-dependency": "^2.2.0", + "@smithy/middleware-content-length": "^2.2.0", + "@smithy/middleware-endpoint": "^2.5.1", + "@smithy/middleware-retry": "^2.3.1", + "@smithy/middleware-serde": "^2.3.0", + "@smithy/middleware-stack": "^2.2.0", + "@smithy/node-config-provider": "^2.3.0", + "@smithy/node-http-handler": "^2.5.0", + "@smithy/protocol-http": "^3.3.0", + "@smithy/smithy-client": "^2.5.1", + "@smithy/types": "^2.12.0", + "@smithy/url-parser": "^2.2.0", + "@smithy/util-base64": "^2.3.0", + "@smithy/util-body-length-browser": "^2.2.0", + "@smithy/util-body-length-node": "^2.3.0", + "@smithy/util-defaults-mode-browser": "^2.2.1", + "@smithy/util-defaults-mode-node": "^2.3.1", + "@smithy/util-endpoints": "^1.2.0", + "@smithy/util-middleware": "^2.2.0", + "@smithy/util-retry": "^2.2.0", + "@smithy/util-utf8": "^2.3.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=6.9.0" + "node": ">=14.0.0" } }, - "node_modules/@babel/helper-compilation-targets/node_modules/lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "node_modules/@aws-sdk/client-sso-oidc": { + "version": "3.556.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso-oidc/-/client-sso-oidc-3.556.0.tgz", + "integrity": "sha512-AXKd2TB6nNrksu+OfmHl8uI07PdgzOo4o8AxoRO8SHlwoMAGvcT9optDGVSYoVfgOKTymCoE7h8/UoUfPc11wQ==", + "dev": true, + "dependencies": { + "@aws-crypto/sha256-browser": "3.0.0", + "@aws-crypto/sha256-js": "3.0.0", + "@aws-sdk/client-sts": "3.556.0", + "@aws-sdk/core": "3.556.0", + "@aws-sdk/middleware-host-header": "3.535.0", + "@aws-sdk/middleware-logger": "3.535.0", + "@aws-sdk/middleware-recursion-detection": "3.535.0", + "@aws-sdk/middleware-user-agent": "3.540.0", + "@aws-sdk/region-config-resolver": "3.535.0", + "@aws-sdk/types": "3.535.0", + "@aws-sdk/util-endpoints": "3.540.0", + "@aws-sdk/util-user-agent-browser": "3.535.0", + "@aws-sdk/util-user-agent-node": "3.535.0", + "@smithy/config-resolver": "^2.2.0", + "@smithy/core": "^1.4.2", + "@smithy/fetch-http-handler": "^2.5.0", + "@smithy/hash-node": "^2.2.0", + "@smithy/invalid-dependency": "^2.2.0", + "@smithy/middleware-content-length": "^2.2.0", + "@smithy/middleware-endpoint": "^2.5.1", + "@smithy/middleware-retry": "^2.3.1", + "@smithy/middleware-serde": "^2.3.0", + "@smithy/middleware-stack": "^2.2.0", + "@smithy/node-config-provider": "^2.3.0", + "@smithy/node-http-handler": "^2.5.0", + "@smithy/protocol-http": "^3.3.0", + "@smithy/smithy-client": "^2.5.1", + "@smithy/types": "^2.12.0", + "@smithy/url-parser": "^2.2.0", + "@smithy/util-base64": "^2.3.0", + "@smithy/util-body-length-browser": "^2.2.0", + "@smithy/util-body-length-node": "^2.3.0", + "@smithy/util-defaults-mode-browser": "^2.2.1", + "@smithy/util-defaults-mode-node": "^2.3.1", + "@smithy/util-endpoints": "^1.2.0", + "@smithy/util-middleware": "^2.2.0", + "@smithy/util-retry": "^2.2.0", + "@smithy/util-utf8": "^2.3.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "@aws-sdk/credential-provider-node": "^3.556.0" + } + }, + "node_modules/@aws-sdk/client-sts": { + "version": "3.556.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.556.0.tgz", + "integrity": "sha512-TsK3js7Suh9xEmC886aY+bv0KdLLYtzrcmVt6sJ/W6EnDXYQhBuKYFhp03NrN2+vSvMGpqJwR62DyfKe1G0QzQ==", + "dev": true, + "dependencies": { + "@aws-crypto/sha256-browser": "3.0.0", + "@aws-crypto/sha256-js": "3.0.0", + "@aws-sdk/core": "3.556.0", + "@aws-sdk/middleware-host-header": "3.535.0", + "@aws-sdk/middleware-logger": "3.535.0", + "@aws-sdk/middleware-recursion-detection": "3.535.0", + "@aws-sdk/middleware-user-agent": "3.540.0", + "@aws-sdk/region-config-resolver": "3.535.0", + "@aws-sdk/types": "3.535.0", + "@aws-sdk/util-endpoints": "3.540.0", + "@aws-sdk/util-user-agent-browser": "3.535.0", + "@aws-sdk/util-user-agent-node": "3.535.0", + "@smithy/config-resolver": "^2.2.0", + "@smithy/core": "^1.4.2", + "@smithy/fetch-http-handler": "^2.5.0", + "@smithy/hash-node": "^2.2.0", + "@smithy/invalid-dependency": "^2.2.0", + "@smithy/middleware-content-length": "^2.2.0", + "@smithy/middleware-endpoint": "^2.5.1", + "@smithy/middleware-retry": "^2.3.1", + "@smithy/middleware-serde": "^2.3.0", + "@smithy/middleware-stack": "^2.2.0", + "@smithy/node-config-provider": "^2.3.0", + "@smithy/node-http-handler": "^2.5.0", + "@smithy/protocol-http": "^3.3.0", + "@smithy/smithy-client": "^2.5.1", + "@smithy/types": "^2.12.0", + "@smithy/url-parser": "^2.2.0", + "@smithy/util-base64": "^2.3.0", + "@smithy/util-body-length-browser": "^2.2.0", + "@smithy/util-body-length-node": "^2.3.0", + "@smithy/util-defaults-mode-browser": "^2.2.1", + "@smithy/util-defaults-mode-node": "^2.3.1", + "@smithy/util-endpoints": "^1.2.0", + "@smithy/util-middleware": "^2.2.0", + "@smithy/util-retry": "^2.2.0", + "@smithy/util-utf8": "^2.3.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "@aws-sdk/credential-provider-node": "^3.556.0" + } + }, + "node_modules/@aws-sdk/core": { + "version": "3.556.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.556.0.tgz", + "integrity": "sha512-vJaSaHw2kPQlo11j/Rzuz0gk1tEaKdz+2ser0f0qZ5vwFlANjt08m/frU17ctnVKC1s58bxpctO/1P894fHLrA==", "dev": true, "dependencies": { - "yallist": "^3.0.2" + "@smithy/core": "^1.4.2", + "@smithy/protocol-http": "^3.3.0", + "@smithy/signature-v4": "^2.3.0", + "@smithy/smithy-client": "^2.5.1", + "@smithy/types": "^2.12.0", + "fast-xml-parser": "4.2.5", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" } }, - "node_modules/@babel/helper-compilation-targets/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "node_modules/@aws-sdk/credential-provider-env": { + "version": "3.535.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.535.0.tgz", + "integrity": "sha512-XppwO8c0GCGSAvdzyJOhbtktSEaShg14VJKg8mpMa1XcgqzmcqqHQjtDWbx5rZheY1VdpXZhpEzJkB6LpQejpA==", "dev": true, - "bin": { - "semver": "bin/semver.js" + "dependencies": { + "@aws-sdk/types": "3.535.0", + "@smithy/property-provider": "^2.2.0", + "@smithy/types": "^2.12.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" } }, - "node_modules/@babel/helper-compilation-targets/node_modules/yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "dev": true - }, - "node_modules/@babel/helper-environment-visitor": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", - "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", + "node_modules/@aws-sdk/credential-provider-http": { + "version": "3.552.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.552.0.tgz", + "integrity": "sha512-vsmu7Cz1i45pFEqzVb4JcFmAmVnWFNLsGheZc8SCptlqCO5voETrZZILHYIl4cjKkSDk3pblBOf0PhyjqWW6WQ==", "dev": true, + "dependencies": { + "@aws-sdk/types": "3.535.0", + "@smithy/fetch-http-handler": "^2.5.0", + "@smithy/node-http-handler": "^2.5.0", + "@smithy/property-provider": "^2.2.0", + "@smithy/protocol-http": "^3.3.0", + "@smithy/smithy-client": "^2.5.1", + "@smithy/types": "^2.12.0", + "@smithy/util-stream": "^2.2.0", + "tslib": "^2.6.2" + }, "engines": { - "node": ">=6.9.0" + "node": ">=14.0.0" } }, - "node_modules/@babel/helper-function-name": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", - "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", + "node_modules/@aws-sdk/credential-provider-ini": { + "version": "3.556.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.556.0.tgz", + "integrity": "sha512-0Nz4ErOlXhe3muxWYMbPwRMgfKmVbBp36BAE2uv/z5wTbfdBkcgUwaflEvlKCLUTdHzuZsQk+BFS/gVyaUeOuA==", "dev": true, "dependencies": { - "@babel/template": "^7.22.15", - "@babel/types": "^7.23.0" + "@aws-sdk/client-sts": "3.556.0", + "@aws-sdk/credential-provider-env": "3.535.0", + "@aws-sdk/credential-provider-process": "3.535.0", + "@aws-sdk/credential-provider-sso": "3.556.0", + "@aws-sdk/credential-provider-web-identity": "3.556.0", + "@aws-sdk/types": "3.535.0", + "@smithy/credential-provider-imds": "^2.3.0", + "@smithy/property-provider": "^2.2.0", + "@smithy/shared-ini-file-loader": "^2.4.0", + "@smithy/types": "^2.12.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=6.9.0" + "node": ">=14.0.0" } }, - "node_modules/@babel/helper-hoist-variables": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", - "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", + "node_modules/@aws-sdk/credential-provider-node": { + "version": "3.556.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.556.0.tgz", + "integrity": "sha512-s1xVtKjyGc60O8qcNIzS1X3H+pWEwEfZ7TgNznVDNyuXvLrlNWiAcigPWGl2aAkc8tGcsSG0Qpyw2KYC939LFg==", "dev": true, "dependencies": { - "@babel/types": "^7.22.5" + "@aws-sdk/credential-provider-env": "3.535.0", + "@aws-sdk/credential-provider-http": "3.552.0", + "@aws-sdk/credential-provider-ini": "3.556.0", + "@aws-sdk/credential-provider-process": "3.535.0", + "@aws-sdk/credential-provider-sso": "3.556.0", + "@aws-sdk/credential-provider-web-identity": "3.556.0", + "@aws-sdk/types": "3.535.0", + "@smithy/credential-provider-imds": "^2.3.0", + "@smithy/property-provider": "^2.2.0", + "@smithy/shared-ini-file-loader": "^2.4.0", + "@smithy/types": "^2.12.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=6.9.0" + "node": ">=14.0.0" } }, - "node_modules/@babel/helper-module-imports": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz", - "integrity": "sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==", + "node_modules/@aws-sdk/credential-provider-process": { + "version": "3.535.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.535.0.tgz", + "integrity": "sha512-9O1OaprGCnlb/kYl8RwmH7Mlg8JREZctB8r9sa1KhSsWFq/SWO0AuJTyowxD7zL5PkeS4eTvzFFHWCa3OO5epA==", "dev": true, "dependencies": { - "@babel/types": "^7.22.15" + "@aws-sdk/types": "3.535.0", + "@smithy/property-provider": "^2.2.0", + "@smithy/shared-ini-file-loader": "^2.4.0", + "@smithy/types": "^2.12.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=6.9.0" + "node": ">=14.0.0" } }, - "node_modules/@babel/helper-module-transforms": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.3.tgz", - "integrity": "sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ==", + "node_modules/@aws-sdk/credential-provider-sso": { + "version": "3.556.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.556.0.tgz", + "integrity": "sha512-ETuBgcnpfxqadEAqhQFWpKoV1C/NAgvs5CbBc5EJbelJ8f4prTdErIHjrRtVT8c02MXj92QwczsiNYd5IoOqyw==", "dev": true, "dependencies": { - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-module-imports": "^7.22.15", - "@babel/helper-simple-access": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/helper-validator-identifier": "^7.22.20" + "@aws-sdk/client-sso": "3.556.0", + "@aws-sdk/token-providers": "3.556.0", + "@aws-sdk/types": "3.535.0", + "@smithy/property-provider": "^2.2.0", + "@smithy/shared-ini-file-loader": "^2.4.0", + "@smithy/types": "^2.12.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" + "node": ">=14.0.0" } }, - "node_modules/@babel/helper-simple-access": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz", - "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==", + "node_modules/@aws-sdk/credential-provider-web-identity": { + "version": "3.556.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.556.0.tgz", + "integrity": "sha512-R/YAL8Uh8i+dzVjzMnbcWLIGeeRi2mioHVGnVF+minmaIkCiQMZg2HPrdlKm49El+RljT28Nl5YHRuiqzEIwMA==", "dev": true, "dependencies": { - "@babel/types": "^7.22.5" + "@aws-sdk/client-sts": "3.556.0", + "@aws-sdk/types": "3.535.0", + "@smithy/property-provider": "^2.2.0", + "@smithy/types": "^2.12.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=6.9.0" + "node": ">=14.0.0" } }, - "node_modules/@babel/helper-split-export-declaration": { - "version": "7.22.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", - "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", + "node_modules/@aws-sdk/middleware-bucket-endpoint": { + "version": "3.535.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-bucket-endpoint/-/middleware-bucket-endpoint-3.535.0.tgz", + "integrity": "sha512-7sijlfQsc4UO9Fsl11mU26Y5f9E7g6UoNg/iJUBpC5pgvvmdBRO5UEhbB/gnqvOEPsBXyhmfzbstebq23Qdz7A==", "dev": true, "dependencies": { - "@babel/types": "^7.22.5" + "@aws-sdk/types": "3.535.0", + "@aws-sdk/util-arn-parser": "3.535.0", + "@smithy/node-config-provider": "^2.3.0", + "@smithy/protocol-http": "^3.3.0", + "@smithy/types": "^2.12.0", + "@smithy/util-config-provider": "^2.3.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=6.9.0" + "node": ">=14.0.0" } }, - "node_modules/@babel/helper-string-parser": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz", - "integrity": "sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==", + "node_modules/@aws-sdk/middleware-expect-continue": { + "version": "3.535.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-expect-continue/-/middleware-expect-continue-3.535.0.tgz", + "integrity": "sha512-hFKyqUBky0NWCVku8iZ9+PACehx0p6vuMw5YnZf8FVgHP0fode0b/NwQY6UY7oor/GftvRsAlRUAWGNFEGUpwA==", "dev": true, + "dependencies": { + "@aws-sdk/types": "3.535.0", + "@smithy/protocol-http": "^3.3.0", + "@smithy/types": "^2.12.0", + "tslib": "^2.6.2" + }, "engines": { - "node": ">=6.9.0" + "node": ">=14.0.0" } }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", - "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", + "node_modules/@aws-sdk/middleware-flexible-checksums": { + "version": "3.535.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-flexible-checksums/-/middleware-flexible-checksums-3.535.0.tgz", + "integrity": "sha512-rBIzldY9jjRATxICDX7t77aW6ctqmVDgnuAOgbVT5xgHftt4o7PGWKoMvl/45hYqoQgxVFnCBof9bxkqSBebVA==", "dev": true, + "dependencies": { + "@aws-crypto/crc32": "3.0.0", + "@aws-crypto/crc32c": "3.0.0", + "@aws-sdk/types": "3.535.0", + "@smithy/is-array-buffer": "^2.2.0", + "@smithy/protocol-http": "^3.3.0", + "@smithy/types": "^2.12.0", + "@smithy/util-utf8": "^2.3.0", + "tslib": "^2.6.2" + }, "engines": { - "node": ">=6.9.0" + "node": ">=14.0.0" } }, - "node_modules/@babel/helper-validator-option": { - "version": "7.23.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz", - "integrity": "sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==", + "node_modules/@aws-sdk/middleware-host-header": { + "version": "3.535.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.535.0.tgz", + "integrity": "sha512-0h6TWjBWtDaYwHMQJI9ulafeS4lLaw1vIxRjbpH0svFRt6Eve+Sy8NlVhECfTU2hNz/fLubvrUxsXoThaLBIew==", "dev": true, + "dependencies": { + "@aws-sdk/types": "3.535.0", + "@smithy/protocol-http": "^3.3.0", + "@smithy/types": "^2.12.0", + "tslib": "^2.6.2" + }, "engines": { - "node": ">=6.9.0" + "node": ">=14.0.0" } }, - "node_modules/@babel/helpers": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.23.9.tgz", - "integrity": "sha512-87ICKgU5t5SzOT7sBMfCOZQ2rHjRU+Pcb9BoILMYz600W6DkVRLFBPwQ18gwUVvggqXivaUakpnxWQGbpywbBQ==", + "node_modules/@aws-sdk/middleware-location-constraint": { + "version": "3.535.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-location-constraint/-/middleware-location-constraint-3.535.0.tgz", + "integrity": "sha512-SxfS9wfidUZZ+WnlKRTCRn3h+XTsymXRXPJj8VV6hNRNeOwzNweoG3YhQbTowuuNfXf89m9v6meYkBBtkdacKw==", "dev": true, "dependencies": { - "@babel/template": "^7.23.9", - "@babel/traverse": "^7.23.9", - "@babel/types": "^7.23.9" + "@aws-sdk/types": "3.535.0", + "@smithy/types": "^2.12.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=6.9.0" + "node": ">=14.0.0" } }, - "node_modules/@babel/highlight": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.23.4.tgz", - "integrity": "sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==", + "node_modules/@aws-sdk/middleware-logger": { + "version": "3.535.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.535.0.tgz", + "integrity": "sha512-huNHpONOrEDrdRTvSQr1cJiRMNf0S52NDXtaPzdxiubTkP+vni2MohmZANMOai/qT0olmEVX01LhZ0ZAOgmg6A==", "dev": true, "dependencies": { - "@babel/helper-validator-identifier": "^7.22.20", - "chalk": "^2.4.2", - "js-tokens": "^4.0.0" + "@aws-sdk/types": "3.535.0", + "@smithy/types": "^2.12.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=6.9.0" + "node": ">=14.0.0" } }, - "node_modules/@babel/parser": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.9.tgz", - "integrity": "sha512-9tcKgqKbs3xGJ+NtKF2ndOBBLVwPjl1SHxPQkd36r3Dlirw3xWUeGaTbqr7uGZcTaxkVNwc+03SVP7aCdWrTlA==", + "node_modules/@aws-sdk/middleware-recursion-detection": { + "version": "3.535.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.535.0.tgz", + "integrity": "sha512-am2qgGs+gwqmR4wHLWpzlZ8PWhm4ktj5bYSgDrsOfjhdBlWNxvPoID9/pDAz5RWL48+oH7I6SQzMqxXsFDikrw==", "dev": true, - "bin": { - "parser": "bin/babel-parser.js" + "dependencies": { + "@aws-sdk/types": "3.535.0", + "@smithy/protocol-http": "^3.3.0", + "@smithy/types": "^2.12.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=6.0.0" + "node": ">=14.0.0" } }, - "node_modules/@babel/template": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.23.9.tgz", - "integrity": "sha512-+xrD2BWLpvHKNmX2QbpdpsBaWnRxahMwJjO+KZk2JOElj5nSmKezyS1B4u+QbHMTX69t4ukm6hh9lsYQ7GHCKA==", + "node_modules/@aws-sdk/middleware-sdk-s3": { + "version": "3.556.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-s3/-/middleware-sdk-s3-3.556.0.tgz", + "integrity": "sha512-4W/dnxqj1B6/uS/5Z+3UHaqDDGjNPgEVlqf5d3ToOFZ31ZfpANwhcCmyX39JklC4aolCEi9renQ5wHnTCC8K8g==", "dev": true, "dependencies": { - "@babel/code-frame": "^7.23.5", - "@babel/parser": "^7.23.9", - "@babel/types": "^7.23.9" + "@aws-sdk/types": "3.535.0", + "@aws-sdk/util-arn-parser": "3.535.0", + "@smithy/node-config-provider": "^2.3.0", + "@smithy/protocol-http": "^3.3.0", + "@smithy/signature-v4": "^2.3.0", + "@smithy/smithy-client": "^2.5.1", + "@smithy/types": "^2.12.0", + "@smithy/util-config-provider": "^2.3.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=6.9.0" + "node": ">=14.0.0" } }, - "node_modules/@babel/traverse": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.9.tgz", - "integrity": "sha512-I/4UJ9vs90OkBtY6iiiTORVMyIhJ4kAVmsKo9KFc8UOxMeUfi2hvtIBsET5u9GizXE6/GFSuKCTNfgCswuEjRg==", + "node_modules/@aws-sdk/middleware-signing": { + "version": "3.556.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-signing/-/middleware-signing-3.556.0.tgz", + "integrity": "sha512-kWrPmU8qd3gI5qzpuW9LtWFaH80cOz1ZJDavXx6PRpYZJ5JaKdUHghwfDlVTzzFYAeJmVsWIkPcLT5d5mY5ZTQ==", "dev": true, "dependencies": { - "@babel/code-frame": "^7.23.5", - "@babel/generator": "^7.23.6", - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-function-name": "^7.23.0", - "@babel/helper-hoist-variables": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/parser": "^7.23.9", - "@babel/types": "^7.23.9", - "debug": "^4.3.1", - "globals": "^11.1.0" + "@aws-sdk/types": "3.535.0", + "@smithy/property-provider": "^2.2.0", + "@smithy/protocol-http": "^3.3.0", + "@smithy/signature-v4": "^2.3.0", + "@smithy/types": "^2.12.0", + "@smithy/util-middleware": "^2.2.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=6.9.0" + "node": ">=14.0.0" } }, - "node_modules/@babel/traverse/node_modules/globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "node_modules/@aws-sdk/middleware-ssec": { + "version": "3.537.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-ssec/-/middleware-ssec-3.537.0.tgz", + "integrity": "sha512-2QWMrbwd5eBy5KCYn9a15JEWBgrK2qFEKQN2lqb/6z0bhtevIOxIRfC99tzvRuPt6nixFQ+ynKuBjcfT4ZFrdQ==", "dev": true, + "dependencies": { + "@aws-sdk/types": "3.535.0", + "@smithy/types": "^2.12.0", + "tslib": "^2.6.2" + }, "engines": { - "node": ">=4" + "node": ">=14.0.0" } }, - "node_modules/@babel/types": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.9.tgz", - "integrity": "sha512-dQjSq/7HaSjRM43FFGnv5keM2HsxpmyV1PfaSVm0nzzjwwTmjOe6J4bC8e3+pTEIgHaHj+1ZlLThRJ2auc/w1Q==", + "node_modules/@aws-sdk/middleware-user-agent": { + "version": "3.540.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.540.0.tgz", + "integrity": "sha512-8Rd6wPeXDnOYzWj1XCmOKcx/Q87L0K1/EHqOBocGjLVbN3gmRxBvpmR1pRTjf7IsWfnnzN5btqtcAkfDPYQUMQ==", "dev": true, "dependencies": { - "@babel/helper-string-parser": "^7.23.4", - "@babel/helper-validator-identifier": "^7.22.20", - "to-fast-properties": "^2.0.0" + "@aws-sdk/types": "3.535.0", + "@aws-sdk/util-endpoints": "3.540.0", + "@smithy/protocol-http": "^3.3.0", + "@smithy/types": "^2.12.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=6.9.0" + "node": ">=14.0.0" } }, - "node_modules/@bcoe/v8-coverage": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", - "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", - "dev": true - }, - "node_modules/@colors/colors": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.6.0.tgz", - "integrity": "sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA==", + "node_modules/@aws-sdk/region-config-resolver": { + "version": "3.535.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/region-config-resolver/-/region-config-resolver-3.535.0.tgz", + "integrity": "sha512-IXOznDiaItBjsQy4Fil0kzX/J3HxIOknEphqHbOfUf+LpA5ugcsxuQQONrbEQusCBnfJyymrldBvBhFmtlU9Wg==", + "dev": true, + "dependencies": { + "@aws-sdk/types": "3.535.0", + "@smithy/node-config-provider": "^2.3.0", + "@smithy/types": "^2.12.0", + "@smithy/util-config-provider": "^2.3.0", + "@smithy/util-middleware": "^2.2.0", + "tslib": "^2.6.2" + }, "engines": { - "node": ">=0.1.90" + "node": ">=14.0.0" } }, - "node_modules/@contrast/fn-inspect": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/@contrast/fn-inspect/-/fn-inspect-3.4.0.tgz", - "integrity": "sha512-Jw6dMFEIt/FXF1ihJri2GFNayeEKQ6r+WRjjWl7MdgMup2D4vCPu99ZV8eHSMqNNkj3BEzUNC91ZaJVB1XJmfg==", - "hasInstallScript": true, - "optional": true, + "node_modules/@aws-sdk/s3-request-presigner": { + "version": "3.556.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/s3-request-presigner/-/s3-request-presigner-3.556.0.tgz", + "integrity": "sha512-uVUZn0TlAFaObePEYT4sdM+6QeuaTzOK96w0CbzQs1F3mYVag1r7tZal3BBRfcGNo6WEbZTgd0EXD1q9g0WuwA==", + "dev": true, "dependencies": { - "nan": "^2.17.0", - "node-gyp-build": "^4.6.0" + "@aws-sdk/signature-v4-multi-region": "3.556.0", + "@aws-sdk/types": "3.535.0", + "@aws-sdk/util-format-url": "3.535.0", + "@smithy/middleware-endpoint": "^2.5.1", + "@smithy/protocol-http": "^3.3.0", + "@smithy/smithy-client": "^2.5.1", + "@smithy/types": "^2.12.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=12.13.0" + "node": ">=14.0.0" } }, - "node_modules/@es-joy/jsdoccomment": { - "version": "0.42.0", - "resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.42.0.tgz", - "integrity": "sha512-R1w57YlVA6+YE01wch3GPYn6bCsrOV3YW/5oGGE2tmX6JcL9Nr+b5IikrjMPF+v9CV3ay+obImEdsDhovhJrzw==", + "node_modules/@aws-sdk/signature-v4-multi-region": { + "version": "3.556.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.556.0.tgz", + "integrity": "sha512-bWDSK0ggK7QzAOmPZGv29UAIZocL1MNY7XyOvm3P3P1U3tFMoIBilQQBLabXyHoZ9J3Ik0Vv4n95htUhRQ35ow==", "dev": true, "dependencies": { - "comment-parser": "1.4.1", - "esquery": "^1.5.0", - "jsdoc-type-pratt-parser": "~4.0.0" + "@aws-sdk/middleware-sdk-s3": "3.556.0", + "@aws-sdk/types": "3.535.0", + "@smithy/protocol-http": "^3.3.0", + "@smithy/signature-v4": "^2.3.0", + "@smithy/types": "^2.12.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=16" + "node": ">=14.0.0" } }, - "node_modules/@eslint-community/eslint-utils": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", - "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "node_modules/@aws-sdk/token-providers": { + "version": "3.556.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.556.0.tgz", + "integrity": "sha512-tvIiugNF0/+2wfuImMrpKjXMx4nCnFWQjQvouObny+wrif/PGqqQYrybwxPJDvzbd965bu1I+QuSv85/ug7xsg==", "dev": true, "dependencies": { - "eslint-visitor-keys": "^3.3.0" + "@aws-sdk/client-sso-oidc": "3.556.0", + "@aws-sdk/types": "3.535.0", + "@smithy/property-provider": "^2.2.0", + "@smithy/shared-ini-file-loader": "^2.4.0", + "@smithy/types": "^2.12.0", + "tslib": "^2.6.2" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + "node": ">=14.0.0" } }, - "node_modules/@eslint-community/regexpp": { - "version": "4.10.0", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz", - "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==", + "node_modules/@aws-sdk/types": { + "version": "3.535.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.535.0.tgz", + "integrity": "sha512-aY4MYfduNj+sRR37U7XxYR8wemfbKP6lx00ze2M2uubn7mZotuVrWYAafbMSXrdEMSToE5JDhr28vArSOoLcSg==", "dev": true, + "dependencies": { + "@smithy/types": "^2.12.0", + "tslib": "^2.6.2" + }, "engines": { - "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + "node": ">=14.0.0" } }, - "node_modules/@eslint/eslintrc": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", - "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "node_modules/@aws-sdk/util-arn-parser": { + "version": "3.535.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-arn-parser/-/util-arn-parser-3.535.0.tgz", + "integrity": "sha512-smVo29nUPAOprp8Z5Y3GHuhiOtw6c8/EtLCm5AVMtRsTPw4V414ZXL2H66tzmb5kEeSzQlbfBSBEdIFZoxO9kg==", "dev": true, "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.6.0", - "globals": "^13.19.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" + "tslib": "^2.6.2" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" + "node": ">=14.0.0" } }, - "node_modules/@eslint/js": { - "version": "8.56.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.56.0.tgz", - "integrity": "sha512-gMsVel9D7f2HLkBma9VbtzZRehRogVRfbr++f06nL2vnCGCNlzOD+/MUov/F4p8myyAHspEhVobgjpX64q5m6A==", + "node_modules/@aws-sdk/util-endpoints": { + "version": "3.540.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.540.0.tgz", + "integrity": "sha512-1kMyQFAWx6f8alaI6UT65/5YW/7pDWAKAdNwL6vuJLea03KrZRX3PMoONOSJpAS5m3Ot7HlWZvf3wZDNTLELZw==", "dev": true, + "dependencies": { + "@aws-sdk/types": "3.535.0", + "@smithy/types": "^2.12.0", + "@smithy/util-endpoints": "^1.2.0", + "tslib": "^2.6.2" + }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": ">=14.0.0" } }, - "node_modules/@grpc/grpc-js": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.10.0.tgz", - "integrity": "sha512-tx+eoEsqkMkLCHR4OOplwNIaJ7SVZWzeVKzEMBz8VR+TbssgBYOP4a0P+KQiQ6LaTG4SGaIEu7YTS8xOmkOWLA==", + "node_modules/@aws-sdk/util-format-url": { + "version": "3.535.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-format-url/-/util-format-url-3.535.0.tgz", + "integrity": "sha512-ElbNkm0bddu53CuW44Iuux1ZbTV50fydbSh/4ypW3LrmUvHx193ogj0HXQ7X26kmmo9rXcsrLdM92yIeTjidVg==", + "dev": true, "dependencies": { - "@grpc/proto-loader": "^0.7.8", - "@types/node": ">=12.12.47" + "@aws-sdk/types": "3.535.0", + "@smithy/querystring-builder": "^2.2.0", + "@smithy/types": "^2.12.0", + "tslib": "^2.6.2" }, "engines": { - "node": "^8.13.0 || >=10.10.0" + "node": ">=14.0.0" } }, - "node_modules/@grpc/proto-loader": { - "version": "0.7.10", - "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.7.10.tgz", - "integrity": "sha512-CAqDfoaQ8ykFd9zqBDn4k6iWT9loLAlc2ETmDFS9JCD70gDcnA4L3AFEo2iV7KyAtAAHFW9ftq1Fz+Vsgq80RQ==", + "node_modules/@aws-sdk/util-locate-window": { + "version": "3.535.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-locate-window/-/util-locate-window-3.535.0.tgz", + "integrity": "sha512-PHJ3SL6d2jpcgbqdgiPxkXpu7Drc2PYViwxSIqvvMKhDwzSB1W3mMvtpzwKM4IE7zLFodZo0GKjJ9AsoXndXhA==", + "dev": true, "dependencies": { - "lodash.camelcase": "^4.3.0", - "long": "^5.0.0", - "protobufjs": "^7.2.4", - "yargs": "^17.7.2" - }, - "bin": { - "proto-loader-gen-types": "build/bin/proto-loader-gen-types.js" + "tslib": "^2.6.2" }, "engines": { - "node": ">=6" + "node": ">=14.0.0" } }, - "node_modules/@humanwhocodes/config-array": { - "version": "0.11.14", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", - "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", + "node_modules/@aws-sdk/util-user-agent-browser": { + "version": "3.535.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.535.0.tgz", + "integrity": "sha512-RWMcF/xV5n+nhaA/Ff5P3yNP3Kur/I+VNZngog4TEs92oB/nwOdAg/2JL8bVAhUbMrjTjpwm7PItziYFQoqyig==", "dev": true, "dependencies": { - "@humanwhocodes/object-schema": "^2.0.2", - "debug": "^4.3.1", - "minimatch": "^3.0.5" - }, - "engines": { - "node": ">=10.10.0" + "@aws-sdk/types": "3.535.0", + "@smithy/types": "^2.12.0", + "bowser": "^2.11.0", + "tslib": "^2.6.2" } }, - "node_modules/@humanwhocodes/module-importer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", - "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "node_modules/@aws-sdk/util-user-agent-node": { + "version": "3.535.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.535.0.tgz", + "integrity": "sha512-dRek0zUuIT25wOWJlsRm97nTkUlh1NDcLsQZIN2Y8KxhwoXXWtJs5vaDPT+qAg+OpcNj80i1zLR/CirqlFg/TQ==", "dev": true, + "dependencies": { + "@aws-sdk/types": "3.535.0", + "@smithy/node-config-provider": "^2.3.0", + "@smithy/types": "^2.12.0", + "tslib": "^2.6.2" + }, "engines": { - "node": ">=12.22" + "node": ">=14.0.0" }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" + "peerDependencies": { + "aws-crt": ">=1.0.0" + }, + "peerDependenciesMeta": { + "aws-crt": { + "optional": true + } } }, - "node_modules/@humanwhocodes/object-schema": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.2.tgz", - "integrity": "sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==", - "dev": true - }, - "node_modules/@istanbuljs/load-nyc-config": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", - "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", + "node_modules/@aws-sdk/util-utf8-browser": { + "version": "3.259.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-utf8-browser/-/util-utf8-browser-3.259.0.tgz", + "integrity": "sha512-UvFa/vR+e19XookZF8RzFZBrw2EUkQWxiBW0yYQAhvk3C+QVGl0H3ouca8LDBlBfQKXwmW3huo/59H8rwb1wJw==", "dev": true, "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" - }, - "engines": { - "node": ">=8" + "tslib": "^2.3.1" } }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "node_modules/@aws-sdk/xml-builder": { + "version": "3.535.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/xml-builder/-/xml-builder-3.535.0.tgz", + "integrity": "sha512-VXAq/Jz8KIrU84+HqsOJhIKZqG0PNTdi6n6PFQ4xJf44ZQHD/5C7ouH4qCFX5XgZXcgbRIcMVVYGC6Jye0dRng==", "dev": true, "dependencies": { - "sprintf-js": "~1.0.2" + "@smithy/types": "^2.12.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" } }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "node_modules/@babel/code-frame": { + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz", + "integrity": "sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==", "dev": true, "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" + "@babel/highlight": "^7.23.4", + "chalk": "^2.4.2" }, "engines": { - "node": ">=8" + "node": ">=6.9.0" } }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "node_modules/@babel/compat-data": { + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.23.5.tgz", + "integrity": "sha512-uU27kfDRlhfKl+w1U6vp16IuvSLtjAxdArVXPa9BvLkrr7CYIsxH5adpHObeAGY/41+syctUWOZ140a2Rvkgjw==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.23.9", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.9.tgz", + "integrity": "sha512-5q0175NOjddqpvvzU+kDiSOAk4PfdO6FvwCWoQ6RO7rTzEe8vlo+4HVfcnAREhD4npMs0e9uZypjTwzZPCf/cw==", "dev": true, "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.23.5", + "@babel/generator": "^7.23.6", + "@babel/helper-compilation-targets": "^7.23.6", + "@babel/helper-module-transforms": "^7.23.3", + "@babel/helpers": "^7.23.9", + "@babel/parser": "^7.23.9", + "@babel/template": "^7.23.9", + "@babel/traverse": "^7.23.9", + "@babel/types": "^7.23.9", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/core/node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true + }, + "node_modules/@babel/core/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, "bin": { - "js-yaml": "bin/js-yaml.js" + "semver": "bin/semver.js" } }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "node_modules/@babel/generator": { + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.6.tgz", + "integrity": "sha512-qrSfCYxYQB5owCmGLbl8XRpX1ytXlpueOb0N0UmQwA073KZxejgQTzAmJezxvpwQD9uGtK2shHdi55QT+MbjIw==", "dev": true, "dependencies": { - "p-locate": "^4.1.0" + "@babel/types": "^7.23.6", + "@jridgewell/gen-mapping": "^0.3.2", + "@jridgewell/trace-mapping": "^0.3.17", + "jsesc": "^2.5.1" }, "engines": { - "node": ">=8" + "node": ">=6.9.0" } }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "node_modules/@babel/helper-compilation-targets": { + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.23.6.tgz", + "integrity": "sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ==", "dev": true, "dependencies": { - "p-try": "^2.0.0" + "@babel/compat-data": "^7.23.5", + "@babel/helper-validator-option": "^7.23.5", + "browserslist": "^4.22.2", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" }, "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=6.9.0" } }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "node_modules/@babel/helper-compilation-targets/node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", "dev": true, "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" + "yallist": "^3.0.2" } }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "node_modules/@babel/helper-compilation-targets/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, - "engines": { - "node": ">=8" + "bin": { + "semver": "bin/semver.js" } }, - "node_modules/@istanbuljs/schema": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", - "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", + "node_modules/@babel/helper-compilation-targets/node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + }, + "node_modules/@babel/helper-environment-visitor": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", + "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", "dev": true, "engines": { - "node": ">=8" + "node": ">=6.9.0" } }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", - "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", + "node_modules/@babel/helper-function-name": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", + "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", "dev": true, "dependencies": { - "@jridgewell/set-array": "^1.0.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" + "@babel/template": "^7.22.15", + "@babel/types": "^7.23.0" }, "engines": { - "node": ">=6.0.0" + "node": ">=6.9.0" } }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", - "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==", + "node_modules/@babel/helper-hoist-variables": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", + "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", "dev": true, + "dependencies": { + "@babel/types": "^7.22.5" + }, "engines": { - "node": ">=6.0.0" + "node": ">=6.9.0" } }, - "node_modules/@jridgewell/set-array": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "node_modules/@babel/helper-module-imports": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz", + "integrity": "sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==", "dev": true, + "dependencies": { + "@babel/types": "^7.22.15" + }, "engines": { - "node": ">=6.0.0" + "node": ">=6.9.0" } }, - "node_modules/@jridgewell/source-map": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.5.tgz", - "integrity": "sha512-UTYAUj/wviwdsMfzoSJspJxbkH5o1snzwX0//0ENX1u/55kkZZkcTZP6u9bwKGkv+dkk9at4m1Cpt0uY80kcpQ==", + "node_modules/@babel/helper-module-transforms": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.3.tgz", + "integrity": "sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ==", "dev": true, "dependencies": { - "@jridgewell/gen-mapping": "^0.3.0", - "@jridgewell/trace-mapping": "^0.3.9" + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-module-imports": "^7.22.15", + "@babel/helper-simple-access": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/helper-validator-identifier": "^7.22.20" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.15", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", - "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", - "dev": true - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.22", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.22.tgz", - "integrity": "sha512-Wf963MzWtA2sjrNt+g18IAln9lKnlRp+K2eH4jjIoF1wYeq3aMREpG09xhlhdzS0EjwU7qmUJYangWa+151vZw==", + "node_modules/@babel/helper-simple-access": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz", + "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==", "dev": true, "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" } }, - "node_modules/@jsdoc/salty": { - "version": "0.2.7", - "resolved": "https://registry.npmjs.org/@jsdoc/salty/-/salty-0.2.7.tgz", - "integrity": "sha512-mh8LbS9d4Jq84KLw8pzho7XC2q2/IJGiJss3xwRoLD1A+EE16SjN4PfaG4jRCzKegTFLlN0Zd8SdUPE6XdoPFg==", + "node_modules/@babel/helper-split-export-declaration": { + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", + "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", "dev": true, "dependencies": { - "lodash": "^4.17.21" + "@babel/types": "^7.22.5" }, "engines": { - "node": ">=v12.0.0" + "node": ">=6.9.0" } }, - "node_modules/@koa/router": { - "version": "12.0.1", - "resolved": "https://registry.npmjs.org/@koa/router/-/router-12.0.1.tgz", - "integrity": "sha512-ribfPYfHb+Uw3b27Eiw6NPqjhIhTpVFzEWLwyc/1Xp+DCdwRRyIlAUODX+9bPARF6aQtUu1+/PHzdNvRzcs/+Q==", + "node_modules/@babel/helper-string-parser": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz", + "integrity": "sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==", "dev": true, - "dependencies": { - "debug": "^4.3.4", - "http-errors": "^2.0.0", - "koa-compose": "^4.1.0", - "methods": "^1.1.2", - "path-to-regexp": "^6.2.1" - }, "engines": { - "node": ">= 12" + "node": ">=6.9.0" } }, - "node_modules/@newrelic/aws-sdk": { - "version": "7.3.0", - "resolved": "https://registry.npmjs.org/@newrelic/aws-sdk/-/aws-sdk-7.3.0.tgz", - "integrity": "sha512-6HBrd9SlHPeFI2MPH9s3KQUwJnuehHgn0boAtoGloiNL+dm6XbuTiNV1Deo1P2qspsCsf/luBvxM5b37MiGqVg==", + "node_modules/@babel/helper-validator-identifier": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", + "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", + "dev": true, "engines": { - "node": ">=16.0.0" + "node": ">=6.9.0" } }, - "node_modules/@newrelic/eslint-config": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@newrelic/eslint-config/-/eslint-config-0.3.0.tgz", - "integrity": "sha512-woQshi/SB6uGrXPWb4w9G98HkQRCb9nJWfJ9/tlj0WkVOqU4Bsn4VZvEI63Vy5y1cTphajr4u6kjOzIk0kC6DA==", + "node_modules/@babel/helper-validator-option": { + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz", + "integrity": "sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==", "dev": true, "engines": { - "node": ">=12" - }, - "peerDependencies": { - "eslint": "^8.24.0", - "eslint-config-prettier": "^8.3.0", - "eslint-plugin-header": "^3.1.1", - "eslint-plugin-node": "^11.1.0", - "eslint-plugin-prettier": "^3.4.0", - "eslint-plugin-sonarjs": "^0.18.0", - "prettier": "^2.3.2" + "node": ">=6.9.0" } }, - "node_modules/@newrelic/native-metrics": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/@newrelic/native-metrics/-/native-metrics-10.0.1.tgz", - "integrity": "sha512-XJlKF3mCiFS/tZj6C79gdRYj+vQQtFSxbL83MMOVK/N025UHk8Oo8lF1ir7GOWk+Ll2xH4WI/t7i9SqDouXX+g==", - "hasInstallScript": true, - "optional": true, + "node_modules/@babel/helpers": { + "version": "7.23.9", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.23.9.tgz", + "integrity": "sha512-87ICKgU5t5SzOT7sBMfCOZQ2rHjRU+Pcb9BoILMYz600W6DkVRLFBPwQ18gwUVvggqXivaUakpnxWQGbpywbBQ==", + "dev": true, "dependencies": { - "https-proxy-agent": "^5.0.1", - "nan": "^2.17.0", - "semver": "^7.5.2" + "@babel/template": "^7.23.9", + "@babel/traverse": "^7.23.9", + "@babel/types": "^7.23.9" }, "engines": { - "node": ">=16", - "npm": ">=6" + "node": ">=6.9.0" } }, - "node_modules/@newrelic/native-metrics/node_modules/agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "optional": true, + "node_modules/@babel/highlight": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.23.4.tgz", + "integrity": "sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==", + "dev": true, "dependencies": { - "debug": "4" + "@babel/helper-validator-identifier": "^7.22.20", + "chalk": "^2.4.2", + "js-tokens": "^4.0.0" }, "engines": { - "node": ">= 6.0.0" + "node": ">=6.9.0" } }, - "node_modules/@newrelic/native-metrics/node_modules/https-proxy-agent": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", - "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", - "optional": true, - "dependencies": { - "agent-base": "6", - "debug": "4" + "node_modules/@babel/parser": { + "version": "7.23.9", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.9.tgz", + "integrity": "sha512-9tcKgqKbs3xGJ+NtKF2ndOBBLVwPjl1SHxPQkd36r3Dlirw3xWUeGaTbqr7uGZcTaxkVNwc+03SVP7aCdWrTlA==", + "dev": true, + "bin": { + "parser": "bin/babel-parser.js" }, "engines": { - "node": ">= 6" + "node": ">=6.0.0" } }, - "node_modules/@newrelic/newrelic-oss-cli": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/@newrelic/newrelic-oss-cli/-/newrelic-oss-cli-0.1.2.tgz", - "integrity": "sha512-KXogVuMOjBKNiyReP79CTrfJQ4CYT72xpB5vm0UzF4dnZFpNRhyX1EosG7X47HhRfuvawySl4F8j7ZUnvUVQfQ==", + "node_modules/@babel/template": { + "version": "7.23.9", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.23.9.tgz", + "integrity": "sha512-+xrD2BWLpvHKNmX2QbpdpsBaWnRxahMwJjO+KZk2JOElj5nSmKezyS1B4u+QbHMTX69t4ukm6hh9lsYQ7GHCKA==", "dev": true, "dependencies": { - "@newrelic/newrelic-plugin-oss-third-party": "^0.1.2", - "@oclif/command": "^1.5.15", - "@oclif/config": "^1.13.0", - "@oclif/plugin-autocomplete": "^0.1.0", - "@oclif/plugin-commands": "^1.2.3", - "@oclif/plugin-help": "^2.2.0", - "@oclif/plugin-not-found": "^1.2.2", - "@oclif/plugin-plugins": "^1.7.9", - "@oclif/plugin-update": "^1.3.9", - "@oclif/plugin-warn-if-update-available": "^1.7.0", - "@oclif/plugin-which": "^1.0.3" - }, - "bin": { - "oss": "bin/run" + "@babel/code-frame": "^7.23.5", + "@babel/parser": "^7.23.9", + "@babel/types": "^7.23.9" }, "engines": { - "node": ">=10.0.0" + "node": ">=6.9.0" } }, - "node_modules/@newrelic/newrelic-plugin-oss-third-party": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/@newrelic/newrelic-plugin-oss-third-party/-/newrelic-plugin-oss-third-party-0.1.2.tgz", - "integrity": "sha512-MOeRggT4YtjFCnnkY9/7dSI9GFaZ71kkd21l0qDolTA5H+vLyBK7pUGJbKdLAIMcK/QHASopkvzjmO8qvUootg==", + "node_modules/@babel/traverse": { + "version": "7.23.9", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.9.tgz", + "integrity": "sha512-I/4UJ9vs90OkBtY6iiiTORVMyIhJ4kAVmsKo9KFc8UOxMeUfi2hvtIBsET5u9GizXE6/GFSuKCTNfgCswuEjRg==", "dev": true, "dependencies": { - "@oclif/command": "^1.5.19", - "@oclif/config": "^1.13.3", - "chalk": "^2.4.2", - "fs-extra": "^8.1.0", - "license-checker": "^25.0.1", - "spdx-license-list": "^6.1.0" + "@babel/code-frame": "^7.23.5", + "@babel/generator": "^7.23.6", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-function-name": "^7.23.0", + "@babel/helper-hoist-variables": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/parser": "^7.23.9", + "@babel/types": "^7.23.9", + "debug": "^4.3.1", + "globals": "^11.1.0" }, "engines": { - "node": ">=8.0.0" + "node": ">=6.9.0" } }, - "node_modules/@newrelic/ritm": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@newrelic/ritm/-/ritm-7.2.0.tgz", - "integrity": "sha512-I4iVhm+wlTEDJXQT8EydF/U5vlR9bBHrtBGyvd/D9WCucoMtrPrCNyILQh9bZ+46E8QRE7zh6QEGyQcnc3qNMg==", + "node_modules/@babel/traverse/node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/types": { + "version": "7.23.9", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.9.tgz", + "integrity": "sha512-dQjSq/7HaSjRM43FFGnv5keM2HsxpmyV1PfaSVm0nzzjwwTmjOe6J4bC8e3+pTEIgHaHj+1ZlLThRJ2auc/w1Q==", + "dev": true, "dependencies": { - "debug": "^4.1.1", - "module-details-from-path": "^1.0.3", - "resolve": "^1.22.1" + "@babel/helper-string-parser": "^7.23.4", + "@babel/helper-validator-identifier": "^7.22.20", + "to-fast-properties": "^2.0.0" }, "engines": { - "node": ">=8.6.0" + "node": ">=6.9.0" } }, - "node_modules/@newrelic/security-agent": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@newrelic/security-agent/-/security-agent-1.1.1.tgz", - "integrity": "sha512-HGeKOPGKIr27vjTpW3j+tRLPT0HmGOIjcnyvgGZyXJXampCY3g79mpvcM5B6DcTAU5qI/LeZq1q+jLmtGHz+AA==", + "node_modules/@bcoe/v8-coverage": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", + "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", + "dev": true + }, + "node_modules/@colors/colors": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.6.0.tgz", + "integrity": "sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA==", + "engines": { + "node": ">=0.1.90" + } + }, + "node_modules/@contrast/fn-inspect": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@contrast/fn-inspect/-/fn-inspect-3.4.0.tgz", + "integrity": "sha512-Jw6dMFEIt/FXF1ihJri2GFNayeEKQ6r+WRjjWl7MdgMup2D4vCPu99ZV8eHSMqNNkj3BEzUNC91ZaJVB1XJmfg==", + "hasInstallScript": true, + "optional": true, "dependencies": { - "axios": "^1.6.8", - "check-disk-space": "^3.4.0", - "content-type": "^1.0.5", - "fast-safe-stringify": "^2.1.1", - "find-package-json": "^1.2.0", - "hash.js": "^1.1.7", - "html-entities": "^2.3.6", - "is-invalid-path": "^1.0.2", - "js-yaml": "^4.1.0", - "jsonschema": "^1.4.1", - "lodash": "^4.17.21", - "log4js": "^6.9.1", - "pretty-bytes": "^5.6.0", - "request-ip": "^3.3.0", - "ringbufferjs": "^2.0.0", - "semver": "^7.5.4", - "sync-request": "^6.1.0", - "unescape": "^1.0.1", - "unescape-js": "^1.1.4", - "uuid": "^9.0.1", - "ws": "^8.14.2" + "nan": "^2.17.0", + "node-gyp-build": "^4.6.0" + }, + "engines": { + "node": ">=12.13.0" } }, - "node_modules/@newrelic/test-utilities": { - "version": "8.5.0", - "resolved": "https://registry.npmjs.org/@newrelic/test-utilities/-/test-utilities-8.5.0.tgz", - "integrity": "sha512-lrdcoJiolBRhhuT7cd0YUN23zsF2WX0kUfmfA8+IGU+9T0witbkLC4AUnaaM9/OQx5qyZveaw5TFQl3XUSHTBg==", + "node_modules/@es-joy/jsdoccomment": { + "version": "0.42.0", + "resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.42.0.tgz", + "integrity": "sha512-R1w57YlVA6+YE01wch3GPYn6bCsrOV3YW/5oGGE2tmX6JcL9Nr+b5IikrjMPF+v9CV3ay+obImEdsDhovhJrzw==", "dev": true, "dependencies": { - "@smithy/eventstream-codec": "^2.1.1", - "@smithy/util-utf8": "^2.1.1", - "async": "^3.2.3", - "colors": "^1.1.2", - "commander": "^2.14.1", - "concat-stream": "^1.6.0", - "glob": "^7.2.3", - "lodash": "^4.17.5", - "log-update": "^1.0.2", - "semver": "^7.5.2" - }, - "bin": { - "versioned-tests": "bin/version-manager.js" + "comment-parser": "1.4.1", + "esquery": "^1.5.0", + "jsdoc-type-pratt-parser": "~4.0.0" }, "engines": { - "node": ">=16.0" + "node": ">=16" } }, - "node_modules/@newrelic/test-utilities/node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true - }, - "node_modules/@newrelic/test-utilities/node_modules/concat-stream": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", - "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "node_modules/@eslint-community/eslint-utils": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", "dev": true, - "engines": [ - "node >= 0.8" - ], "dependencies": { - "buffer-from": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^2.2.2", - "typedarray": "^0.0.6" + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, - "node_modules/@newrelic/test-utilities/node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", - "dev": true - }, - "node_modules/@newrelic/test-utilities/node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "node_modules/@eslint-community/regexpp": { + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz", + "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==", "dev": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } }, - "node_modules/@newrelic/test-utilities/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "node_modules/@newrelic/test-utilities/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "node_modules/@eslint/eslintrc": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", "dev": true, "dependencies": { - "safe-buffer": "~5.1.0" + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "node_modules/@eslint/js": { + "version": "8.56.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.56.0.tgz", + "integrity": "sha512-gMsVel9D7f2HLkBma9VbtzZRehRogVRfbr++f06nL2vnCGCNlzOD+/MUov/F4p8myyAHspEhVobgjpX64q5m6A==", "dev": true, - "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - }, "engines": { - "node": ">= 8" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true, + "node_modules/@grpc/grpc-js": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.10.0.tgz", + "integrity": "sha512-tx+eoEsqkMkLCHR4OOplwNIaJ7SVZWzeVKzEMBz8VR+TbssgBYOP4a0P+KQiQ6LaTG4SGaIEu7YTS8xOmkOWLA==", + "dependencies": { + "@grpc/proto-loader": "^0.7.8", + "@types/node": ">=12.12.47" + }, "engines": { - "node": ">= 8" + "node": "^8.13.0 || >=10.10.0" } }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dev": true, + "node_modules/@grpc/proto-loader": { + "version": "0.7.10", + "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.7.10.tgz", + "integrity": "sha512-CAqDfoaQ8ykFd9zqBDn4k6iWT9loLAlc2ETmDFS9JCD70gDcnA4L3AFEo2iV7KyAtAAHFW9ftq1Fz+Vsgq80RQ==", "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" + "lodash.camelcase": "^4.3.0", + "long": "^5.0.0", + "protobufjs": "^7.2.4", + "yargs": "^17.7.2" + }, + "bin": { + "proto-loader-gen-types": "build/bin/proto-loader-gen-types.js" }, "engines": { - "node": ">= 8" + "node": ">=6" } }, - "node_modules/@oclif/color": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/@oclif/color/-/color-0.1.2.tgz", - "integrity": "sha512-M9o+DOrb8l603qvgz1FogJBUGLqcMFL1aFg2ZEL0FbXJofiNTLOWIeB4faeZTLwE6dt0xH9GpCVpzksMMzGbmA==", - "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", + "node_modules/@humanwhocodes/config-array": { + "version": "0.11.14", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", + "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", "dev": true, "dependencies": { - "ansi-styles": "^3.2.1", - "chalk": "^3.0.0", - "strip-ansi": "^5.2.0", - "supports-color": "^5.4.0", - "tslib": "^1" + "@humanwhocodes/object-schema": "^2.0.2", + "debug": "^4.3.1", + "minimatch": "^3.0.5" }, "engines": { - "node": ">=8.0.0" + "node": ">=10.10.0" } }, - "node_modules/@oclif/color/node_modules/ansi-regex": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", - "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", "dev": true, "engines": { - "node": ">=6" + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" } }, - "node_modules/@oclif/color/node_modules/chalk": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", - "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "node_modules/@humanwhocodes/object-schema": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.2.tgz", + "integrity": "sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==", + "dev": true + }, + "node_modules/@istanbuljs/load-nyc-config": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", + "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", "dev": true, "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "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" }, "engines": { "node": ">=8" } }, - "node_modules/@oclif/color/node_modules/chalk/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "node_modules/@istanbuljs/load-nyc-config/node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", "dev": true, "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "sprintf-js": "~1.0.2" } }, - "node_modules/@oclif/color/node_modules/chalk/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "node_modules/@istanbuljs/load-nyc-config/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "dev": true, "dependencies": { - "has-flag": "^4.0.0" + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" }, "engines": { "node": ">=8" } }, - "node_modules/@oclif/color/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "node_modules/@istanbuljs/load-nyc-config/node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", "dev": true, "dependencies": { - "color-name": "~1.1.4" + "argparse": "^1.0.7", + "esprima": "^4.0.0" }, - "engines": { - "node": ">=7.0.0" + "bin": { + "js-yaml": "bin/js-yaml.js" } }, - "node_modules/@oclif/color/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/@oclif/color/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "node_modules/@istanbuljs/load-nyc-config/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", "dev": true, + "dependencies": { + "p-locate": "^4.1.0" + }, "engines": { "node": ">=8" } }, - "node_modules/@oclif/color/node_modules/strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "node_modules/@istanbuljs/load-nyc-config/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "dev": true, "dependencies": { - "ansi-regex": "^4.1.0" + "p-try": "^2.0.0" }, "engines": { "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@oclif/color/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - }, - "node_modules/@oclif/command": { - "version": "1.8.36", - "resolved": "https://registry.npmjs.org/@oclif/command/-/command-1.8.36.tgz", - "integrity": "sha512-/zACSgaYGtAQRzc7HjzrlIs14FuEYAZrMOEwicRoUnZVyRunG4+t5iSEeQu0Xy2bgbCD0U1SP/EdeNZSTXRwjQ==", - "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", - "dev": true, - "dependencies": { - "@oclif/config": "^1.18.2", - "@oclif/errors": "^1.3.6", - "@oclif/help": "^1.0.1", - "@oclif/parser": "^3.8.17", - "debug": "^4.1.1", - "semver": "^7.5.4" - }, - "engines": { - "node": ">=12.0.0" - }, - "peerDependencies": { - "@oclif/config": "^1" - } - }, - "node_modules/@oclif/config": { - "version": "1.18.17", - "resolved": "https://registry.npmjs.org/@oclif/config/-/config-1.18.17.tgz", - "integrity": "sha512-k77qyeUvjU8qAJ3XK3fr/QVAqsZO8QOBuESnfeM5HHtPNLSyfVcwiMM2zveSW5xRdLSG3MfV8QnLVkuyCL2ENg==", - "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", + "node_modules/@istanbuljs/load-nyc-config/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", "dev": true, "dependencies": { - "@oclif/errors": "^1.3.6", - "@oclif/parser": "^3.8.17", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-wsl": "^2.1.1", - "tslib": "^2.6.1" + "p-limit": "^2.2.0" }, "engines": { - "node": ">=8.0.0" + "node": ">=8" } }, - "node_modules/@oclif/errors": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/@oclif/errors/-/errors-1.3.6.tgz", - "integrity": "sha512-fYaU4aDceETd89KXP+3cLyg9EHZsLD3RxF2IU9yxahhBpspWjkWi3Dy3bTgcwZ3V47BgxQaGapzJWDM33XIVDQ==", - "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", + "node_modules/@istanbuljs/load-nyc-config/node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", "dev": true, - "dependencies": { - "clean-stack": "^3.0.0", - "fs-extra": "^8.1", - "indent-string": "^4.0.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - }, "engines": { - "node": ">=8.0.0" + "node": ">=8" } }, - "node_modules/@oclif/help": { - "version": "1.0.15", - "resolved": "https://registry.npmjs.org/@oclif/help/-/help-1.0.15.tgz", - "integrity": "sha512-Yt8UHoetk/XqohYX76DfdrUYLsPKMc5pgkzsZVHDyBSkLiGRzujVaGZdjr32ckVZU9q3a47IjhWxhip7Dz5W/g==", - "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", + "node_modules/@istanbuljs/schema": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", "dev": true, - "dependencies": { - "@oclif/config": "1.18.16", - "@oclif/errors": "1.3.6", - "chalk": "^4.1.2", - "indent-string": "^4.0.0", - "lodash": "^4.17.21", - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "widest-line": "^3.1.0", - "wrap-ansi": "^6.2.0" - }, "engines": { - "node": ">=8.0.0" + "node": ">=8" } }, - "node_modules/@oclif/help/node_modules/@oclif/config": { - "version": "1.18.16", - "resolved": "https://registry.npmjs.org/@oclif/config/-/config-1.18.16.tgz", - "integrity": "sha512-VskIxVcN22qJzxRUq+raalq6Q3HUde7sokB7/xk5TqRZGEKRVbFeqdQBxDWwQeudiJEgcNiMvIFbMQ43dY37FA==", - "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", + "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", "dev": true, "dependencies": { - "@oclif/errors": "^1.3.6", - "@oclif/parser": "^3.8.16", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-wsl": "^2.1.1", - "tslib": "^2.6.1" + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" }, "engines": { - "node": ">=8.0.0" + "node": ">=6.0.0" } }, - "node_modules/@oclif/help/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", + "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==", "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "node": ">=6.0.0" } }, - "node_modules/@oclif/help/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "node_modules/@jridgewell/set-array": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", + "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "node": ">=6.0.0" } }, - "node_modules/@oclif/help/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "node_modules/@jridgewell/source-map": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.5.tgz", + "integrity": "sha512-UTYAUj/wviwdsMfzoSJspJxbkH5o1snzwX0//0ENX1u/55kkZZkcTZP6u9bwKGkv+dkk9at4m1Cpt0uY80kcpQ==", "dev": true, "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" + "@jridgewell/gen-mapping": "^0.3.0", + "@jridgewell/trace-mapping": "^0.3.9" } }, - "node_modules/@oclif/help/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.15", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", "dev": true }, - "node_modules/@oclif/help/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.22", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.22.tgz", + "integrity": "sha512-Wf963MzWtA2sjrNt+g18IAln9lKnlRp+K2eH4jjIoF1wYeq3aMREpG09xhlhdzS0EjwU7qmUJYangWa+151vZw==", "dev": true, - "engines": { - "node": ">=8" + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" } }, - "node_modules/@oclif/help/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "node_modules/@jsdoc/salty": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/@jsdoc/salty/-/salty-0.2.7.tgz", + "integrity": "sha512-mh8LbS9d4Jq84KLw8pzho7XC2q2/IJGiJss3xwRoLD1A+EE16SjN4PfaG4jRCzKegTFLlN0Zd8SdUPE6XdoPFg==", "dev": true, "dependencies": { - "has-flag": "^4.0.0" + "lodash": "^4.17.21" }, "engines": { - "node": ">=8" + "node": ">=v12.0.0" } }, - "node_modules/@oclif/help/node_modules/wrap-ansi": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", - "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "node_modules/@koa/router": { + "version": "12.0.1", + "resolved": "https://registry.npmjs.org/@koa/router/-/router-12.0.1.tgz", + "integrity": "sha512-ribfPYfHb+Uw3b27Eiw6NPqjhIhTpVFzEWLwyc/1Xp+DCdwRRyIlAUODX+9bPARF6aQtUu1+/PHzdNvRzcs/+Q==", "dev": true, "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" + "debug": "^4.3.4", + "http-errors": "^2.0.0", + "koa-compose": "^4.1.0", + "methods": "^1.1.2", + "path-to-regexp": "^6.2.1" }, "engines": { - "node": ">=8" + "node": ">= 12" } }, - "node_modules/@oclif/linewrap": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@oclif/linewrap/-/linewrap-1.0.0.tgz", - "integrity": "sha512-Ups2dShK52xXa8w6iBWLgcjPJWjais6KPJQq3gQ/88AY6BXoTX+MIGFPrWQO1KLMiQfoTpcLnUwloN4brrVUHw==", - "dev": true - }, - "node_modules/@oclif/parser": { - "version": "3.8.17", - "resolved": "https://registry.npmjs.org/@oclif/parser/-/parser-3.8.17.tgz", - "integrity": "sha512-l04iSd0xoh/16TGVpXb81Gg3z7tlQGrEup16BrVLsZBK6SEYpYHRJZnM32BwZrHI97ZSFfuSwVlzoo6HdsaK8A==", - "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", + "node_modules/@newrelic/eslint-config": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@newrelic/eslint-config/-/eslint-config-0.3.0.tgz", + "integrity": "sha512-woQshi/SB6uGrXPWb4w9G98HkQRCb9nJWfJ9/tlj0WkVOqU4Bsn4VZvEI63Vy5y1cTphajr4u6kjOzIk0kC6DA==", "dev": true, - "dependencies": { - "@oclif/errors": "^1.3.6", - "@oclif/linewrap": "^1.0.0", - "chalk": "^4.1.0", - "tslib": "^2.6.2" - }, "engines": { - "node": ">=8.0.0" + "node": ">=12" + }, + "peerDependencies": { + "eslint": "^8.24.0", + "eslint-config-prettier": "^8.3.0", + "eslint-plugin-header": "^3.1.1", + "eslint-plugin-node": "^11.1.0", + "eslint-plugin-prettier": "^3.4.0", + "eslint-plugin-sonarjs": "^0.18.0", + "prettier": "^2.3.2" } }, - "node_modules/@oclif/parser/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, + "node_modules/@newrelic/native-metrics": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/@newrelic/native-metrics/-/native-metrics-10.0.1.tgz", + "integrity": "sha512-XJlKF3mCiFS/tZj6C79gdRYj+vQQtFSxbL83MMOVK/N025UHk8Oo8lF1ir7GOWk+Ll2xH4WI/t7i9SqDouXX+g==", + "hasInstallScript": true, + "optional": true, "dependencies": { - "color-convert": "^2.0.1" + "https-proxy-agent": "^5.0.1", + "nan": "^2.17.0", + "semver": "^7.5.2" }, "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "node": ">=16", + "npm": ">=6" } }, - "node_modules/@oclif/parser/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, + "node_modules/@newrelic/native-metrics/node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "optional": true, "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "debug": "4" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "node": ">= 6.0.0" } }, - "node_modules/@oclif/parser/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, + "node_modules/@newrelic/native-metrics/node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "optional": true, "dependencies": { - "color-name": "~1.1.4" + "agent-base": "6", + "debug": "4" }, "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/@oclif/parser/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/@oclif/parser/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" + "node": ">= 6" } }, - "node_modules/@oclif/parser/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "node_modules/@newrelic/newrelic-oss-cli": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/@newrelic/newrelic-oss-cli/-/newrelic-oss-cli-0.1.2.tgz", + "integrity": "sha512-KXogVuMOjBKNiyReP79CTrfJQ4CYT72xpB5vm0UzF4dnZFpNRhyX1EosG7X47HhRfuvawySl4F8j7ZUnvUVQfQ==", "dev": true, "dependencies": { - "has-flag": "^4.0.0" + "@newrelic/newrelic-plugin-oss-third-party": "^0.1.2", + "@oclif/command": "^1.5.15", + "@oclif/config": "^1.13.0", + "@oclif/plugin-autocomplete": "^0.1.0", + "@oclif/plugin-commands": "^1.2.3", + "@oclif/plugin-help": "^2.2.0", + "@oclif/plugin-not-found": "^1.2.2", + "@oclif/plugin-plugins": "^1.7.9", + "@oclif/plugin-update": "^1.3.9", + "@oclif/plugin-warn-if-update-available": "^1.7.0", + "@oclif/plugin-which": "^1.0.3" + }, + "bin": { + "oss": "bin/run" }, "engines": { - "node": ">=8" + "node": ">=10.0.0" } }, - "node_modules/@oclif/plugin-autocomplete": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/@oclif/plugin-autocomplete/-/plugin-autocomplete-0.1.5.tgz", - "integrity": "sha512-Afchpdd8FNfx9GaU/1D9IzyfiXvjfGybgzQ6G4GTFvPO0/hLdkXX3YyYq+SnxE6/bCrhg4pleiB+GuJACmmkEA==", + "node_modules/@newrelic/newrelic-plugin-oss-third-party": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/@newrelic/newrelic-plugin-oss-third-party/-/newrelic-plugin-oss-third-party-0.1.2.tgz", + "integrity": "sha512-MOeRggT4YtjFCnnkY9/7dSI9GFaZ71kkd21l0qDolTA5H+vLyBK7pUGJbKdLAIMcK/QHASopkvzjmO8qvUootg==", "dev": true, "dependencies": { - "@oclif/command": "^1.4.31", - "@oclif/config": "^1.6.22", - "chalk": "^2.4.1", - "cli-ux": "^4.4.0", - "debug": "^3.1.0", - "fs-extra": "^6.0.1", - "moment": "^2.22.1" + "@oclif/command": "^1.5.19", + "@oclif/config": "^1.13.3", + "chalk": "^2.4.2", + "fs-extra": "^8.1.0", + "license-checker": "^25.0.1", + "spdx-license-list": "^6.1.0" }, "engines": { "node": ">=8.0.0" } }, - "node_modules/@oclif/plugin-autocomplete/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, + "node_modules/@newrelic/ritm": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@newrelic/ritm/-/ritm-7.2.0.tgz", + "integrity": "sha512-I4iVhm+wlTEDJXQT8EydF/U5vlR9bBHrtBGyvd/D9WCucoMtrPrCNyILQh9bZ+46E8QRE7zh6QEGyQcnc3qNMg==", "dependencies": { - "ms": "^2.1.1" + "debug": "^4.1.1", + "module-details-from-path": "^1.0.3", + "resolve": "^1.22.1" + }, + "engines": { + "node": ">=8.6.0" } }, - "node_modules/@oclif/plugin-autocomplete/node_modules/fs-extra": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-6.0.1.tgz", - "integrity": "sha512-GnyIkKhhzXZUWFCaJzvyDLEEgDkPfb4/TPvJCJVuS8MWZgoSsErf++QpiAlDnKFcqhRlm+tIOcencCjyJE6ZCA==", - "dev": true, + "node_modules/@newrelic/security-agent": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@newrelic/security-agent/-/security-agent-1.1.1.tgz", + "integrity": "sha512-HGeKOPGKIr27vjTpW3j+tRLPT0HmGOIjcnyvgGZyXJXampCY3g79mpvcM5B6DcTAU5qI/LeZq1q+jLmtGHz+AA==", "dependencies": { - "graceful-fs": "^4.1.2", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" + "axios": "^1.6.8", + "check-disk-space": "^3.4.0", + "content-type": "^1.0.5", + "fast-safe-stringify": "^2.1.1", + "find-package-json": "^1.2.0", + "hash.js": "^1.1.7", + "html-entities": "^2.3.6", + "is-invalid-path": "^1.0.2", + "js-yaml": "^4.1.0", + "jsonschema": "^1.4.1", + "lodash": "^4.17.21", + "log4js": "^6.9.1", + "pretty-bytes": "^5.6.0", + "request-ip": "^3.3.0", + "ringbufferjs": "^2.0.0", + "semver": "^7.5.4", + "sync-request": "^6.1.0", + "unescape": "^1.0.1", + "unescape-js": "^1.1.4", + "uuid": "^9.0.1", + "ws": "^8.14.2" } }, - "node_modules/@oclif/plugin-commands": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@oclif/plugin-commands/-/plugin-commands-1.3.0.tgz", - "integrity": "sha512-Qx9gJ7/aPBgo+Q/DHmGcWyxn2/0bjqmCwt/nO0lWuTZQIH3ZTqclTm68TMZLS4QnQyDGeeYK0GqZ5qJlrXD+SQ==", + "node_modules/@newrelic/test-utilities": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@newrelic/test-utilities/-/test-utilities-8.5.0.tgz", + "integrity": "sha512-lrdcoJiolBRhhuT7cd0YUN23zsF2WX0kUfmfA8+IGU+9T0witbkLC4AUnaaM9/OQx5qyZveaw5TFQl3XUSHTBg==", "dev": true, "dependencies": { - "@oclif/command": "^1.5.4", - "@oclif/config": "^1.8.7", - "cli-ux": "^5.4.5", - "lodash": "^4.17.11" + "@smithy/eventstream-codec": "^2.1.1", + "@smithy/util-utf8": "^2.1.1", + "async": "^3.2.3", + "colors": "^1.1.2", + "commander": "^2.14.1", + "concat-stream": "^1.6.0", + "glob": "^7.2.3", + "lodash": "^4.17.5", + "log-update": "^1.0.2", + "semver": "^7.5.2" + }, + "bin": { + "versioned-tests": "bin/version-manager.js" }, "engines": { - "node": ">=8.0.0" + "node": ">=16.0" } }, - "node_modules/@oclif/plugin-commands/node_modules/ansi-escapes": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", - "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "node_modules/@newrelic/test-utilities/node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "node_modules/@newrelic/test-utilities/node_modules/concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", "dev": true, + "engines": [ + "node >= 0.8" + ], "dependencies": { - "type-fest": "^0.21.3" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" } }, - "node_modules/@oclif/plugin-commands/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "node_modules/@newrelic/test-utilities/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true + }, + "node_modules/@newrelic/test-utilities/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", "dev": true, "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" } }, - "node_modules/@oclif/plugin-commands/node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "node_modules/@newrelic/test-utilities/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/@newrelic/test-utilities/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dev": true, "dependencies": { - "sprintf-js": "~1.0.2" + "safe-buffer": "~5.1.0" } }, - "node_modules/@oclif/plugin-commands/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", "dev": true, "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "node": ">= 8" } }, - "node_modules/@oclif/plugin-commands/node_modules/chalk/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, "engines": { - "node": ">=8" + "node": ">= 8" } }, - "node_modules/@oclif/plugin-commands/node_modules/cli-ux": { - "version": "5.6.7", - "resolved": "https://registry.npmjs.org/cli-ux/-/cli-ux-5.6.7.tgz", - "integrity": "sha512-dsKAurMNyFDnO6X1TiiRNiVbL90XReLKcvIq4H777NMqXGBxBws23ag8ubCJE97vVZEgWG2eSUhsyLf63Jv8+g==", - "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", "dev": true, "dependencies": { - "@oclif/command": "^1.8.15", - "@oclif/errors": "^1.3.5", - "@oclif/linewrap": "^1.0.0", - "@oclif/screen": "^1.0.4", - "ansi-escapes": "^4.3.0", - "ansi-styles": "^4.2.0", - "cardinal": "^2.1.1", - "chalk": "^4.1.0", - "clean-stack": "^3.0.0", - "cli-progress": "^3.4.0", - "extract-stack": "^2.0.0", - "fs-extra": "^8.1", - "hyperlinker": "^1.0.0", - "indent-string": "^4.0.0", - "is-wsl": "^2.2.0", - "js-yaml": "^3.13.1", - "lodash": "^4.17.21", - "natural-orderby": "^2.0.1", - "object-treeify": "^1.1.4", - "password-prompt": "^1.1.2", - "semver": "^7.3.2", - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "supports-color": "^8.1.0", - "supports-hyperlinks": "^2.1.0", - "tslib": "^2.0.0" + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" }, "engines": { - "node": ">=8.0.0" + "node": ">= 8" } }, - "node_modules/@oclif/plugin-commands/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "node_modules/@oclif/color": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/@oclif/color/-/color-0.1.2.tgz", + "integrity": "sha512-M9o+DOrb8l603qvgz1FogJBUGLqcMFL1aFg2ZEL0FbXJofiNTLOWIeB4faeZTLwE6dt0xH9GpCVpzksMMzGbmA==", + "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", "dev": true, "dependencies": { - "color-name": "~1.1.4" + "ansi-styles": "^3.2.1", + "chalk": "^3.0.0", + "strip-ansi": "^5.2.0", + "supports-color": "^5.4.0", + "tslib": "^1" }, "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/@oclif/plugin-commands/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/@oclif/plugin-commands/node_modules/extract-stack": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/extract-stack/-/extract-stack-2.0.0.tgz", - "integrity": "sha512-AEo4zm+TenK7zQorGK1f9mJ8L14hnTDi2ZQPR+Mub1NX8zimka1mXpV5LpH8x9HoUmFSHZCfLHqWvp0Y4FxxzQ==", - "dev": true, - "engines": { - "node": ">=8" + "node": ">=8.0.0" } }, - "node_modules/@oclif/plugin-commands/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "node_modules/@oclif/color/node_modules/ansi-regex": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", + "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", "dev": true, "engines": { - "node": ">=8" - } - }, - "node_modules/@oclif/plugin-commands/node_modules/js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", - "dev": true, - "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" + "node": ">=6" } }, - "node_modules/@oclif/plugin-commands/node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "node_modules/@oclif/color/node_modules/chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", "dev": true, "dependencies": { - "has-flag": "^4.0.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" + "node": ">=8" } }, - "node_modules/@oclif/plugin-commands/node_modules/supports-hyperlinks": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-2.3.0.tgz", - "integrity": "sha512-RpsAZlpWcDwOPQA22aCH4J0t7L8JmAvsCxfOSEwm7cQs3LshN36QaTkwd70DnBOXDWGssw2eUoc8CaRWT0XunA==", + "node_modules/@oclif/color/node_modules/chalk/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "dependencies": { - "has-flag": "^4.0.0", - "supports-color": "^7.0.0" + "color-convert": "^2.0.1" }, "engines": { "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/@oclif/plugin-commands/node_modules/supports-hyperlinks/node_modules/supports-color": { + "node_modules/@oclif/color/node_modules/chalk/node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", @@ -1744,76 +2004,34 @@ "node": ">=8" } }, - "node_modules/@oclif/plugin-commands/node_modules/type-fest": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", - "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@oclif/plugin-help": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/@oclif/plugin-help/-/plugin-help-2.2.3.tgz", - "integrity": "sha512-bGHUdo5e7DjPJ0vTeRBMIrfqTRDBfyR5w0MP41u0n3r7YG5p14lvMmiCXxi6WDaP2Hw5nqx3PnkAIntCKZZN7g==", + "node_modules/@oclif/color/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, "dependencies": { - "@oclif/command": "^1.5.13", - "chalk": "^2.4.1", - "indent-string": "^4.0.0", - "lodash.template": "^4.4.0", - "string-width": "^3.0.0", - "strip-ansi": "^5.0.0", - "widest-line": "^2.0.1", - "wrap-ansi": "^4.0.0" + "color-name": "~1.1.4" }, "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/@oclif/plugin-help/node_modules/ansi-regex": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", - "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", - "dev": true, - "engines": { - "node": ">=6" + "node": ">=7.0.0" } }, - "node_modules/@oclif/plugin-help/node_modules/emoji-regex": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "node_modules/@oclif/color/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, - "node_modules/@oclif/plugin-help/node_modules/is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/@oclif/plugin-help/node_modules/string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "node_modules/@oclif/color/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, - "dependencies": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - }, "engines": { - "node": ">=6" + "node": ">=8" } }, - "node_modules/@oclif/plugin-help/node_modules/strip-ansi": { + "node_modules/@oclif/color/node_modules/strip-ansi": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", @@ -1825,146 +2043,77 @@ "node": ">=6" } }, - "node_modules/@oclif/plugin-help/node_modules/widest-line": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-2.0.1.tgz", - "integrity": "sha512-Ba5m9/Fa4Xt9eb2ELXt77JxVDV8w7qQrH0zS/TWSJdLyAwQjWoOzpzj5lwVftDz6n/EOu3tNACS84v509qwnJA==", + "node_modules/@oclif/color/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "node_modules/@oclif/command": { + "version": "1.8.36", + "resolved": "https://registry.npmjs.org/@oclif/command/-/command-1.8.36.tgz", + "integrity": "sha512-/zACSgaYGtAQRzc7HjzrlIs14FuEYAZrMOEwicRoUnZVyRunG4+t5iSEeQu0Xy2bgbCD0U1SP/EdeNZSTXRwjQ==", + "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", "dev": true, "dependencies": { - "string-width": "^2.1.1" + "@oclif/config": "^1.18.2", + "@oclif/errors": "^1.3.6", + "@oclif/help": "^1.0.1", + "@oclif/parser": "^3.8.17", + "debug": "^4.1.1", + "semver": "^7.5.4" }, "engines": { - "node": ">=4" + "node": ">=12.0.0" + }, + "peerDependencies": { + "@oclif/config": "^1" } }, - "node_modules/@oclif/plugin-help/node_modules/widest-line/node_modules/ansi-regex": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz", - "integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==", + "node_modules/@oclif/config": { + "version": "1.18.17", + "resolved": "https://registry.npmjs.org/@oclif/config/-/config-1.18.17.tgz", + "integrity": "sha512-k77qyeUvjU8qAJ3XK3fr/QVAqsZO8QOBuESnfeM5HHtPNLSyfVcwiMM2zveSW5xRdLSG3MfV8QnLVkuyCL2ENg==", + "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/@oclif/plugin-help/node_modules/widest-line/node_modules/string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "dev": true, - "dependencies": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@oclif/plugin-help/node_modules/widest-line/node_modules/strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha512-4XaJ2zQdCzROZDivEVIDPkcQn8LMFSa8kj8Gxb/Lnwzv9A8VctNZ+lfivC/sV3ivW8ElJTERXZoPBRrZKkNKow==", - "dev": true, - "dependencies": { - "ansi-regex": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@oclif/plugin-help/node_modules/wrap-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-4.0.0.tgz", - "integrity": "sha512-uMTsj9rDb0/7kk1PbcbCcwvHUxp60fGDB/NNXpVa0Q+ic/e7y5+BwTxKfQ33VYgDppSwi/FBzpetYzo8s6tfbg==", - "dev": true, - "dependencies": { - "ansi-styles": "^3.2.0", - "string-width": "^2.1.1", - "strip-ansi": "^4.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/@oclif/plugin-help/node_modules/wrap-ansi/node_modules/ansi-regex": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz", - "integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/@oclif/plugin-help/node_modules/wrap-ansi/node_modules/string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "dev": true, - "dependencies": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@oclif/plugin-help/node_modules/wrap-ansi/node_modules/strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha512-4XaJ2zQdCzROZDivEVIDPkcQn8LMFSa8kj8Gxb/Lnwzv9A8VctNZ+lfivC/sV3ivW8ElJTERXZoPBRrZKkNKow==", - "dev": true, - "dependencies": { - "ansi-regex": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@oclif/plugin-not-found": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/@oclif/plugin-not-found/-/plugin-not-found-1.2.6.tgz", - "integrity": "sha512-cfkDub79I9EpselfU/W8FTXhslrkOgfqjaa25tyGo99dAX5UVr6BWL2wbUobsU+rUcm4HN3byzdHDcqfu6hoAw==", - "dev": true, - "dependencies": { - "@oclif/color": "^0.1.2", - "@oclif/command": "1.8.11", - "cli-ux": "5.6.6", - "fast-levenshtein": "^3.0.0", - "lodash": "^4.17.21" - }, + "dependencies": { + "@oclif/errors": "^1.3.6", + "@oclif/parser": "^3.8.17", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-wsl": "^2.1.1", + "tslib": "^2.6.1" + }, "engines": { "node": ">=8.0.0" } }, - "node_modules/@oclif/plugin-not-found/node_modules/@oclif/command": { - "version": "1.8.11", - "resolved": "https://registry.npmjs.org/@oclif/command/-/command-1.8.11.tgz", - "integrity": "sha512-2fGLMvi6J5+oNxTaZfdWPMWY8oW15rYj0V8yLzmZBAEjfzjLqLIzJE9IlNccN1zwRqRHc1bcISSRDdxJ56IS/Q==", + "node_modules/@oclif/errors": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/@oclif/errors/-/errors-1.3.6.tgz", + "integrity": "sha512-fYaU4aDceETd89KXP+3cLyg9EHZsLD3RxF2IU9yxahhBpspWjkWi3Dy3bTgcwZ3V47BgxQaGapzJWDM33XIVDQ==", "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", "dev": true, "dependencies": { - "@oclif/config": "^1.18.2", - "@oclif/errors": "^1.3.5", - "@oclif/parser": "^3.8.6", - "@oclif/plugin-help": "3.2.14", - "debug": "^4.1.1", - "semver": "^7.3.2" + "clean-stack": "^3.0.0", + "fs-extra": "^8.1", + "indent-string": "^4.0.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" }, "engines": { - "node": ">=12.0.0" - }, - "peerDependencies": { - "@oclif/config": "^1" + "node": ">=8.0.0" } }, - "node_modules/@oclif/plugin-not-found/node_modules/@oclif/plugin-help": { - "version": "3.2.14", - "resolved": "https://registry.npmjs.org/@oclif/plugin-help/-/plugin-help-3.2.14.tgz", - "integrity": "sha512-NP5qmE2YfcW3MmXjcrxiqKe9Hf3G0uK/qNc0zAMYKU4crFyIsWj7dBfQVFZSb28YXGioOOpjMzG1I7VMxKF38Q==", + "node_modules/@oclif/help": { + "version": "1.0.15", + "resolved": "https://registry.npmjs.org/@oclif/help/-/help-1.0.15.tgz", + "integrity": "sha512-Yt8UHoetk/XqohYX76DfdrUYLsPKMc5pgkzsZVHDyBSkLiGRzujVaGZdjr32ckVZU9q3a47IjhWxhip7Dz5W/g==", + "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", "dev": true, "dependencies": { - "@oclif/command": "^1.8.9", - "@oclif/config": "^1.18.2", - "@oclif/errors": "^1.3.5", + "@oclif/config": "1.18.16", + "@oclif/errors": "1.3.6", "chalk": "^4.1.2", "indent-string": "^4.0.0", "lodash": "^4.17.21", @@ -1977,22 +2126,25 @@ "node": ">=8.0.0" } }, - "node_modules/@oclif/plugin-not-found/node_modules/ansi-escapes": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", - "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "node_modules/@oclif/help/node_modules/@oclif/config": { + "version": "1.18.16", + "resolved": "https://registry.npmjs.org/@oclif/config/-/config-1.18.16.tgz", + "integrity": "sha512-VskIxVcN22qJzxRUq+raalq6Q3HUde7sokB7/xk5TqRZGEKRVbFeqdQBxDWwQeudiJEgcNiMvIFbMQ43dY37FA==", + "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", "dev": true, "dependencies": { - "type-fest": "^0.21.3" + "@oclif/errors": "^1.3.6", + "@oclif/parser": "^3.8.16", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-wsl": "^2.1.1", + "tslib": "^2.6.1" }, "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=8.0.0" } }, - "node_modules/@oclif/plugin-not-found/node_modules/ansi-styles": { + "node_modules/@oclif/help/node_modules/ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", @@ -2007,16 +2159,7 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/@oclif/plugin-not-found/node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "dependencies": { - "sprintf-js": "~1.0.2" - } - }, - "node_modules/@oclif/plugin-not-found/node_modules/chalk": { + "node_modules/@oclif/help/node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", @@ -2032,60 +2175,7 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/@oclif/plugin-not-found/node_modules/cli-ux": { - "version": "5.6.6", - "resolved": "https://registry.npmjs.org/cli-ux/-/cli-ux-5.6.6.tgz", - "integrity": "sha512-4wUB34zoFklcZV0z5YiOM5IqVMMt9c3TK3QYRK3dqyk3XoRC0ybiWDWHfsMDjkKrzsVTw95rXn9NrzSHbae4pg==", - "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", - "dev": true, - "dependencies": { - "@oclif/command": "^1.8.9", - "@oclif/errors": "^1.3.5", - "@oclif/linewrap": "^1.0.0", - "@oclif/screen": "^1.0.4", - "ansi-escapes": "^4.3.0", - "ansi-styles": "^4.2.0", - "cardinal": "^2.1.1", - "chalk": "^4.1.0", - "clean-stack": "^3.0.0", - "cli-progress": "^3.4.0", - "extract-stack": "^2.0.0", - "fs-extra": "^8.1", - "hyperlinker": "^1.0.0", - "indent-string": "^4.0.0", - "is-wsl": "^2.2.0", - "js-yaml": "^3.13.1", - "lodash": "^4.17.21", - "natural-orderby": "^2.0.1", - "object-treeify": "^1.1.4", - "password-prompt": "^1.1.2", - "semver": "^7.3.2", - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "supports-color": "^8.1.0", - "supports-hyperlinks": "^2.1.0", - "tslib": "^2.0.0" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/@oclif/plugin-not-found/node_modules/cli-ux/node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, - "node_modules/@oclif/plugin-not-found/node_modules/color-convert": { + "node_modules/@oclif/help/node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", @@ -2097,22 +2187,13 @@ "node": ">=7.0.0" } }, - "node_modules/@oclif/plugin-not-found/node_modules/color-name": { + "node_modules/@oclif/help/node_modules/color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, - "node_modules/@oclif/plugin-not-found/node_modules/extract-stack": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/extract-stack/-/extract-stack-2.0.0.tgz", - "integrity": "sha512-AEo4zm+TenK7zQorGK1f9mJ8L14hnTDi2ZQPR+Mub1NX8zimka1mXpV5LpH8x9HoUmFSHZCfLHqWvp0Y4FxxzQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/@oclif/plugin-not-found/node_modules/has-flag": { + "node_modules/@oclif/help/node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", @@ -2121,20 +2202,7 @@ "node": ">=8" } }, - "node_modules/@oclif/plugin-not-found/node_modules/js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", - "dev": true, - "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/@oclif/plugin-not-found/node_modules/supports-color": { + "node_modules/@oclif/help/node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", @@ -2146,70 +2214,166 @@ "node": ">=8" } }, - "node_modules/@oclif/plugin-not-found/node_modules/supports-hyperlinks": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-2.3.0.tgz", - "integrity": "sha512-RpsAZlpWcDwOPQA22aCH4J0t7L8JmAvsCxfOSEwm7cQs3LshN36QaTkwd70DnBOXDWGssw2eUoc8CaRWT0XunA==", + "node_modules/@oclif/help/node_modules/wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", "dev": true, "dependencies": { - "has-flag": "^4.0.0", - "supports-color": "^7.0.0" - }, - "engines": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { "node": ">=8" } }, - "node_modules/@oclif/plugin-not-found/node_modules/type-fest": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", - "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "node_modules/@oclif/linewrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@oclif/linewrap/-/linewrap-1.0.0.tgz", + "integrity": "sha512-Ups2dShK52xXa8w6iBWLgcjPJWjais6KPJQq3gQ/88AY6BXoTX+MIGFPrWQO1KLMiQfoTpcLnUwloN4brrVUHw==", + "dev": true + }, + "node_modules/@oclif/parser": { + "version": "3.8.17", + "resolved": "https://registry.npmjs.org/@oclif/parser/-/parser-3.8.17.tgz", + "integrity": "sha512-l04iSd0xoh/16TGVpXb81Gg3z7tlQGrEup16BrVLsZBK6SEYpYHRJZnM32BwZrHI97ZSFfuSwVlzoo6HdsaK8A==", + "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", + "dev": true, + "dependencies": { + "@oclif/errors": "^1.3.6", + "@oclif/linewrap": "^1.0.0", + "chalk": "^4.1.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@oclif/parser/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@oclif/parser/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, "engines": { "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/@oclif/plugin-not-found/node_modules/wrap-ansi": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", - "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "node_modules/@oclif/parser/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" + "color-name": "~1.1.4" }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@oclif/parser/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/@oclif/parser/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, "engines": { "node": ">=8" } }, - "node_modules/@oclif/plugin-plugins": { - "version": "1.10.11", - "resolved": "https://registry.npmjs.org/@oclif/plugin-plugins/-/plugin-plugins-1.10.11.tgz", - "integrity": "sha512-C9eHF10UkxwoAqRYrPW51YDuDOpDXASX4BEA++kTVcqhMQTKBQalmEJKw+gVnLl1YNmapse1ZSAcU1TrXjqykg==", + "node_modules/@oclif/parser/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "dependencies": { - "@oclif/color": "^0.1.2", - "@oclif/command": "^1.8.15", - "@oclif/errors": "^1.3.5", - "chalk": "^4.1.2", - "cli-ux": "^5.6.7", - "debug": "^4.3.3", - "fs-extra": "^9.0", - "http-call": "^5.3.0", - "load-json-file": "^5.3.0", - "npm-run-path": "^4.0.1", - "semver": "^7.3.2", - "tslib": "^2.0.0", - "yarn": "^1.21.1" + "has-flag": "^4.0.0" }, "engines": { - "node": ">=12.0.0" + "node": ">=8" } }, - "node_modules/@oclif/plugin-plugins/node_modules/ansi-escapes": { + "node_modules/@oclif/plugin-autocomplete": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/@oclif/plugin-autocomplete/-/plugin-autocomplete-0.1.5.tgz", + "integrity": "sha512-Afchpdd8FNfx9GaU/1D9IzyfiXvjfGybgzQ6G4GTFvPO0/hLdkXX3YyYq+SnxE6/bCrhg4pleiB+GuJACmmkEA==", + "dev": true, + "dependencies": { + "@oclif/command": "^1.4.31", + "@oclif/config": "^1.6.22", + "chalk": "^2.4.1", + "cli-ux": "^4.4.0", + "debug": "^3.1.0", + "fs-extra": "^6.0.1", + "moment": "^2.22.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@oclif/plugin-autocomplete/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/@oclif/plugin-autocomplete/node_modules/fs-extra": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-6.0.1.tgz", + "integrity": "sha512-GnyIkKhhzXZUWFCaJzvyDLEEgDkPfb4/TPvJCJVuS8MWZgoSsErf++QpiAlDnKFcqhRlm+tIOcencCjyJE6ZCA==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "node_modules/@oclif/plugin-commands": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@oclif/plugin-commands/-/plugin-commands-1.3.0.tgz", + "integrity": "sha512-Qx9gJ7/aPBgo+Q/DHmGcWyxn2/0bjqmCwt/nO0lWuTZQIH3ZTqclTm68TMZLS4QnQyDGeeYK0GqZ5qJlrXD+SQ==", + "dev": true, + "dependencies": { + "@oclif/command": "^1.5.4", + "@oclif/config": "^1.8.7", + "cli-ux": "^5.4.5", + "lodash": "^4.17.11" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@oclif/plugin-commands/node_modules/ansi-escapes": { "version": "4.3.2", "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", @@ -2224,7 +2388,7 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@oclif/plugin-plugins/node_modules/ansi-styles": { + "node_modules/@oclif/plugin-commands/node_modules/ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", @@ -2239,7 +2403,7 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/@oclif/plugin-plugins/node_modules/argparse": { + "node_modules/@oclif/plugin-commands/node_modules/argparse": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", @@ -2248,7 +2412,7 @@ "sprintf-js": "~1.0.2" } }, - "node_modules/@oclif/plugin-plugins/node_modules/chalk": { + "node_modules/@oclif/plugin-commands/node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", @@ -2264,7 +2428,19 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/@oclif/plugin-plugins/node_modules/cli-ux": { + "node_modules/@oclif/plugin-commands/node_modules/chalk/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@oclif/plugin-commands/node_modules/cli-ux": { "version": "5.6.7", "resolved": "https://registry.npmjs.org/cli-ux/-/cli-ux-5.6.7.tgz", "integrity": "sha512-dsKAurMNyFDnO6X1TiiRNiVbL90XReLKcvIq4H777NMqXGBxBws23ag8ubCJE97vVZEgWG2eSUhsyLf63Jv8+g==", @@ -2302,36 +2478,7 @@ "node": ">=8.0.0" } }, - "node_modules/@oclif/plugin-plugins/node_modules/cli-ux/node_modules/fs-extra": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", - "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - }, - "engines": { - "node": ">=6 <7 || >=8" - } - }, - "node_modules/@oclif/plugin-plugins/node_modules/cli-ux/node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, - "node_modules/@oclif/plugin-plugins/node_modules/color-convert": { + "node_modules/@oclif/plugin-commands/node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", @@ -2343,13 +2490,13 @@ "node": ">=7.0.0" } }, - "node_modules/@oclif/plugin-plugins/node_modules/color-name": { + "node_modules/@oclif/plugin-commands/node_modules/color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, - "node_modules/@oclif/plugin-plugins/node_modules/extract-stack": { + "node_modules/@oclif/plugin-commands/node_modules/extract-stack": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/extract-stack/-/extract-stack-2.0.0.tgz", "integrity": "sha512-AEo4zm+TenK7zQorGK1f9mJ8L14hnTDi2ZQPR+Mub1NX8zimka1mXpV5LpH8x9HoUmFSHZCfLHqWvp0Y4FxxzQ==", @@ -2358,65 +2505,57 @@ "node": ">=8" } }, - "node_modules/@oclif/plugin-plugins/node_modules/fs-extra": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", - "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "node_modules/@oclif/plugin-commands/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, - "dependencies": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, "engines": { - "node": ">=10" + "node": ">=8" } }, - "node_modules/@oclif/plugin-plugins/node_modules/fs-extra/node_modules/jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "node_modules/@oclif/plugin-commands/node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", "dev": true, "dependencies": { - "universalify": "^2.0.0" + "argparse": "^1.0.7", + "esprima": "^4.0.0" }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" + "bin": { + "js-yaml": "bin/js-yaml.js" } }, - "node_modules/@oclif/plugin-plugins/node_modules/fs-extra/node_modules/universalify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", - "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", - "dev": true, - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/@oclif/plugin-plugins/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "node_modules/@oclif/plugin-commands/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, "engines": { - "node": ">=8" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" } }, - "node_modules/@oclif/plugin-plugins/node_modules/js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "node_modules/@oclif/plugin-commands/node_modules/supports-hyperlinks": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-2.3.0.tgz", + "integrity": "sha512-RpsAZlpWcDwOPQA22aCH4J0t7L8JmAvsCxfOSEwm7cQs3LshN36QaTkwd70DnBOXDWGssw2eUoc8CaRWT0XunA==", "dev": true, "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" + "has-flag": "^4.0.0", + "supports-color": "^7.0.0" }, - "bin": { - "js-yaml": "bin/js-yaml.js" + "engines": { + "node": ">=8" } }, - "node_modules/@oclif/plugin-plugins/node_modules/supports-color": { + "node_modules/@oclif/plugin-commands/node_modules/supports-hyperlinks/node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", @@ -2428,20 +2567,7 @@ "node": ">=8" } }, - "node_modules/@oclif/plugin-plugins/node_modules/supports-hyperlinks": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-2.3.0.tgz", - "integrity": "sha512-RpsAZlpWcDwOPQA22aCH4J0t7L8JmAvsCxfOSEwm7cQs3LshN36QaTkwd70DnBOXDWGssw2eUoc8CaRWT0XunA==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0", - "supports-color": "^7.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@oclif/plugin-plugins/node_modules/type-fest": { + "node_modules/@oclif/plugin-commands/node_modules/type-fest": { "version": "0.21.3", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", @@ -2453,237 +2579,321 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@oclif/plugin-update": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@oclif/plugin-update/-/plugin-update-1.5.0.tgz", - "integrity": "sha512-GsWK1CMeBBO8YknThoOZulj3xE+ZgZAXW1ouNJALXcs3mbROzszLDGjXV3RM6ffbJpnWLiMIqSFNOE8d+vGcgQ==", + "node_modules/@oclif/plugin-help": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/@oclif/plugin-help/-/plugin-help-2.2.3.tgz", + "integrity": "sha512-bGHUdo5e7DjPJ0vTeRBMIrfqTRDBfyR5w0MP41u0n3r7YG5p14lvMmiCXxi6WDaP2Hw5nqx3PnkAIntCKZZN7g==", "dev": true, "dependencies": { - "@oclif/color": "^0.1.0", - "@oclif/command": "^1.7.0", - "@oclif/config": "^1.16.0", - "@oclif/errors": "^1.3.4", - "@types/semver": "^7.3.4", - "cli-ux": "^5.5.1", - "cross-spawn": "^7.0.3", - "debug": "^4.3.1", - "filesize": "^6.1.0", - "fs-extra": "^9.0.1", - "http-call": "^5.3.0", - "lodash": "^4.17.21", - "log-chopper": "^1.0.2", - "semver": "^7.3.5", - "tar-fs": "^2.1.1" + "@oclif/command": "^1.5.13", + "chalk": "^2.4.1", + "indent-string": "^4.0.0", + "lodash.template": "^4.4.0", + "string-width": "^3.0.0", + "strip-ansi": "^5.0.0", + "widest-line": "^2.0.1", + "wrap-ansi": "^4.0.0" }, "engines": { "node": ">=8.0.0" } }, - "node_modules/@oclif/plugin-update/node_modules/ansi-escapes": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", - "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "node_modules/@oclif/plugin-help/node_modules/ansi-regex": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", + "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", "dev": true, - "dependencies": { - "type-fest": "^0.21.3" - }, "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=6" } }, - "node_modules/@oclif/plugin-update/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "node_modules/@oclif/plugin-help/node_modules/emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "dev": true + }, + "node_modules/@oclif/plugin-help/node_modules/is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==", "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "node": ">=4" } }, - "node_modules/@oclif/plugin-update/node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "node_modules/@oclif/plugin-help/node_modules/string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", "dev": true, "dependencies": { - "sprintf-js": "~1.0.2" + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + }, + "engines": { + "node": ">=6" } }, - "node_modules/@oclif/plugin-update/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "node_modules/@oclif/plugin-help/node_modules/strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", "dev": true, "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "ansi-regex": "^4.1.0" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "node": ">=6" } }, - "node_modules/@oclif/plugin-update/node_modules/chalk/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "node_modules/@oclif/plugin-help/node_modules/widest-line": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-2.0.1.tgz", + "integrity": "sha512-Ba5m9/Fa4Xt9eb2ELXt77JxVDV8w7qQrH0zS/TWSJdLyAwQjWoOzpzj5lwVftDz6n/EOu3tNACS84v509qwnJA==", "dev": true, "dependencies": { - "has-flag": "^4.0.0" + "string-width": "^2.1.1" }, "engines": { - "node": ">=8" + "node": ">=4" } }, - "node_modules/@oclif/plugin-update/node_modules/cli-ux": { - "version": "5.6.7", - "resolved": "https://registry.npmjs.org/cli-ux/-/cli-ux-5.6.7.tgz", - "integrity": "sha512-dsKAurMNyFDnO6X1TiiRNiVbL90XReLKcvIq4H777NMqXGBxBws23ag8ubCJE97vVZEgWG2eSUhsyLf63Jv8+g==", - "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", + "node_modules/@oclif/plugin-help/node_modules/widest-line/node_modules/ansi-regex": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz", + "integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@oclif/plugin-help/node_modules/widest-line/node_modules/string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", "dev": true, "dependencies": { - "@oclif/command": "^1.8.15", - "@oclif/errors": "^1.3.5", - "@oclif/linewrap": "^1.0.0", - "@oclif/screen": "^1.0.4", - "ansi-escapes": "^4.3.0", - "ansi-styles": "^4.2.0", - "cardinal": "^2.1.1", - "chalk": "^4.1.0", - "clean-stack": "^3.0.0", - "cli-progress": "^3.4.0", - "extract-stack": "^2.0.0", - "fs-extra": "^8.1", - "hyperlinker": "^1.0.0", - "indent-string": "^4.0.0", - "is-wsl": "^2.2.0", - "js-yaml": "^3.13.1", - "lodash": "^4.17.21", - "natural-orderby": "^2.0.1", - "object-treeify": "^1.1.4", - "password-prompt": "^1.1.2", - "semver": "^7.3.2", - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "supports-color": "^8.1.0", - "supports-hyperlinks": "^2.1.0", - "tslib": "^2.0.0" + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" }, "engines": { - "node": ">=8.0.0" + "node": ">=4" } }, - "node_modules/@oclif/plugin-update/node_modules/cli-ux/node_modules/fs-extra": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", - "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "node_modules/@oclif/plugin-help/node_modules/widest-line/node_modules/strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha512-4XaJ2zQdCzROZDivEVIDPkcQn8LMFSa8kj8Gxb/Lnwzv9A8VctNZ+lfivC/sV3ivW8ElJTERXZoPBRrZKkNKow==", "dev": true, "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" + "ansi-regex": "^3.0.0" }, "engines": { - "node": ">=6 <7 || >=8" + "node": ">=4" } }, - "node_modules/@oclif/plugin-update/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "node_modules/@oclif/plugin-help/node_modules/wrap-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-4.0.0.tgz", + "integrity": "sha512-uMTsj9rDb0/7kk1PbcbCcwvHUxp60fGDB/NNXpVa0Q+ic/e7y5+BwTxKfQ33VYgDppSwi/FBzpetYzo8s6tfbg==", "dev": true, "dependencies": { - "color-name": "~1.1.4" + "ansi-styles": "^3.2.0", + "string-width": "^2.1.1", + "strip-ansi": "^4.0.0" }, "engines": { - "node": ">=7.0.0" + "node": ">=6" } }, - "node_modules/@oclif/plugin-update/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/@oclif/plugin-update/node_modules/extract-stack": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/extract-stack/-/extract-stack-2.0.0.tgz", - "integrity": "sha512-AEo4zm+TenK7zQorGK1f9mJ8L14hnTDi2ZQPR+Mub1NX8zimka1mXpV5LpH8x9HoUmFSHZCfLHqWvp0Y4FxxzQ==", + "node_modules/@oclif/plugin-help/node_modules/wrap-ansi/node_modules/ansi-regex": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz", + "integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==", "dev": true, "engines": { - "node": ">=8" + "node": ">=4" } }, - "node_modules/@oclif/plugin-update/node_modules/fs-extra": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", - "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "node_modules/@oclif/plugin-help/node_modules/wrap-ansi/node_modules/string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", "dev": true, "dependencies": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" }, "engines": { - "node": ">=10" + "node": ">=4" } }, - "node_modules/@oclif/plugin-update/node_modules/fs-extra/node_modules/jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "node_modules/@oclif/plugin-help/node_modules/wrap-ansi/node_modules/strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha512-4XaJ2zQdCzROZDivEVIDPkcQn8LMFSa8kj8Gxb/Lnwzv9A8VctNZ+lfivC/sV3ivW8ElJTERXZoPBRrZKkNKow==", "dev": true, "dependencies": { - "universalify": "^2.0.0" + "ansi-regex": "^3.0.0" }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" + "engines": { + "node": ">=4" } }, - "node_modules/@oclif/plugin-update/node_modules/fs-extra/node_modules/universalify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", - "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "node_modules/@oclif/plugin-not-found": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@oclif/plugin-not-found/-/plugin-not-found-1.2.6.tgz", + "integrity": "sha512-cfkDub79I9EpselfU/W8FTXhslrkOgfqjaa25tyGo99dAX5UVr6BWL2wbUobsU+rUcm4HN3byzdHDcqfu6hoAw==", "dev": true, + "dependencies": { + "@oclif/color": "^0.1.2", + "@oclif/command": "1.8.11", + "cli-ux": "5.6.6", + "fast-levenshtein": "^3.0.0", + "lodash": "^4.17.21" + }, "engines": { - "node": ">= 10.0.0" + "node": ">=8.0.0" } }, - "node_modules/@oclif/plugin-update/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "node_modules/@oclif/plugin-not-found/node_modules/@oclif/command": { + "version": "1.8.11", + "resolved": "https://registry.npmjs.org/@oclif/command/-/command-1.8.11.tgz", + "integrity": "sha512-2fGLMvi6J5+oNxTaZfdWPMWY8oW15rYj0V8yLzmZBAEjfzjLqLIzJE9IlNccN1zwRqRHc1bcISSRDdxJ56IS/Q==", + "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", + "dev": true, + "dependencies": { + "@oclif/config": "^1.18.2", + "@oclif/errors": "^1.3.5", + "@oclif/parser": "^3.8.6", + "@oclif/plugin-help": "3.2.14", + "debug": "^4.1.1", + "semver": "^7.3.2" + }, + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "@oclif/config": "^1" + } + }, + "node_modules/@oclif/plugin-not-found/node_modules/@oclif/plugin-help": { + "version": "3.2.14", + "resolved": "https://registry.npmjs.org/@oclif/plugin-help/-/plugin-help-3.2.14.tgz", + "integrity": "sha512-NP5qmE2YfcW3MmXjcrxiqKe9Hf3G0uK/qNc0zAMYKU4crFyIsWj7dBfQVFZSb28YXGioOOpjMzG1I7VMxKF38Q==", + "dev": true, + "dependencies": { + "@oclif/command": "^1.8.9", + "@oclif/config": "^1.18.2", + "@oclif/errors": "^1.3.5", + "chalk": "^4.1.2", + "indent-string": "^4.0.0", + "lodash": "^4.17.21", + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "widest-line": "^3.1.0", + "wrap-ansi": "^6.2.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@oclif/plugin-not-found/node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", "dev": true, + "dependencies": { + "type-fest": "^0.21.3" + }, "engines": { "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@oclif/plugin-update/node_modules/js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "node_modules/@oclif/plugin-not-found/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" + "color-convert": "^2.0.1" }, - "bin": { - "js-yaml": "bin/js-yaml.js" + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/@oclif/plugin-update/node_modules/supports-color": { + "node_modules/@oclif/plugin-not-found/node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/@oclif/plugin-not-found/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@oclif/plugin-not-found/node_modules/cli-ux": { + "version": "5.6.6", + "resolved": "https://registry.npmjs.org/cli-ux/-/cli-ux-5.6.6.tgz", + "integrity": "sha512-4wUB34zoFklcZV0z5YiOM5IqVMMt9c3TK3QYRK3dqyk3XoRC0ybiWDWHfsMDjkKrzsVTw95rXn9NrzSHbae4pg==", + "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", + "dev": true, + "dependencies": { + "@oclif/command": "^1.8.9", + "@oclif/errors": "^1.3.5", + "@oclif/linewrap": "^1.0.0", + "@oclif/screen": "^1.0.4", + "ansi-escapes": "^4.3.0", + "ansi-styles": "^4.2.0", + "cardinal": "^2.1.1", + "chalk": "^4.1.0", + "clean-stack": "^3.0.0", + "cli-progress": "^3.4.0", + "extract-stack": "^2.0.0", + "fs-extra": "^8.1", + "hyperlinker": "^1.0.0", + "indent-string": "^4.0.0", + "is-wsl": "^2.2.0", + "js-yaml": "^3.13.1", + "lodash": "^4.17.21", + "natural-orderby": "^2.0.1", + "object-treeify": "^1.1.4", + "password-prompt": "^1.1.2", + "semver": "^7.3.2", + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "supports-color": "^8.1.0", + "supports-hyperlinks": "^2.1.0", + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@oclif/plugin-not-found/node_modules/cli-ux/node_modules/supports-color": { "version": "8.1.1", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", @@ -2698,20 +2908,56 @@ "url": "https://github.com/chalk/supports-color?sponsor=1" } }, - "node_modules/@oclif/plugin-update/node_modules/supports-hyperlinks": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-2.3.0.tgz", - "integrity": "sha512-RpsAZlpWcDwOPQA22aCH4J0t7L8JmAvsCxfOSEwm7cQs3LshN36QaTkwd70DnBOXDWGssw2eUoc8CaRWT0XunA==", + "node_modules/@oclif/plugin-not-found/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, "dependencies": { - "has-flag": "^4.0.0", - "supports-color": "^7.0.0" + "color-name": "~1.1.4" }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@oclif/plugin-not-found/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/@oclif/plugin-not-found/node_modules/extract-stack": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/extract-stack/-/extract-stack-2.0.0.tgz", + "integrity": "sha512-AEo4zm+TenK7zQorGK1f9mJ8L14hnTDi2ZQPR+Mub1NX8zimka1mXpV5LpH8x9HoUmFSHZCfLHqWvp0Y4FxxzQ==", + "dev": true, "engines": { "node": ">=8" } }, - "node_modules/@oclif/plugin-update/node_modules/supports-hyperlinks/node_modules/supports-color": { + "node_modules/@oclif/plugin-not-found/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@oclif/plugin-not-found/node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/@oclif/plugin-not-found/node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", @@ -2723,7 +2969,20 @@ "node": ">=8" } }, - "node_modules/@oclif/plugin-update/node_modules/type-fest": { + "node_modules/@oclif/plugin-not-found/node_modules/supports-hyperlinks": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-2.3.0.tgz", + "integrity": "sha512-RpsAZlpWcDwOPQA22aCH4J0t7L8JmAvsCxfOSEwm7cQs3LshN36QaTkwd70DnBOXDWGssw2eUoc8CaRWT0XunA==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0", + "supports-color": "^7.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@oclif/plugin-not-found/node_modules/type-fest": { "version": "0.21.3", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", @@ -2735,214 +2994,1409 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@oclif/plugin-warn-if-update-available": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/@oclif/plugin-warn-if-update-available/-/plugin-warn-if-update-available-1.7.3.tgz", - "integrity": "sha512-q8q0NIneVCwIAJzglUMsl3EbXR/H5aPDk6g+qs7uF0tToxe07SWSONoNaKPzViwRWvYChMPjL77/rXyW1HVn4A==", - "dev": true, - "dependencies": { - "@oclif/command": "^1.8.6", - "@oclif/config": "^1.17.1", + "node_modules/@oclif/plugin-not-found/node_modules/wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@oclif/plugin-plugins": { + "version": "1.10.11", + "resolved": "https://registry.npmjs.org/@oclif/plugin-plugins/-/plugin-plugins-1.10.11.tgz", + "integrity": "sha512-C9eHF10UkxwoAqRYrPW51YDuDOpDXASX4BEA++kTVcqhMQTKBQalmEJKw+gVnLl1YNmapse1ZSAcU1TrXjqykg==", + "dev": true, + "dependencies": { + "@oclif/color": "^0.1.2", + "@oclif/command": "^1.8.15", "@oclif/errors": "^1.3.5", - "chalk": "^4.1.0", - "debug": "^4.1.0", - "fs-extra": "^9.0.1", - "http-call": "^5.2.2", - "lodash": "^4.17.21", - "semver": "^7.3.2" + "chalk": "^4.1.2", + "cli-ux": "^5.6.7", + "debug": "^4.3.3", + "fs-extra": "^9.0", + "http-call": "^5.3.0", + "load-json-file": "^5.3.0", + "npm-run-path": "^4.0.1", + "semver": "^7.3.2", + "tslib": "^2.0.0", + "yarn": "^1.21.1" }, "engines": { - "node": ">=8.0.0" + "node": ">=12.0.0" } }, - "node_modules/@oclif/plugin-warn-if-update-available/node_modules/ansi-styles": { + "node_modules/@oclif/plugin-plugins/node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dev": true, + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@oclif/plugin-plugins/node_modules/ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@oclif/plugin-plugins/node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/@oclif/plugin-plugins/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@oclif/plugin-plugins/node_modules/cli-ux": { + "version": "5.6.7", + "resolved": "https://registry.npmjs.org/cli-ux/-/cli-ux-5.6.7.tgz", + "integrity": "sha512-dsKAurMNyFDnO6X1TiiRNiVbL90XReLKcvIq4H777NMqXGBxBws23ag8ubCJE97vVZEgWG2eSUhsyLf63Jv8+g==", + "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", + "dev": true, + "dependencies": { + "@oclif/command": "^1.8.15", + "@oclif/errors": "^1.3.5", + "@oclif/linewrap": "^1.0.0", + "@oclif/screen": "^1.0.4", + "ansi-escapes": "^4.3.0", + "ansi-styles": "^4.2.0", + "cardinal": "^2.1.1", + "chalk": "^4.1.0", + "clean-stack": "^3.0.0", + "cli-progress": "^3.4.0", + "extract-stack": "^2.0.0", + "fs-extra": "^8.1", + "hyperlinker": "^1.0.0", + "indent-string": "^4.0.0", + "is-wsl": "^2.2.0", + "js-yaml": "^3.13.1", + "lodash": "^4.17.21", + "natural-orderby": "^2.0.1", + "object-treeify": "^1.1.4", + "password-prompt": "^1.1.2", + "semver": "^7.3.2", + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "supports-color": "^8.1.0", + "supports-hyperlinks": "^2.1.0", + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@oclif/plugin-plugins/node_modules/cli-ux/node_modules/fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "engines": { + "node": ">=6 <7 || >=8" + } + }, + "node_modules/@oclif/plugin-plugins/node_modules/cli-ux/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/@oclif/plugin-plugins/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@oclif/plugin-plugins/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/@oclif/plugin-plugins/node_modules/extract-stack": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/extract-stack/-/extract-stack-2.0.0.tgz", + "integrity": "sha512-AEo4zm+TenK7zQorGK1f9mJ8L14hnTDi2ZQPR+Mub1NX8zimka1mXpV5LpH8x9HoUmFSHZCfLHqWvp0Y4FxxzQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@oclif/plugin-plugins/node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dev": true, + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@oclif/plugin-plugins/node_modules/fs-extra/node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/@oclif/plugin-plugins/node_modules/fs-extra/node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/@oclif/plugin-plugins/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@oclif/plugin-plugins/node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/@oclif/plugin-plugins/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@oclif/plugin-plugins/node_modules/supports-hyperlinks": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-2.3.0.tgz", + "integrity": "sha512-RpsAZlpWcDwOPQA22aCH4J0t7L8JmAvsCxfOSEwm7cQs3LshN36QaTkwd70DnBOXDWGssw2eUoc8CaRWT0XunA==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0", + "supports-color": "^7.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@oclif/plugin-plugins/node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@oclif/plugin-update": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@oclif/plugin-update/-/plugin-update-1.5.0.tgz", + "integrity": "sha512-GsWK1CMeBBO8YknThoOZulj3xE+ZgZAXW1ouNJALXcs3mbROzszLDGjXV3RM6ffbJpnWLiMIqSFNOE8d+vGcgQ==", + "dev": true, + "dependencies": { + "@oclif/color": "^0.1.0", + "@oclif/command": "^1.7.0", + "@oclif/config": "^1.16.0", + "@oclif/errors": "^1.3.4", + "@types/semver": "^7.3.4", + "cli-ux": "^5.5.1", + "cross-spawn": "^7.0.3", + "debug": "^4.3.1", + "filesize": "^6.1.0", + "fs-extra": "^9.0.1", + "http-call": "^5.3.0", + "lodash": "^4.17.21", + "log-chopper": "^1.0.2", + "semver": "^7.3.5", + "tar-fs": "^2.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@oclif/plugin-update/node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dev": true, + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@oclif/plugin-update/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@oclif/plugin-update/node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/@oclif/plugin-update/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@oclif/plugin-update/node_modules/chalk/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@oclif/plugin-update/node_modules/cli-ux": { + "version": "5.6.7", + "resolved": "https://registry.npmjs.org/cli-ux/-/cli-ux-5.6.7.tgz", + "integrity": "sha512-dsKAurMNyFDnO6X1TiiRNiVbL90XReLKcvIq4H777NMqXGBxBws23ag8ubCJE97vVZEgWG2eSUhsyLf63Jv8+g==", + "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", + "dev": true, + "dependencies": { + "@oclif/command": "^1.8.15", + "@oclif/errors": "^1.3.5", + "@oclif/linewrap": "^1.0.0", + "@oclif/screen": "^1.0.4", + "ansi-escapes": "^4.3.0", + "ansi-styles": "^4.2.0", + "cardinal": "^2.1.1", + "chalk": "^4.1.0", + "clean-stack": "^3.0.0", + "cli-progress": "^3.4.0", + "extract-stack": "^2.0.0", + "fs-extra": "^8.1", + "hyperlinker": "^1.0.0", + "indent-string": "^4.0.0", + "is-wsl": "^2.2.0", + "js-yaml": "^3.13.1", + "lodash": "^4.17.21", + "natural-orderby": "^2.0.1", + "object-treeify": "^1.1.4", + "password-prompt": "^1.1.2", + "semver": "^7.3.2", + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "supports-color": "^8.1.0", + "supports-hyperlinks": "^2.1.0", + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@oclif/plugin-update/node_modules/cli-ux/node_modules/fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "engines": { + "node": ">=6 <7 || >=8" + } + }, + "node_modules/@oclif/plugin-update/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@oclif/plugin-update/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/@oclif/plugin-update/node_modules/extract-stack": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/extract-stack/-/extract-stack-2.0.0.tgz", + "integrity": "sha512-AEo4zm+TenK7zQorGK1f9mJ8L14hnTDi2ZQPR+Mub1NX8zimka1mXpV5LpH8x9HoUmFSHZCfLHqWvp0Y4FxxzQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@oclif/plugin-update/node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dev": true, + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@oclif/plugin-update/node_modules/fs-extra/node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/@oclif/plugin-update/node_modules/fs-extra/node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/@oclif/plugin-update/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@oclif/plugin-update/node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/@oclif/plugin-update/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/@oclif/plugin-update/node_modules/supports-hyperlinks": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-2.3.0.tgz", + "integrity": "sha512-RpsAZlpWcDwOPQA22aCH4J0t7L8JmAvsCxfOSEwm7cQs3LshN36QaTkwd70DnBOXDWGssw2eUoc8CaRWT0XunA==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0", + "supports-color": "^7.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@oclif/plugin-update/node_modules/supports-hyperlinks/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@oclif/plugin-update/node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@oclif/plugin-warn-if-update-available": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/@oclif/plugin-warn-if-update-available/-/plugin-warn-if-update-available-1.7.3.tgz", + "integrity": "sha512-q8q0NIneVCwIAJzglUMsl3EbXR/H5aPDk6g+qs7uF0tToxe07SWSONoNaKPzViwRWvYChMPjL77/rXyW1HVn4A==", + "dev": true, + "dependencies": { + "@oclif/command": "^1.8.6", + "@oclif/config": "^1.17.1", + "@oclif/errors": "^1.3.5", + "chalk": "^4.1.0", + "debug": "^4.1.0", + "fs-extra": "^9.0.1", + "http-call": "^5.2.2", + "lodash": "^4.17.21", + "semver": "^7.3.2" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@oclif/plugin-warn-if-update-available/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@oclif/plugin-warn-if-update-available/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@oclif/plugin-warn-if-update-available/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@oclif/plugin-warn-if-update-available/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/@oclif/plugin-warn-if-update-available/node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dev": true, + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@oclif/plugin-warn-if-update-available/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@oclif/plugin-warn-if-update-available/node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/@oclif/plugin-warn-if-update-available/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@oclif/plugin-warn-if-update-available/node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/@oclif/plugin-which": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@oclif/plugin-which/-/plugin-which-1.0.4.tgz", + "integrity": "sha512-xuJVhnUDiKIPIw5i6GiQnB3QZ55ie7ucrI6/P0TQWx+1BEt3xl6tEs/vFqnyFuDOh8fc0ZwYTBWFUWkQfYsv4w==", + "dev": true, + "dependencies": { + "@oclif/command": "1.8.11", + "@oclif/config": "1.18.2", + "cli-ux": "5.6.6", + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@oclif/plugin-which/node_modules/@oclif/command": { + "version": "1.8.11", + "resolved": "https://registry.npmjs.org/@oclif/command/-/command-1.8.11.tgz", + "integrity": "sha512-2fGLMvi6J5+oNxTaZfdWPMWY8oW15rYj0V8yLzmZBAEjfzjLqLIzJE9IlNccN1zwRqRHc1bcISSRDdxJ56IS/Q==", + "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", + "dev": true, + "dependencies": { + "@oclif/config": "^1.18.2", + "@oclif/errors": "^1.3.5", + "@oclif/parser": "^3.8.6", + "@oclif/plugin-help": "3.2.14", + "debug": "^4.1.1", + "semver": "^7.3.2" + }, + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "@oclif/config": "^1" + } + }, + "node_modules/@oclif/plugin-which/node_modules/@oclif/config": { + "version": "1.18.2", + "resolved": "https://registry.npmjs.org/@oclif/config/-/config-1.18.2.tgz", + "integrity": "sha512-cE3qfHWv8hGRCP31j7fIS7BfCflm/BNZ2HNqHexH+fDrdF2f1D5S8VmXWLC77ffv3oDvWyvE9AZeR0RfmHCCaA==", + "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", + "dev": true, + "dependencies": { + "@oclif/errors": "^1.3.3", + "@oclif/parser": "^3.8.0", + "debug": "^4.1.1", + "globby": "^11.0.1", + "is-wsl": "^2.1.1", + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@oclif/plugin-which/node_modules/@oclif/plugin-help": { + "version": "3.2.14", + "resolved": "https://registry.npmjs.org/@oclif/plugin-help/-/plugin-help-3.2.14.tgz", + "integrity": "sha512-NP5qmE2YfcW3MmXjcrxiqKe9Hf3G0uK/qNc0zAMYKU4crFyIsWj7dBfQVFZSb28YXGioOOpjMzG1I7VMxKF38Q==", + "dev": true, + "dependencies": { + "@oclif/command": "^1.8.9", + "@oclif/config": "^1.18.2", + "@oclif/errors": "^1.3.5", + "chalk": "^4.1.2", + "indent-string": "^4.0.0", + "lodash": "^4.17.21", + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "widest-line": "^3.1.0", + "wrap-ansi": "^6.2.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@oclif/plugin-which/node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dev": true, + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@oclif/plugin-which/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@oclif/plugin-which/node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/@oclif/plugin-which/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@oclif/plugin-which/node_modules/cli-ux": { + "version": "5.6.6", + "resolved": "https://registry.npmjs.org/cli-ux/-/cli-ux-5.6.6.tgz", + "integrity": "sha512-4wUB34zoFklcZV0z5YiOM5IqVMMt9c3TK3QYRK3dqyk3XoRC0ybiWDWHfsMDjkKrzsVTw95rXn9NrzSHbae4pg==", + "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", + "dev": true, + "dependencies": { + "@oclif/command": "^1.8.9", + "@oclif/errors": "^1.3.5", + "@oclif/linewrap": "^1.0.0", + "@oclif/screen": "^1.0.4", + "ansi-escapes": "^4.3.0", + "ansi-styles": "^4.2.0", + "cardinal": "^2.1.1", + "chalk": "^4.1.0", + "clean-stack": "^3.0.0", + "cli-progress": "^3.4.0", + "extract-stack": "^2.0.0", + "fs-extra": "^8.1", + "hyperlinker": "^1.0.0", + "indent-string": "^4.0.0", + "is-wsl": "^2.2.0", + "js-yaml": "^3.13.1", + "lodash": "^4.17.21", + "natural-orderby": "^2.0.1", + "object-treeify": "^1.1.4", + "password-prompt": "^1.1.2", + "semver": "^7.3.2", + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "supports-color": "^8.1.0", + "supports-hyperlinks": "^2.1.0", + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@oclif/plugin-which/node_modules/cli-ux/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/@oclif/plugin-which/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@oclif/plugin-which/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/@oclif/plugin-which/node_modules/extract-stack": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/extract-stack/-/extract-stack-2.0.0.tgz", + "integrity": "sha512-AEo4zm+TenK7zQorGK1f9mJ8L14hnTDi2ZQPR+Mub1NX8zimka1mXpV5LpH8x9HoUmFSHZCfLHqWvp0Y4FxxzQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@oclif/plugin-which/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@oclif/plugin-which/node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/@oclif/plugin-which/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@oclif/plugin-which/node_modules/supports-hyperlinks": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-2.3.0.tgz", + "integrity": "sha512-RpsAZlpWcDwOPQA22aCH4J0t7L8JmAvsCxfOSEwm7cQs3LshN36QaTkwd70DnBOXDWGssw2eUoc8CaRWT0XunA==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0", + "supports-color": "^7.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@oclif/plugin-which/node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@oclif/plugin-which/node_modules/wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@oclif/screen": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@oclif/screen/-/screen-1.0.4.tgz", + "integrity": "sha512-60CHpq+eqnTxLZQ4PGHYNwUX572hgpMHGPtTWMjdTMsAvlm69lZV/4ly6O3sAYkomo4NggGcomrDpBe34rxUqw==", + "deprecated": "Deprecated in favor of @oclif/core", + "dev": true, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@octokit/auth-token": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-2.5.0.tgz", + "integrity": "sha512-r5FVUJCOLl19AxiuZD2VRZ/ORjp/4IN98Of6YJoJOkY75CIBuYfmiNHGrDwXr+aLGG55igl9QrxX3hbiXlLb+g==", + "dev": true, + "dependencies": { + "@octokit/types": "^6.0.3" + } + }, + "node_modules/@octokit/core": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/@octokit/core/-/core-3.6.0.tgz", + "integrity": "sha512-7RKRKuA4xTjMhY+eG3jthb3hlZCsOwg3rztWh75Xc+ShDWOfDDATWbeZpAHBNRpm4Tv9WgBMOy1zEJYXG6NJ7Q==", + "dev": true, + "dependencies": { + "@octokit/auth-token": "^2.4.4", + "@octokit/graphql": "^4.5.8", + "@octokit/request": "^5.6.3", + "@octokit/request-error": "^2.0.5", + "@octokit/types": "^6.0.3", + "before-after-hook": "^2.2.0", + "universal-user-agent": "^6.0.0" + } + }, + "node_modules/@octokit/endpoint": { + "version": "6.0.12", + "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-6.0.12.tgz", + "integrity": "sha512-lF3puPwkQWGfkMClXb4k/eUT/nZKQfxinRWJrdZaJO85Dqwo/G0yOC434Jr2ojwafWJMYqFGFa5ms4jJUgujdA==", + "dev": true, + "dependencies": { + "@octokit/types": "^6.0.3", + "is-plain-object": "^5.0.0", + "universal-user-agent": "^6.0.0" + } + }, + "node_modules/@octokit/graphql": { + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-4.8.0.tgz", + "integrity": "sha512-0gv+qLSBLKF0z8TKaSKTsS39scVKF9dbMxJpj3U0vC7wjNWFuIpL/z76Qe2fiuCbDRcJSavkXsVtMS6/dtQQsg==", + "dev": true, + "dependencies": { + "@octokit/request": "^5.6.0", + "@octokit/types": "^6.0.3", + "universal-user-agent": "^6.0.0" + } + }, + "node_modules/@octokit/openapi-types": { + "version": "12.11.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-12.11.0.tgz", + "integrity": "sha512-VsXyi8peyRq9PqIz/tpqiL2w3w80OgVMwBHltTml3LmVvXiphgeqmY9mvBw9Wu7e0QWk/fqD37ux8yP5uVekyQ==", + "dev": true + }, + "node_modules/@octokit/plugin-paginate-rest": { + "version": "2.21.3", + "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-2.21.3.tgz", + "integrity": "sha512-aCZTEf0y2h3OLbrgKkrfFdjRL6eSOo8komneVQJnYecAxIej7Bafor2xhuDJOIFau4pk0i/P28/XgtbyPF0ZHw==", + "dev": true, + "dependencies": { + "@octokit/types": "^6.40.0" + }, + "peerDependencies": { + "@octokit/core": ">=2" + } + }, + "node_modules/@octokit/plugin-request-log": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-1.0.4.tgz", + "integrity": "sha512-mLUsMkgP7K/cnFEw07kWqXGF5LKrOkD+lhCrKvPHXWDywAwuDUeDwWBpc69XK3pNX0uKiVt8g5z96PJ6z9xCFA==", + "dev": true, + "peerDependencies": { + "@octokit/core": ">=3" + } + }, + "node_modules/@octokit/plugin-rest-endpoint-methods": { + "version": "5.16.2", + "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-5.16.2.tgz", + "integrity": "sha512-8QFz29Fg5jDuTPXVtey05BLm7OB+M8fnvE64RNegzX7U+5NUXcOcnpTIK0YfSHBg8gYd0oxIq3IZTe9SfPZiRw==", + "dev": true, + "dependencies": { + "@octokit/types": "^6.39.0", + "deprecation": "^2.3.1" + }, + "peerDependencies": { + "@octokit/core": ">=3" + } + }, + "node_modules/@octokit/request": { + "version": "5.6.3", + "resolved": "https://registry.npmjs.org/@octokit/request/-/request-5.6.3.tgz", + "integrity": "sha512-bFJl0I1KVc9jYTe9tdGGpAMPy32dLBXXo1dS/YwSCTL/2nd9XeHsY616RE3HPXDVk+a+dBuzyz5YdlXwcDTr2A==", + "dev": true, + "dependencies": { + "@octokit/endpoint": "^6.0.1", + "@octokit/request-error": "^2.1.0", + "@octokit/types": "^6.16.1", + "is-plain-object": "^5.0.0", + "node-fetch": "^2.6.7", + "universal-user-agent": "^6.0.0" + } + }, + "node_modules/@octokit/request-error": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-2.1.0.tgz", + "integrity": "sha512-1VIvgXxs9WHSjicsRwq8PlR2LR2x6DwsJAaFgzdi0JfJoGSO8mYI/cHJQ+9FbN21aa+DrgNLnwObmyeSC8Rmpg==", + "dev": true, + "dependencies": { + "@octokit/types": "^6.0.3", + "deprecation": "^2.0.0", + "once": "^1.4.0" + } + }, + "node_modules/@octokit/rest": { + "version": "18.12.0", + "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-18.12.0.tgz", + "integrity": "sha512-gDPiOHlyGavxr72y0guQEhLsemgVjwRePayJ+FcKc2SJqKUbxbkvf5kAZEWA/MKvsfYlQAMVzNJE3ezQcxMJ2Q==", + "dev": true, + "dependencies": { + "@octokit/core": "^3.5.1", + "@octokit/plugin-paginate-rest": "^2.16.8", + "@octokit/plugin-request-log": "^1.0.4", + "@octokit/plugin-rest-endpoint-methods": "^5.12.0" + } + }, + "node_modules/@octokit/types": { + "version": "6.41.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.41.0.tgz", + "integrity": "sha512-eJ2jbzjdijiL3B4PrSQaSjuF2sPEQPVCPzBvTHJD9Nz+9dw2SGH4K4xeQJ77YfTq5bRQ+bD8wT11JbeDPmxmGg==", + "dev": true, + "dependencies": { + "@octokit/openapi-types": "^12.11.0" + } + }, + "node_modules/@prisma/prisma-fmt-wasm": { + "version": "4.17.0-16.27eb2449f178cd9fe1a4b892d732cc4795f75085", + "resolved": "https://registry.npmjs.org/@prisma/prisma-fmt-wasm/-/prisma-fmt-wasm-4.17.0-16.27eb2449f178cd9fe1a4b892d732cc4795f75085.tgz", + "integrity": "sha512-zYz3rFwPB82mVlHGknAPdnSY/a308dhPOblxQLcZgZTDRtDXOE1MgxoRAys+jekwR4/bm3+rZDPs1xsFMsPZig==", + "optional": true + }, + "node_modules/@protobufjs/aspromise": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", + "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==" + }, + "node_modules/@protobufjs/base64": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", + "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==" + }, + "node_modules/@protobufjs/codegen": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", + "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==" + }, + "node_modules/@protobufjs/eventemitter": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", + "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==" + }, + "node_modules/@protobufjs/fetch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", + "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==", + "dependencies": { + "@protobufjs/aspromise": "^1.1.1", + "@protobufjs/inquire": "^1.1.0" + } + }, + "node_modules/@protobufjs/float": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", + "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==" + }, + "node_modules/@protobufjs/inquire": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", + "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==" + }, + "node_modules/@protobufjs/path": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", + "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==" + }, + "node_modules/@protobufjs/pool": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", + "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==" + }, + "node_modules/@protobufjs/utf8": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", + "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==" + }, + "node_modules/@sindresorhus/is": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz", + "integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==", + "dev": true, "engines": { - "node": ">=8" + "node": ">=10" }, "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "url": "https://github.com/sindresorhus/is?sponsor=1" } }, - "node_modules/@oclif/plugin-warn-if-update-available/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "node_modules/@sinonjs/commons": { + "version": "1.8.6", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.6.tgz", + "integrity": "sha512-Ky+XkAkqPZSm3NLBeUng77EBQl3cmeJhITaGHdYH8kjVB+aun3S4XBRti2zt17mtt0mIUDiNxYeoJm6drVvBJQ==", "dev": true, "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "type-detect": "4.0.8" } }, - "node_modules/@oclif/plugin-warn-if-update-available/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "node_modules/@sinonjs/formatio": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@sinonjs/formatio/-/formatio-2.0.0.tgz", + "integrity": "sha512-ls6CAMA6/5gG+O/IdsBcblvnd8qcO/l1TYoNeAzp3wcISOxlPXQEus0mLcdwazEkWjaBdaJ3TaxmNgCLWwvWzg==", "dev": true, "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" + "samsam": "1.3.0" } }, - "node_modules/@oclif/plugin-warn-if-update-available/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "node_modules/@sinonjs/samsam": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-3.3.3.tgz", + "integrity": "sha512-bKCMKZvWIjYD0BLGnNrxVuw4dkWCYsLqFOUWw8VgKF/+5Y+mE7LfHWPIYoDXowH+3a9LsWDMo0uAP8YDosPvHQ==", + "dev": true, + "dependencies": { + "@sinonjs/commons": "^1.3.0", + "array-from": "^2.1.1", + "lodash": "^4.17.15" + } + }, + "node_modules/@sinonjs/text-encoding": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.2.tgz", + "integrity": "sha512-sXXKG+uL9IrKqViTtao2Ws6dy0znu9sOaP1di/jKGW1M6VssO8vlpXCQcpZ+jisQ1tTFAC5Jo/EOzFbggBagFQ==", "dev": true }, - "node_modules/@oclif/plugin-warn-if-update-available/node_modules/fs-extra": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", - "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "node_modules/@slack/bolt": { + "version": "3.17.1", + "resolved": "https://registry.npmjs.org/@slack/bolt/-/bolt-3.17.1.tgz", + "integrity": "sha512-N+4WxpkM59RXi7BL3IXUtENnn9cF7TOBn7ttaHpgvlnjUaro+yQyY60arXTlP4ytVDFJ1w0mSdfftcM17h+i2w==", "dev": true, "dependencies": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" + "@slack/logger": "^4.0.0", + "@slack/oauth": "^2.6.2", + "@slack/socket-mode": "^1.3.3", + "@slack/types": "^2.11.0", + "@slack/web-api": "^6.11.2", + "@types/express": "^4.16.1", + "@types/promise.allsettled": "^1.0.3", + "@types/tsscmp": "^1.0.0", + "axios": "^1.6.0", + "express": "^4.16.4", + "path-to-regexp": "^6.2.1", + "please-upgrade-node": "^3.2.0", + "promise.allsettled": "^1.0.2", + "raw-body": "^2.3.3", + "tsscmp": "^1.0.6" }, "engines": { - "node": ">=10" + "node": ">=12.13.0", + "npm": ">=6.12.0" } }, - "node_modules/@oclif/plugin-warn-if-update-available/node_modules/has-flag": { + "node_modules/@slack/logger": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "resolved": "https://registry.npmjs.org/@slack/logger/-/logger-4.0.0.tgz", + "integrity": "sha512-Wz7QYfPAlG/DR+DfABddUZeNgoeY7d1J39OCR2jR+v7VBsB8ezulDK5szTnDDPDwLH5IWhLvXIHlCFZV7MSKgA==", "dev": true, + "dependencies": { + "@types/node": ">=18.0.0" + }, "engines": { - "node": ">=8" + "node": ">= 18", + "npm": ">= 8.6.0" } }, - "node_modules/@oclif/plugin-warn-if-update-available/node_modules/jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "node_modules/@slack/oauth": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/@slack/oauth/-/oauth-2.6.2.tgz", + "integrity": "sha512-2R3MyB/R63hTRXzk5J6wcui59TBxXzhk+Uh2/Xu3Wp3O4pXg/BNucQhP/DQbL/ScVhLvFtMXirLrKi0Yo5gIVw==", "dev": true, "dependencies": { - "universalify": "^2.0.0" + "@slack/logger": "^3.0.0", + "@slack/web-api": "^6.11.2", + "@types/jsonwebtoken": "^8.3.7", + "@types/node": ">=12", + "jsonwebtoken": "^9.0.0", + "lodash.isstring": "^4.0.1" }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" + "engines": { + "node": ">=12.13.0", + "npm": ">=6.12.0" } }, - "node_modules/@oclif/plugin-warn-if-update-available/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "node_modules/@slack/oauth/node_modules/@slack/logger": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@slack/logger/-/logger-3.0.0.tgz", + "integrity": "sha512-DTuBFbqu4gGfajREEMrkq5jBhcnskinhr4+AnfJEk48zhVeEv3XnUKGIX98B74kxhYsIMfApGGySTn7V3b5yBA==", "dev": true, "dependencies": { - "has-flag": "^4.0.0" + "@types/node": ">=12.0.0" }, "engines": { - "node": ">=8" + "node": ">= 12.13.0", + "npm": ">= 6.12.0" } }, - "node_modules/@oclif/plugin-warn-if-update-available/node_modules/universalify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", - "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "node_modules/@slack/socket-mode": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@slack/socket-mode/-/socket-mode-1.3.3.tgz", + "integrity": "sha512-vN3zG4woRtf2Ut6rZgRW6G/Oe56uLMlnz39I08Q7DOvVfB+1MmDbNv0PNOiFgujdKXJR+bXF41/F/VvryXcqlw==", "dev": true, + "dependencies": { + "@slack/logger": "^3.0.0", + "@slack/web-api": "^6.11.2", + "@types/node": ">=12.0.0", + "@types/p-queue": "^2.3.2", + "@types/ws": "^7.4.7", + "eventemitter3": "^3.1.0", + "finity": "^0.5.4", + "p-cancelable": "^1.1.0", + "p-queue": "^2.4.2", + "ws": "^7.5.3" + }, "engines": { - "node": ">= 10.0.0" + "node": ">=12.13.0", + "npm": ">=6.12.0" } }, - "node_modules/@oclif/plugin-which": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@oclif/plugin-which/-/plugin-which-1.0.4.tgz", - "integrity": "sha512-xuJVhnUDiKIPIw5i6GiQnB3QZ55ie7ucrI6/P0TQWx+1BEt3xl6tEs/vFqnyFuDOh8fc0ZwYTBWFUWkQfYsv4w==", + "node_modules/@slack/socket-mode/node_modules/@slack/logger": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@slack/logger/-/logger-3.0.0.tgz", + "integrity": "sha512-DTuBFbqu4gGfajREEMrkq5jBhcnskinhr4+AnfJEk48zhVeEv3XnUKGIX98B74kxhYsIMfApGGySTn7V3b5yBA==", "dev": true, "dependencies": { - "@oclif/command": "1.8.11", - "@oclif/config": "1.18.2", - "cli-ux": "5.6.6", - "tslib": "^2.0.0" + "@types/node": ">=12.0.0" }, "engines": { - "node": ">=8.0.0" + "node": ">= 12.13.0", + "npm": ">= 6.12.0" } }, - "node_modules/@oclif/plugin-which/node_modules/@oclif/command": { - "version": "1.8.11", - "resolved": "https://registry.npmjs.org/@oclif/command/-/command-1.8.11.tgz", - "integrity": "sha512-2fGLMvi6J5+oNxTaZfdWPMWY8oW15rYj0V8yLzmZBAEjfzjLqLIzJE9IlNccN1zwRqRHc1bcISSRDdxJ56IS/Q==", - "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", + "node_modules/@slack/socket-mode/node_modules/ws": { + "version": "7.5.9", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", + "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", "dev": true, - "dependencies": { - "@oclif/config": "^1.18.2", - "@oclif/errors": "^1.3.5", - "@oclif/parser": "^3.8.6", - "@oclif/plugin-help": "3.2.14", - "debug": "^4.1.1", - "semver": "^7.3.2" - }, "engines": { - "node": ">=12.0.0" + "node": ">=8.3.0" }, "peerDependencies": { - "@oclif/config": "^1" + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } } }, - "node_modules/@oclif/plugin-which/node_modules/@oclif/config": { - "version": "1.18.2", - "resolved": "https://registry.npmjs.org/@oclif/config/-/config-1.18.2.tgz", - "integrity": "sha512-cE3qfHWv8hGRCP31j7fIS7BfCflm/BNZ2HNqHexH+fDrdF2f1D5S8VmXWLC77ffv3oDvWyvE9AZeR0RfmHCCaA==", - "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", + "node_modules/@slack/types": { + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/@slack/types/-/types-2.11.0.tgz", + "integrity": "sha512-UlIrDWvuLaDly3QZhCPnwUSI/KYmV1N9LyhuH6EDKCRS1HWZhyTG3Ja46T3D0rYfqdltKYFXbJSSRPwZpwO0cQ==", "dev": true, - "dependencies": { - "@oclif/errors": "^1.3.3", - "@oclif/parser": "^3.8.0", - "debug": "^4.1.1", - "globby": "^11.0.1", - "is-wsl": "^2.1.1", - "tslib": "^2.0.0" - }, "engines": { - "node": ">=8.0.0" + "node": ">= 12.13.0", + "npm": ">= 6.12.0" } }, - "node_modules/@oclif/plugin-which/node_modules/@oclif/plugin-help": { - "version": "3.2.14", - "resolved": "https://registry.npmjs.org/@oclif/plugin-help/-/plugin-help-3.2.14.tgz", - "integrity": "sha512-NP5qmE2YfcW3MmXjcrxiqKe9Hf3G0uK/qNc0zAMYKU4crFyIsWj7dBfQVFZSb28YXGioOOpjMzG1I7VMxKF38Q==", + "node_modules/@slack/web-api": { + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@slack/web-api/-/web-api-6.12.0.tgz", + "integrity": "sha512-RPw6F8rWfGveGkZEJ4+4jUin5iazxRK2q3FpQDz/FvdgzC3nZmPyLx8WRzc6nh0w3MBjEbphNnp2VZksfhpBIQ==", "dev": true, "dependencies": { - "@oclif/command": "^1.8.9", - "@oclif/config": "^1.18.2", - "@oclif/errors": "^1.3.5", - "chalk": "^4.1.2", - "indent-string": "^4.0.0", - "lodash": "^4.17.21", - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "widest-line": "^3.1.0", - "wrap-ansi": "^6.2.0" + "@slack/logger": "^3.0.0", + "@slack/types": "^2.11.0", + "@types/is-stream": "^1.1.0", + "@types/node": ">=12.0.0", + "axios": "^1.6.5", + "eventemitter3": "^3.1.0", + "form-data": "^2.5.0", + "is-electron": "2.2.2", + "is-stream": "^1.1.0", + "p-queue": "^6.6.1", + "p-retry": "^4.0.0" + }, + "engines": { + "node": ">= 12.13.0", + "npm": ">= 6.12.0" + } + }, + "node_modules/@slack/web-api/node_modules/@slack/logger": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@slack/logger/-/logger-3.0.0.tgz", + "integrity": "sha512-DTuBFbqu4gGfajREEMrkq5jBhcnskinhr4+AnfJEk48zhVeEv3XnUKGIX98B74kxhYsIMfApGGySTn7V3b5yBA==", + "dev": true, + "dependencies": { + "@types/node": ">=12.0.0" }, "engines": { - "node": ">=8.0.0" + "node": ">= 12.13.0", + "npm": ">= 6.12.0" } }, - "node_modules/@oclif/plugin-which/node_modules/ansi-escapes": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", - "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "node_modules/@slack/web-api/node_modules/p-queue": { + "version": "6.6.2", + "resolved": "https://registry.npmjs.org/p-queue/-/p-queue-6.6.2.tgz", + "integrity": "sha512-RwFpb72c/BhQLEXIZ5K2e+AhgNVmIejGlTgiB9MzZ0e93GRvqZ7uSi0dvRF7/XIXDeNkra2fNHBxTyPDGySpjQ==", "dev": true, "dependencies": { - "type-fest": "^0.21.3" + "eventemitter3": "^4.0.4", + "p-timeout": "^3.2.0" }, "engines": { "node": ">=8" @@ -2951,712 +4405,694 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@oclif/plugin-which/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "node_modules/@slack/web-api/node_modules/p-queue/node_modules/eventemitter3": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", + "dev": true + }, + "node_modules/@smithy/abort-controller": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-2.2.0.tgz", + "integrity": "sha512-wRlta7GuLWpTqtFfGo+nZyOO1vEvewdNR1R4rTxpC8XU6vG/NDyrFBhwLZsqg1NUoR1noVaXJPC/7ZK47QCySw==", "dev": true, "dependencies": { - "color-convert": "^2.0.1" + "@smithy/types": "^2.12.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "node": ">=14.0.0" } }, - "node_modules/@oclif/plugin-which/node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "node_modules/@smithy/chunked-blob-reader": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/chunked-blob-reader/-/chunked-blob-reader-2.2.0.tgz", + "integrity": "sha512-3GJNvRwXBGdkDZZOGiziVYzDpn4j6zfyULHMDKAGIUo72yHALpE9CbhfQp/XcLNVoc1byfMpn6uW5H2BqPjgaQ==", "dev": true, "dependencies": { - "sprintf-js": "~1.0.2" + "tslib": "^2.6.2" } }, - "node_modules/@oclif/plugin-which/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "node_modules/@smithy/chunked-blob-reader-native": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/chunked-blob-reader-native/-/chunked-blob-reader-native-2.2.0.tgz", + "integrity": "sha512-VNB5+1oCgX3Fzs072yuRsUoC2N4Zg/LJ11DTxX3+Qu+Paa6AmbIF0E9sc2wthz9Psrk/zcOlTCyuposlIhPjZQ==", "dev": true, "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "@smithy/util-base64": "^2.3.0", + "tslib": "^2.6.2" } }, - "node_modules/@oclif/plugin-which/node_modules/cli-ux": { - "version": "5.6.6", - "resolved": "https://registry.npmjs.org/cli-ux/-/cli-ux-5.6.6.tgz", - "integrity": "sha512-4wUB34zoFklcZV0z5YiOM5IqVMMt9c3TK3QYRK3dqyk3XoRC0ybiWDWHfsMDjkKrzsVTw95rXn9NrzSHbae4pg==", - "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", + "node_modules/@smithy/config-resolver": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/config-resolver/-/config-resolver-2.2.0.tgz", + "integrity": "sha512-fsiMgd8toyUba6n1WRmr+qACzXltpdDkPTAaDqc8QqPBUzO+/JKwL6bUBseHVi8tu9l+3JOK+tSf7cay+4B3LA==", "dev": true, "dependencies": { - "@oclif/command": "^1.8.9", - "@oclif/errors": "^1.3.5", - "@oclif/linewrap": "^1.0.0", - "@oclif/screen": "^1.0.4", - "ansi-escapes": "^4.3.0", - "ansi-styles": "^4.2.0", - "cardinal": "^2.1.1", - "chalk": "^4.1.0", - "clean-stack": "^3.0.0", - "cli-progress": "^3.4.0", - "extract-stack": "^2.0.0", - "fs-extra": "^8.1", - "hyperlinker": "^1.0.0", - "indent-string": "^4.0.0", - "is-wsl": "^2.2.0", - "js-yaml": "^3.13.1", - "lodash": "^4.17.21", - "natural-orderby": "^2.0.1", - "object-treeify": "^1.1.4", - "password-prompt": "^1.1.2", - "semver": "^7.3.2", - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "supports-color": "^8.1.0", - "supports-hyperlinks": "^2.1.0", - "tslib": "^2.0.0" + "@smithy/node-config-provider": "^2.3.0", + "@smithy/types": "^2.12.0", + "@smithy/util-config-provider": "^2.3.0", + "@smithy/util-middleware": "^2.2.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=8.0.0" + "node": ">=14.0.0" } }, - "node_modules/@oclif/plugin-which/node_modules/cli-ux/node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "node_modules/@smithy/core": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/@smithy/core/-/core-1.4.2.tgz", + "integrity": "sha512-2fek3I0KZHWJlRLvRTqxTEri+qV0GRHrJIoLFuBMZB4EMg4WgeBGfF0X6abnrNYpq55KJ6R4D6x4f0vLnhzinA==", "dev": true, "dependencies": { - "has-flag": "^4.0.0" + "@smithy/middleware-endpoint": "^2.5.1", + "@smithy/middleware-retry": "^2.3.1", + "@smithy/middleware-serde": "^2.3.0", + "@smithy/protocol-http": "^3.3.0", + "@smithy/smithy-client": "^2.5.1", + "@smithy/types": "^2.12.0", + "@smithy/util-middleware": "^2.2.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" + "node": ">=14.0.0" } }, - "node_modules/@oclif/plugin-which/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "node_modules/@smithy/credential-provider-imds": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-2.3.0.tgz", + "integrity": "sha512-BWB9mIukO1wjEOo1Ojgl6LrG4avcaC7T/ZP6ptmAaW4xluhSIPZhY+/PI5YKzlk+jsm+4sQZB45Bt1OfMeQa3w==", "dev": true, "dependencies": { - "color-name": "~1.1.4" + "@smithy/node-config-provider": "^2.3.0", + "@smithy/property-provider": "^2.2.0", + "@smithy/types": "^2.12.0", + "@smithy/url-parser": "^2.2.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=7.0.0" + "node": ">=14.0.0" } }, - "node_modules/@oclif/plugin-which/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/@oclif/plugin-which/node_modules/extract-stack": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/extract-stack/-/extract-stack-2.0.0.tgz", - "integrity": "sha512-AEo4zm+TenK7zQorGK1f9mJ8L14hnTDi2ZQPR+Mub1NX8zimka1mXpV5LpH8x9HoUmFSHZCfLHqWvp0Y4FxxzQ==", + "node_modules/@smithy/eventstream-codec": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-codec/-/eventstream-codec-2.2.0.tgz", + "integrity": "sha512-8janZoJw85nJmQZc4L8TuePp2pk1nxLgkxIR0TUjKJ5Dkj5oelB9WtiSSGXCQvNsJl0VSTvK/2ueMXxvpa9GVw==", "dev": true, - "engines": { - "node": ">=8" + "dependencies": { + "@aws-crypto/crc32": "3.0.0", + "@smithy/types": "^2.12.0", + "@smithy/util-hex-encoding": "^2.2.0", + "tslib": "^2.6.2" } }, - "node_modules/@oclif/plugin-which/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "node_modules/@smithy/eventstream-serde-browser": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-browser/-/eventstream-serde-browser-2.2.0.tgz", + "integrity": "sha512-UaPf8jKbcP71BGiO0CdeLmlg+RhWnlN8ipsMSdwvqBFigl5nil3rHOI/5GE3tfiuX8LvY5Z9N0meuU7Rab7jWw==", "dev": true, + "dependencies": { + "@smithy/eventstream-serde-universal": "^2.2.0", + "@smithy/types": "^2.12.0", + "tslib": "^2.6.2" + }, "engines": { - "node": ">=8" + "node": ">=14.0.0" } }, - "node_modules/@oclif/plugin-which/node_modules/js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "node_modules/@smithy/eventstream-serde-config-resolver": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-config-resolver/-/eventstream-serde-config-resolver-2.2.0.tgz", + "integrity": "sha512-RHhbTw/JW3+r8QQH7PrganjNCiuiEZmpi6fYUAetFfPLfZ6EkiA08uN3EFfcyKubXQxOwTeJRZSQmDDCdUshaA==", "dev": true, "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" + "@smithy/types": "^2.12.0", + "tslib": "^2.6.2" }, - "bin": { - "js-yaml": "bin/js-yaml.js" + "engines": { + "node": ">=14.0.0" } }, - "node_modules/@oclif/plugin-which/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "node_modules/@smithy/eventstream-serde-node": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-node/-/eventstream-serde-node-2.2.0.tgz", + "integrity": "sha512-zpQMtJVqCUMn+pCSFcl9K/RPNtQE0NuMh8sKpCdEHafhwRsjP50Oq/4kMmvxSRy6d8Jslqd8BLvDngrUtmN9iA==", "dev": true, "dependencies": { - "has-flag": "^4.0.0" + "@smithy/eventstream-serde-universal": "^2.2.0", + "@smithy/types": "^2.12.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=8" + "node": ">=14.0.0" } }, - "node_modules/@oclif/plugin-which/node_modules/supports-hyperlinks": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-2.3.0.tgz", - "integrity": "sha512-RpsAZlpWcDwOPQA22aCH4J0t7L8JmAvsCxfOSEwm7cQs3LshN36QaTkwd70DnBOXDWGssw2eUoc8CaRWT0XunA==", + "node_modules/@smithy/eventstream-serde-universal": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-universal/-/eventstream-serde-universal-2.2.0.tgz", + "integrity": "sha512-pvoe/vvJY0mOpuF84BEtyZoYfbehiFj8KKWk1ds2AT0mTLYFVs+7sBJZmioOFdBXKd48lfrx1vumdPdmGlCLxA==", "dev": true, "dependencies": { - "has-flag": "^4.0.0", - "supports-color": "^7.0.0" + "@smithy/eventstream-codec": "^2.2.0", + "@smithy/types": "^2.12.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=8" + "node": ">=14.0.0" } }, - "node_modules/@oclif/plugin-which/node_modules/type-fest": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", - "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "node_modules/@smithy/fetch-http-handler": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-2.5.0.tgz", + "integrity": "sha512-BOWEBeppWhLn/no/JxUL/ghTfANTjT7kg3Ww2rPqTUY9R4yHPXxJ9JhMe3Z03LN3aPwiwlpDIUcVw1xDyHqEhw==", "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "dependencies": { + "@smithy/protocol-http": "^3.3.0", + "@smithy/querystring-builder": "^2.2.0", + "@smithy/types": "^2.12.0", + "@smithy/util-base64": "^2.3.0", + "tslib": "^2.6.2" } }, - "node_modules/@oclif/plugin-which/node_modules/wrap-ansi": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", - "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "node_modules/@smithy/hash-blob-browser": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/hash-blob-browser/-/hash-blob-browser-2.2.0.tgz", + "integrity": "sha512-SGPoVH8mdXBqrkVCJ1Hd1X7vh1zDXojNN1yZyZTZsCno99hVue9+IYzWDjq/EQDDXxmITB0gBmuyPh8oAZSTcg==", "dev": true, "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" + "@smithy/chunked-blob-reader": "^2.2.0", + "@smithy/chunked-blob-reader-native": "^2.2.0", + "@smithy/types": "^2.12.0", + "tslib": "^2.6.2" + } + }, + "node_modules/@smithy/hash-node": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/hash-node/-/hash-node-2.2.0.tgz", + "integrity": "sha512-zLWaC/5aWpMrHKpoDF6nqpNtBhlAYKF/7+9yMN7GpdR8CzohnWfGtMznPybnwSS8saaXBMxIGwJqR4HmRp6b3g==", + "dev": true, + "dependencies": { + "@smithy/types": "^2.12.0", + "@smithy/util-buffer-from": "^2.2.0", + "@smithy/util-utf8": "^2.3.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=8" + "node": ">=14.0.0" } }, - "node_modules/@oclif/screen": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@oclif/screen/-/screen-1.0.4.tgz", - "integrity": "sha512-60CHpq+eqnTxLZQ4PGHYNwUX572hgpMHGPtTWMjdTMsAvlm69lZV/4ly6O3sAYkomo4NggGcomrDpBe34rxUqw==", - "deprecated": "Deprecated in favor of @oclif/core", + "node_modules/@smithy/hash-stream-node": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/hash-stream-node/-/hash-stream-node-2.2.0.tgz", + "integrity": "sha512-aT+HCATOSRMGpPI7bi7NSsTNVZE/La9IaxLXWoVAYMxHT5hGO3ZOGEMZQg8A6nNL+pdFGtZQtND1eoY084HgHQ==", "dev": true, + "dependencies": { + "@smithy/types": "^2.12.0", + "@smithy/util-utf8": "^2.3.0", + "tslib": "^2.6.2" + }, "engines": { - "node": ">=8.0.0" + "node": ">=14.0.0" } }, - "node_modules/@octokit/auth-token": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-2.5.0.tgz", - "integrity": "sha512-r5FVUJCOLl19AxiuZD2VRZ/ORjp/4IN98Of6YJoJOkY75CIBuYfmiNHGrDwXr+aLGG55igl9QrxX3hbiXlLb+g==", + "node_modules/@smithy/invalid-dependency": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/invalid-dependency/-/invalid-dependency-2.2.0.tgz", + "integrity": "sha512-nEDASdbKFKPXN2O6lOlTgrEEOO9NHIeO+HVvZnkqc8h5U9g3BIhWsvzFo+UcUbliMHvKNPD/zVxDrkP1Sbgp8Q==", "dev": true, "dependencies": { - "@octokit/types": "^6.0.3" + "@smithy/types": "^2.12.0", + "tslib": "^2.6.2" } }, - "node_modules/@octokit/core": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/@octokit/core/-/core-3.6.0.tgz", - "integrity": "sha512-7RKRKuA4xTjMhY+eG3jthb3hlZCsOwg3rztWh75Xc+ShDWOfDDATWbeZpAHBNRpm4Tv9WgBMOy1zEJYXG6NJ7Q==", + "node_modules/@smithy/is-array-buffer": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-2.2.0.tgz", + "integrity": "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==", "dev": true, "dependencies": { - "@octokit/auth-token": "^2.4.4", - "@octokit/graphql": "^4.5.8", - "@octokit/request": "^5.6.3", - "@octokit/request-error": "^2.0.5", - "@octokit/types": "^6.0.3", - "before-after-hook": "^2.2.0", - "universal-user-agent": "^6.0.0" + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" } }, - "node_modules/@octokit/endpoint": { - "version": "6.0.12", - "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-6.0.12.tgz", - "integrity": "sha512-lF3puPwkQWGfkMClXb4k/eUT/nZKQfxinRWJrdZaJO85Dqwo/G0yOC434Jr2ojwafWJMYqFGFa5ms4jJUgujdA==", + "node_modules/@smithy/md5-js": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/md5-js/-/md5-js-2.2.0.tgz", + "integrity": "sha512-M26XTtt9IIusVMOWEAhIvFIr9jYj4ISPPGJROqw6vXngO3IYJCnVVSMFn4Tx1rUTG5BiKJNg9u2nxmBiZC5IlQ==", "dev": true, "dependencies": { - "@octokit/types": "^6.0.3", - "is-plain-object": "^5.0.0", - "universal-user-agent": "^6.0.0" + "@smithy/types": "^2.12.0", + "@smithy/util-utf8": "^2.3.0", + "tslib": "^2.6.2" + } + }, + "node_modules/@smithy/middleware-content-length": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/middleware-content-length/-/middleware-content-length-2.2.0.tgz", + "integrity": "sha512-5bl2LG1Ah/7E5cMSC+q+h3IpVHMeOkG0yLRyQT1p2aMJkSrZG7RlXHPuAgb7EyaFeidKEnnd/fNaLLaKlHGzDQ==", + "dev": true, + "dependencies": { + "@smithy/protocol-http": "^3.3.0", + "@smithy/types": "^2.12.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" } }, - "node_modules/@octokit/graphql": { - "version": "4.8.0", - "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-4.8.0.tgz", - "integrity": "sha512-0gv+qLSBLKF0z8TKaSKTsS39scVKF9dbMxJpj3U0vC7wjNWFuIpL/z76Qe2fiuCbDRcJSavkXsVtMS6/dtQQsg==", + "node_modules/@smithy/middleware-endpoint": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-2.5.1.tgz", + "integrity": "sha512-1/8kFp6Fl4OsSIVTWHnNjLnTL8IqpIb/D3sTSczrKFnrE9VMNWxnrRKNvpUHOJ6zpGD5f62TPm7+17ilTJpiCQ==", "dev": true, "dependencies": { - "@octokit/request": "^5.6.0", - "@octokit/types": "^6.0.3", - "universal-user-agent": "^6.0.0" + "@smithy/middleware-serde": "^2.3.0", + "@smithy/node-config-provider": "^2.3.0", + "@smithy/shared-ini-file-loader": "^2.4.0", + "@smithy/types": "^2.12.0", + "@smithy/url-parser": "^2.2.0", + "@smithy/util-middleware": "^2.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" } }, - "node_modules/@octokit/openapi-types": { - "version": "12.11.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-12.11.0.tgz", - "integrity": "sha512-VsXyi8peyRq9PqIz/tpqiL2w3w80OgVMwBHltTml3LmVvXiphgeqmY9mvBw9Wu7e0QWk/fqD37ux8yP5uVekyQ==", - "dev": true - }, - "node_modules/@octokit/plugin-paginate-rest": { - "version": "2.21.3", - "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-2.21.3.tgz", - "integrity": "sha512-aCZTEf0y2h3OLbrgKkrfFdjRL6eSOo8komneVQJnYecAxIej7Bafor2xhuDJOIFau4pk0i/P28/XgtbyPF0ZHw==", + "node_modules/@smithy/middleware-retry": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-2.3.1.tgz", + "integrity": "sha512-P2bGufFpFdYcWvqpyqqmalRtwFUNUA8vHjJR5iGqbfR6mp65qKOLcUd6lTr4S9Gn/enynSrSf3p3FVgVAf6bXA==", "dev": true, "dependencies": { - "@octokit/types": "^6.40.0" + "@smithy/node-config-provider": "^2.3.0", + "@smithy/protocol-http": "^3.3.0", + "@smithy/service-error-classification": "^2.1.5", + "@smithy/smithy-client": "^2.5.1", + "@smithy/types": "^2.12.0", + "@smithy/util-middleware": "^2.2.0", + "@smithy/util-retry": "^2.2.0", + "tslib": "^2.6.2", + "uuid": "^9.0.1" }, - "peerDependencies": { - "@octokit/core": ">=2" + "engines": { + "node": ">=14.0.0" } }, - "node_modules/@octokit/plugin-request-log": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-1.0.4.tgz", - "integrity": "sha512-mLUsMkgP7K/cnFEw07kWqXGF5LKrOkD+lhCrKvPHXWDywAwuDUeDwWBpc69XK3pNX0uKiVt8g5z96PJ6z9xCFA==", + "node_modules/@smithy/middleware-serde": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-2.3.0.tgz", + "integrity": "sha512-sIADe7ojwqTyvEQBe1nc/GXB9wdHhi9UwyX0lTyttmUWDJLP655ZYE1WngnNyXREme8I27KCaUhyhZWRXL0q7Q==", "dev": true, - "peerDependencies": { - "@octokit/core": ">=3" + "dependencies": { + "@smithy/types": "^2.12.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" } }, - "node_modules/@octokit/plugin-rest-endpoint-methods": { - "version": "5.16.2", - "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-5.16.2.tgz", - "integrity": "sha512-8QFz29Fg5jDuTPXVtey05BLm7OB+M8fnvE64RNegzX7U+5NUXcOcnpTIK0YfSHBg8gYd0oxIq3IZTe9SfPZiRw==", + "node_modules/@smithy/middleware-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/middleware-stack/-/middleware-stack-2.2.0.tgz", + "integrity": "sha512-Qntc3jrtwwrsAC+X8wms8zhrTr0sFXnyEGhZd9sLtsJ/6gGQKFzNB+wWbOcpJd7BR8ThNCoKt76BuQahfMvpeA==", "dev": true, "dependencies": { - "@octokit/types": "^6.39.0", - "deprecation": "^2.3.1" + "@smithy/types": "^2.12.0", + "tslib": "^2.6.2" }, - "peerDependencies": { - "@octokit/core": ">=3" + "engines": { + "node": ">=14.0.0" } }, - "node_modules/@octokit/request": { - "version": "5.6.3", - "resolved": "https://registry.npmjs.org/@octokit/request/-/request-5.6.3.tgz", - "integrity": "sha512-bFJl0I1KVc9jYTe9tdGGpAMPy32dLBXXo1dS/YwSCTL/2nd9XeHsY616RE3HPXDVk+a+dBuzyz5YdlXwcDTr2A==", + "node_modules/@smithy/node-config-provider": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-2.3.0.tgz", + "integrity": "sha512-0elK5/03a1JPWMDPaS726Iw6LpQg80gFut1tNpPfxFuChEEklo2yL823V94SpTZTxmKlXFtFgsP55uh3dErnIg==", "dev": true, "dependencies": { - "@octokit/endpoint": "^6.0.1", - "@octokit/request-error": "^2.1.0", - "@octokit/types": "^6.16.1", - "is-plain-object": "^5.0.0", - "node-fetch": "^2.6.7", - "universal-user-agent": "^6.0.0" + "@smithy/property-provider": "^2.2.0", + "@smithy/shared-ini-file-loader": "^2.4.0", + "@smithy/types": "^2.12.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" } }, - "node_modules/@octokit/request-error": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-2.1.0.tgz", - "integrity": "sha512-1VIvgXxs9WHSjicsRwq8PlR2LR2x6DwsJAaFgzdi0JfJoGSO8mYI/cHJQ+9FbN21aa+DrgNLnwObmyeSC8Rmpg==", + "node_modules/@smithy/node-http-handler": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-2.5.0.tgz", + "integrity": "sha512-mVGyPBzkkGQsPoxQUbxlEfRjrj6FPyA3u3u2VXGr9hT8wilsoQdZdvKpMBFMB8Crfhv5dNkKHIW0Yyuc7eABqA==", "dev": true, "dependencies": { - "@octokit/types": "^6.0.3", - "deprecation": "^2.0.0", - "once": "^1.4.0" + "@smithy/abort-controller": "^2.2.0", + "@smithy/protocol-http": "^3.3.0", + "@smithy/querystring-builder": "^2.2.0", + "@smithy/types": "^2.12.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" } }, - "node_modules/@octokit/rest": { - "version": "18.12.0", - "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-18.12.0.tgz", - "integrity": "sha512-gDPiOHlyGavxr72y0guQEhLsemgVjwRePayJ+FcKc2SJqKUbxbkvf5kAZEWA/MKvsfYlQAMVzNJE3ezQcxMJ2Q==", + "node_modules/@smithy/property-provider": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-2.2.0.tgz", + "integrity": "sha512-+xiil2lFhtTRzXkx8F053AV46QnIw6e7MV8od5Mi68E1ICOjCeCHw2XfLnDEUHnT9WGUIkwcqavXjfwuJbGlpg==", "dev": true, "dependencies": { - "@octokit/core": "^3.5.1", - "@octokit/plugin-paginate-rest": "^2.16.8", - "@octokit/plugin-request-log": "^1.0.4", - "@octokit/plugin-rest-endpoint-methods": "^5.12.0" + "@smithy/types": "^2.12.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" } }, - "node_modules/@octokit/types": { - "version": "6.41.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.41.0.tgz", - "integrity": "sha512-eJ2jbzjdijiL3B4PrSQaSjuF2sPEQPVCPzBvTHJD9Nz+9dw2SGH4K4xeQJ77YfTq5bRQ+bD8wT11JbeDPmxmGg==", + "node_modules/@smithy/protocol-http": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-3.3.0.tgz", + "integrity": "sha512-Xy5XK1AFWW2nlY/biWZXu6/krgbaf2dg0q492D8M5qthsnU2H+UgFeZLbM76FnH7s6RO/xhQRkj+T6KBO3JzgQ==", "dev": true, "dependencies": { - "@octokit/openapi-types": "^12.11.0" + "@smithy/types": "^2.12.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" } }, - "node_modules/@prisma/prisma-fmt-wasm": { - "version": "4.17.0-16.27eb2449f178cd9fe1a4b892d732cc4795f75085", - "resolved": "https://registry.npmjs.org/@prisma/prisma-fmt-wasm/-/prisma-fmt-wasm-4.17.0-16.27eb2449f178cd9fe1a4b892d732cc4795f75085.tgz", - "integrity": "sha512-zYz3rFwPB82mVlHGknAPdnSY/a308dhPOblxQLcZgZTDRtDXOE1MgxoRAys+jekwR4/bm3+rZDPs1xsFMsPZig==", - "optional": true - }, - "node_modules/@protobufjs/aspromise": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", - "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==" - }, - "node_modules/@protobufjs/base64": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", - "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==" - }, - "node_modules/@protobufjs/codegen": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", - "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==" - }, - "node_modules/@protobufjs/eventemitter": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", - "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==" - }, - "node_modules/@protobufjs/fetch": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", - "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==", + "node_modules/@smithy/querystring-builder": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-2.2.0.tgz", + "integrity": "sha512-L1kSeviUWL+emq3CUVSgdogoM/D9QMFaqxL/dd0X7PCNWmPXqt+ExtrBjqT0V7HLN03Vs9SuiLrG3zy3JGnE5A==", + "dev": true, "dependencies": { - "@protobufjs/aspromise": "^1.1.1", - "@protobufjs/inquire": "^1.1.0" + "@smithy/types": "^2.12.0", + "@smithy/util-uri-escape": "^2.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" } }, - "node_modules/@protobufjs/float": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", - "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==" - }, - "node_modules/@protobufjs/inquire": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", - "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==" - }, - "node_modules/@protobufjs/path": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", - "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==" - }, - "node_modules/@protobufjs/pool": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", - "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==" - }, - "node_modules/@protobufjs/utf8": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", - "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==" - }, - "node_modules/@sindresorhus/is": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz", - "integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==", + "node_modules/@smithy/querystring-parser": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/querystring-parser/-/querystring-parser-2.2.0.tgz", + "integrity": "sha512-BvHCDrKfbG5Yhbpj4vsbuPV2GgcpHiAkLeIlcA1LtfpMz3jrqizP1+OguSNSj1MwBHEiN+jwNisXLGdajGDQJA==", "dev": true, - "engines": { - "node": ">=10" + "dependencies": { + "@smithy/types": "^2.12.0", + "tslib": "^2.6.2" }, - "funding": { - "url": "https://github.com/sindresorhus/is?sponsor=1" + "engines": { + "node": ">=14.0.0" } }, - "node_modules/@sinonjs/commons": { - "version": "1.8.6", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.6.tgz", - "integrity": "sha512-Ky+XkAkqPZSm3NLBeUng77EBQl3cmeJhITaGHdYH8kjVB+aun3S4XBRti2zt17mtt0mIUDiNxYeoJm6drVvBJQ==", + "node_modules/@smithy/service-error-classification": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@smithy/service-error-classification/-/service-error-classification-2.1.5.tgz", + "integrity": "sha512-uBDTIBBEdAQryvHdc5W8sS5YX7RQzF683XrHePVdFmAgKiMofU15FLSM0/HU03hKTnazdNRFa0YHS7+ArwoUSQ==", "dev": true, "dependencies": { - "type-detect": "4.0.8" + "@smithy/types": "^2.12.0" + }, + "engines": { + "node": ">=14.0.0" } }, - "node_modules/@sinonjs/formatio": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@sinonjs/formatio/-/formatio-2.0.0.tgz", - "integrity": "sha512-ls6CAMA6/5gG+O/IdsBcblvnd8qcO/l1TYoNeAzp3wcISOxlPXQEus0mLcdwazEkWjaBdaJ3TaxmNgCLWwvWzg==", + "node_modules/@smithy/shared-ini-file-loader": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-2.4.0.tgz", + "integrity": "sha512-WyujUJL8e1B6Z4PBfAqC/aGY1+C7T0w20Gih3yrvJSk97gpiVfB+y7c46T4Nunk+ZngLq0rOIdeVeIklk0R3OA==", "dev": true, "dependencies": { - "samsam": "1.3.0" + "@smithy/types": "^2.12.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" } }, - "node_modules/@sinonjs/samsam": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-3.3.3.tgz", - "integrity": "sha512-bKCMKZvWIjYD0BLGnNrxVuw4dkWCYsLqFOUWw8VgKF/+5Y+mE7LfHWPIYoDXowH+3a9LsWDMo0uAP8YDosPvHQ==", + "node_modules/@smithy/signature-v4": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-2.3.0.tgz", + "integrity": "sha512-ui/NlpILU+6HAQBfJX8BBsDXuKSNrjTSuOYArRblcrErwKFutjrCNb/OExfVRyj9+26F9J+ZmfWT+fKWuDrH3Q==", "dev": true, "dependencies": { - "@sinonjs/commons": "^1.3.0", - "array-from": "^2.1.1", - "lodash": "^4.17.15" + "@smithy/is-array-buffer": "^2.2.0", + "@smithy/types": "^2.12.0", + "@smithy/util-hex-encoding": "^2.2.0", + "@smithy/util-middleware": "^2.2.0", + "@smithy/util-uri-escape": "^2.2.0", + "@smithy/util-utf8": "^2.3.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" } }, - "node_modules/@sinonjs/text-encoding": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.2.tgz", - "integrity": "sha512-sXXKG+uL9IrKqViTtao2Ws6dy0znu9sOaP1di/jKGW1M6VssO8vlpXCQcpZ+jisQ1tTFAC5Jo/EOzFbggBagFQ==", - "dev": true - }, - "node_modules/@slack/bolt": { - "version": "3.17.1", - "resolved": "https://registry.npmjs.org/@slack/bolt/-/bolt-3.17.1.tgz", - "integrity": "sha512-N+4WxpkM59RXi7BL3IXUtENnn9cF7TOBn7ttaHpgvlnjUaro+yQyY60arXTlP4ytVDFJ1w0mSdfftcM17h+i2w==", + "node_modules/@smithy/smithy-client": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-2.5.1.tgz", + "integrity": "sha512-jrbSQrYCho0yDaaf92qWgd+7nAeap5LtHTI51KXqmpIFCceKU3K9+vIVTUH72bOJngBMqa4kyu1VJhRcSrk/CQ==", "dev": true, "dependencies": { - "@slack/logger": "^4.0.0", - "@slack/oauth": "^2.6.2", - "@slack/socket-mode": "^1.3.3", - "@slack/types": "^2.11.0", - "@slack/web-api": "^6.11.2", - "@types/express": "^4.16.1", - "@types/promise.allsettled": "^1.0.3", - "@types/tsscmp": "^1.0.0", - "axios": "^1.6.0", - "express": "^4.16.4", - "path-to-regexp": "^6.2.1", - "please-upgrade-node": "^3.2.0", - "promise.allsettled": "^1.0.2", - "raw-body": "^2.3.3", - "tsscmp": "^1.0.6" + "@smithy/middleware-endpoint": "^2.5.1", + "@smithy/middleware-stack": "^2.2.0", + "@smithy/protocol-http": "^3.3.0", + "@smithy/types": "^2.12.0", + "@smithy/util-stream": "^2.2.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=12.13.0", - "npm": ">=6.12.0" + "node": ">=14.0.0" } }, - "node_modules/@slack/logger": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@slack/logger/-/logger-4.0.0.tgz", - "integrity": "sha512-Wz7QYfPAlG/DR+DfABddUZeNgoeY7d1J39OCR2jR+v7VBsB8ezulDK5szTnDDPDwLH5IWhLvXIHlCFZV7MSKgA==", + "node_modules/@smithy/types": { + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/@smithy/types/-/types-2.12.0.tgz", + "integrity": "sha512-QwYgloJ0sVNBeBuBs65cIkTbfzV/Q6ZNPCJ99EICFEdJYG50nGIY/uYXp+TbsdJReIuPr0a0kXmCvren3MbRRw==", "dev": true, "dependencies": { - "@types/node": ">=18.0.0" + "tslib": "^2.6.2" }, "engines": { - "node": ">= 18", - "npm": ">= 8.6.0" + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/url-parser": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/url-parser/-/url-parser-2.2.0.tgz", + "integrity": "sha512-hoA4zm61q1mNTpksiSWp2nEl1dt3j726HdRhiNgVJQMj7mLp7dprtF57mOB6JvEk/x9d2bsuL5hlqZbBuHQylQ==", + "dev": true, + "dependencies": { + "@smithy/querystring-parser": "^2.2.0", + "@smithy/types": "^2.12.0", + "tslib": "^2.6.2" } }, - "node_modules/@slack/oauth": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/@slack/oauth/-/oauth-2.6.2.tgz", - "integrity": "sha512-2R3MyB/R63hTRXzk5J6wcui59TBxXzhk+Uh2/Xu3Wp3O4pXg/BNucQhP/DQbL/ScVhLvFtMXirLrKi0Yo5gIVw==", + "node_modules/@smithy/util-base64": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@smithy/util-base64/-/util-base64-2.3.0.tgz", + "integrity": "sha512-s3+eVwNeJuXUwuMbusncZNViuhv2LjVJ1nMwTqSA0XAC7gjKhqqxRdJPhR8+YrkoZ9IiIbFk/yK6ACe/xlF+hw==", "dev": true, "dependencies": { - "@slack/logger": "^3.0.0", - "@slack/web-api": "^6.11.2", - "@types/jsonwebtoken": "^8.3.7", - "@types/node": ">=12", - "jsonwebtoken": "^9.0.0", - "lodash.isstring": "^4.0.1" + "@smithy/util-buffer-from": "^2.2.0", + "@smithy/util-utf8": "^2.3.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=12.13.0", - "npm": ">=6.12.0" + "node": ">=14.0.0" } }, - "node_modules/@slack/oauth/node_modules/@slack/logger": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@slack/logger/-/logger-3.0.0.tgz", - "integrity": "sha512-DTuBFbqu4gGfajREEMrkq5jBhcnskinhr4+AnfJEk48zhVeEv3XnUKGIX98B74kxhYsIMfApGGySTn7V3b5yBA==", + "node_modules/@smithy/util-body-length-browser": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/util-body-length-browser/-/util-body-length-browser-2.2.0.tgz", + "integrity": "sha512-dtpw9uQP7W+n3vOtx0CfBD5EWd7EPdIdsQnWTDoFf77e3VUf05uA7R7TGipIo8e4WL2kuPdnsr3hMQn9ziYj5w==", "dev": true, "dependencies": { - "@types/node": ">=12.0.0" - }, - "engines": { - "node": ">= 12.13.0", - "npm": ">= 6.12.0" + "tslib": "^2.6.2" } }, - "node_modules/@slack/socket-mode": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/@slack/socket-mode/-/socket-mode-1.3.3.tgz", - "integrity": "sha512-vN3zG4woRtf2Ut6rZgRW6G/Oe56uLMlnz39I08Q7DOvVfB+1MmDbNv0PNOiFgujdKXJR+bXF41/F/VvryXcqlw==", + "node_modules/@smithy/util-body-length-node": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@smithy/util-body-length-node/-/util-body-length-node-2.3.0.tgz", + "integrity": "sha512-ITWT1Wqjubf2CJthb0BuT9+bpzBfXeMokH/AAa5EJQgbv9aPMVfnM76iFIZVFf50hYXGbtiV71BHAthNWd6+dw==", "dev": true, "dependencies": { - "@slack/logger": "^3.0.0", - "@slack/web-api": "^6.11.2", - "@types/node": ">=12.0.0", - "@types/p-queue": "^2.3.2", - "@types/ws": "^7.4.7", - "eventemitter3": "^3.1.0", - "finity": "^0.5.4", - "p-cancelable": "^1.1.0", - "p-queue": "^2.4.2", - "ws": "^7.5.3" + "tslib": "^2.6.2" }, "engines": { - "node": ">=12.13.0", - "npm": ">=6.12.0" + "node": ">=14.0.0" } }, - "node_modules/@slack/socket-mode/node_modules/@slack/logger": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@slack/logger/-/logger-3.0.0.tgz", - "integrity": "sha512-DTuBFbqu4gGfajREEMrkq5jBhcnskinhr4+AnfJEk48zhVeEv3XnUKGIX98B74kxhYsIMfApGGySTn7V3b5yBA==", + "node_modules/@smithy/util-buffer-from": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-2.2.0.tgz", + "integrity": "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==", "dev": true, "dependencies": { - "@types/node": ">=12.0.0" + "@smithy/is-array-buffer": "^2.2.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">= 12.13.0", - "npm": ">= 6.12.0" + "node": ">=14.0.0" } }, - "node_modules/@slack/socket-mode/node_modules/ws": { - "version": "7.5.9", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", - "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", + "node_modules/@smithy/util-config-provider": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@smithy/util-config-provider/-/util-config-provider-2.3.0.tgz", + "integrity": "sha512-HZkzrRcuFN1k70RLqlNK4FnPXKOpkik1+4JaBoHNJn+RnJGYqaa3c5/+XtLOXhlKzlRgNvyaLieHTW2VwGN0VQ==", "dev": true, - "engines": { - "node": ">=8.3.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" + "dependencies": { + "tslib": "^2.6.2" }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } + "engines": { + "node": ">=14.0.0" } }, - "node_modules/@slack/types": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/@slack/types/-/types-2.11.0.tgz", - "integrity": "sha512-UlIrDWvuLaDly3QZhCPnwUSI/KYmV1N9LyhuH6EDKCRS1HWZhyTG3Ja46T3D0rYfqdltKYFXbJSSRPwZpwO0cQ==", + "node_modules/@smithy/util-defaults-mode-browser": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-2.2.1.tgz", + "integrity": "sha512-RtKW+8j8skk17SYowucwRUjeh4mCtnm5odCL0Lm2NtHQBsYKrNW0od9Rhopu9wF1gHMfHeWF7i90NwBz/U22Kw==", "dev": true, + "dependencies": { + "@smithy/property-provider": "^2.2.0", + "@smithy/smithy-client": "^2.5.1", + "@smithy/types": "^2.12.0", + "bowser": "^2.11.0", + "tslib": "^2.6.2" + }, "engines": { - "node": ">= 12.13.0", - "npm": ">= 6.12.0" + "node": ">= 10.0.0" } }, - "node_modules/@slack/web-api": { - "version": "6.12.0", - "resolved": "https://registry.npmjs.org/@slack/web-api/-/web-api-6.12.0.tgz", - "integrity": "sha512-RPw6F8rWfGveGkZEJ4+4jUin5iazxRK2q3FpQDz/FvdgzC3nZmPyLx8WRzc6nh0w3MBjEbphNnp2VZksfhpBIQ==", + "node_modules/@smithy/util-defaults-mode-node": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-2.3.1.tgz", + "integrity": "sha512-vkMXHQ0BcLFysBMWgSBLSk3+leMpFSyyFj8zQtv5ZyUBx8/owVh1/pPEkzmW/DR/Gy/5c8vjLDD9gZjXNKbrpA==", "dev": true, "dependencies": { - "@slack/logger": "^3.0.0", - "@slack/types": "^2.11.0", - "@types/is-stream": "^1.1.0", - "@types/node": ">=12.0.0", - "axios": "^1.6.5", - "eventemitter3": "^3.1.0", - "form-data": "^2.5.0", - "is-electron": "2.2.2", - "is-stream": "^1.1.0", - "p-queue": "^6.6.1", - "p-retry": "^4.0.0" + "@smithy/config-resolver": "^2.2.0", + "@smithy/credential-provider-imds": "^2.3.0", + "@smithy/node-config-provider": "^2.3.0", + "@smithy/property-provider": "^2.2.0", + "@smithy/smithy-client": "^2.5.1", + "@smithy/types": "^2.12.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">= 12.13.0", - "npm": ">= 6.12.0" + "node": ">= 10.0.0" } }, - "node_modules/@slack/web-api/node_modules/@slack/logger": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@slack/logger/-/logger-3.0.0.tgz", - "integrity": "sha512-DTuBFbqu4gGfajREEMrkq5jBhcnskinhr4+AnfJEk48zhVeEv3XnUKGIX98B74kxhYsIMfApGGySTn7V3b5yBA==", + "node_modules/@smithy/util-endpoints": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@smithy/util-endpoints/-/util-endpoints-1.2.0.tgz", + "integrity": "sha512-BuDHv8zRjsE5zXd3PxFXFknzBG3owCpjq8G3FcsXW3CykYXuEqM3nTSsmLzw5q+T12ZYuDlVUZKBdpNbhVtlrQ==", "dev": true, "dependencies": { - "@types/node": ">=12.0.0" + "@smithy/node-config-provider": "^2.3.0", + "@smithy/types": "^2.12.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">= 12.13.0", - "npm": ">= 6.12.0" + "node": ">= 14.0.0" } }, - "node_modules/@slack/web-api/node_modules/p-queue": { - "version": "6.6.2", - "resolved": "https://registry.npmjs.org/p-queue/-/p-queue-6.6.2.tgz", - "integrity": "sha512-RwFpb72c/BhQLEXIZ5K2e+AhgNVmIejGlTgiB9MzZ0e93GRvqZ7uSi0dvRF7/XIXDeNkra2fNHBxTyPDGySpjQ==", + "node_modules/@smithy/util-hex-encoding": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/util-hex-encoding/-/util-hex-encoding-2.2.0.tgz", + "integrity": "sha512-7iKXR+/4TpLK194pVjKiasIyqMtTYJsgKgM242Y9uzt5dhHnUDvMNb+3xIhRJ9QhvqGii/5cRUt4fJn3dtXNHQ==", "dev": true, "dependencies": { - "eventemitter3": "^4.0.4", - "p-timeout": "^3.2.0" + "tslib": "^2.6.2" }, "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=14.0.0" } }, - "node_modules/@slack/web-api/node_modules/p-queue/node_modules/eventemitter3": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", - "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", - "dev": true - }, - "node_modules/@smithy/eventstream-codec": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@smithy/eventstream-codec/-/eventstream-codec-2.1.1.tgz", - "integrity": "sha512-E8KYBxBIuU4c+zrpR22VsVrOPoEDzk35bQR3E+xm4k6Pa6JqzkDOdMyf9Atac5GPNKHJBdVaQ4JtjdWX2rl/nw==", + "node_modules/@smithy/util-middleware": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-2.2.0.tgz", + "integrity": "sha512-L1qpleXf9QD6LwLCJ5jddGkgWyuSvWBkJwWAZ6kFkdifdso+sk3L3O1HdmPvCdnCK3IS4qWyPxev01QMnfHSBw==", "dev": true, "dependencies": { - "@aws-crypto/crc32": "3.0.0", - "@smithy/types": "^2.9.1", - "@smithy/util-hex-encoding": "^2.1.1", - "tslib": "^2.5.0" + "@smithy/types": "^2.12.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" } }, - "node_modules/@smithy/is-array-buffer": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-2.1.1.tgz", - "integrity": "sha512-xozSQrcUinPpNPNPds4S7z/FakDTh1MZWtRP/2vQtYB/u3HYrX2UXuZs+VhaKBd6Vc7g2XPr2ZtwGBNDN6fNKQ==", + "node_modules/@smithy/util-retry": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-2.2.0.tgz", + "integrity": "sha512-q9+pAFPTfftHXRytmZ7GzLFFrEGavqapFc06XxzZFcSIGERXMerXxCitjOG1prVDR9QdjqotF40SWvbqcCpf8g==", "dev": true, "dependencies": { - "tslib": "^2.5.0" + "@smithy/service-error-classification": "^2.1.5", + "@smithy/types": "^2.12.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">= 14.0.0" } }, - "node_modules/@smithy/types": { - "version": "2.9.1", - "resolved": "https://registry.npmjs.org/@smithy/types/-/types-2.9.1.tgz", - "integrity": "sha512-vjXlKNXyprDYDuJ7UW5iobdmyDm6g8dDG+BFUncAg/3XJaN45Gy5RWWWUVgrzIK7S4R1KWgIX5LeJcfvSI24bw==", + "node_modules/@smithy/util-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-2.2.0.tgz", + "integrity": "sha512-17faEXbYWIRst1aU9SvPZyMdWmqIrduZjVOqCPMIsWFNxs5yQQgFrJL6b2SdiCzyW9mJoDjFtgi53xx7EH+BXA==", "dev": true, "dependencies": { - "tslib": "^2.5.0" + "@smithy/fetch-http-handler": "^2.5.0", + "@smithy/node-http-handler": "^2.5.0", + "@smithy/types": "^2.12.0", + "@smithy/util-base64": "^2.3.0", + "@smithy/util-buffer-from": "^2.2.0", + "@smithy/util-hex-encoding": "^2.2.0", + "@smithy/util-utf8": "^2.3.0", + "tslib": "^2.6.2" }, "engines": { "node": ">=14.0.0" } }, - "node_modules/@smithy/util-buffer-from": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-2.1.1.tgz", - "integrity": "sha512-clhNjbyfqIv9Md2Mg6FffGVrJxw7bgK7s3Iax36xnfVj6cg0fUG7I4RH0XgXJF8bxi+saY5HR21g2UPKSxVCXg==", + "node_modules/@smithy/util-uri-escape": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/util-uri-escape/-/util-uri-escape-2.2.0.tgz", + "integrity": "sha512-jtmJMyt1xMD/d8OtbVJ2gFZOSKc+ueYJZPW20ULW1GOp/q/YIM0wNh+u8ZFao9UaIGz4WoPW8hC64qlWLIfoDA==", "dev": true, "dependencies": { - "@smithy/is-array-buffer": "^2.1.1", - "tslib": "^2.5.0" + "tslib": "^2.6.2" }, "engines": { "node": ">=14.0.0" } }, - "node_modules/@smithy/util-hex-encoding": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@smithy/util-hex-encoding/-/util-hex-encoding-2.1.1.tgz", - "integrity": "sha512-3UNdP2pkYUUBGEXzQI9ODTDK+Tcu1BlCyDBaRHwyxhA+8xLP8agEKQq4MGmpjqb4VQAjq9TwlCQX0kP6XDKYLg==", + "node_modules/@smithy/util-utf8": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.3.0.tgz", + "integrity": "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==", "dev": true, "dependencies": { - "tslib": "^2.5.0" + "@smithy/util-buffer-from": "^2.2.0", + "tslib": "^2.6.2" }, "engines": { "node": ">=14.0.0" } }, - "node_modules/@smithy/util-utf8": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.1.1.tgz", - "integrity": "sha512-BqTpzYEcUMDwAKr7/mVRUtHDhs6ZoXDi9NypMvMfOr/+u1NW7JgqodPDECiiLboEm6bobcPcECxzjtQh865e9A==", + "node_modules/@smithy/util-waiter": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/util-waiter/-/util-waiter-2.2.0.tgz", + "integrity": "sha512-IHk53BVw6MPMi2Gsn+hCng8rFA3ZmR3Rk7GllxDUW9qFJl/hiSvskn7XldkECapQVkIg/1dHpMAxI9xSTaLLSA==", "dev": true, "dependencies": { - "@smithy/util-buffer-from": "^2.1.1", - "tslib": "^2.5.0" + "@smithy/abort-controller": "^2.2.0", + "@smithy/types": "^2.12.0", + "tslib": "^2.6.2" }, "engines": { "node": ">=14.0.0" @@ -4341,6 +5777,60 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/aws-sdk": { + "version": "2.1604.0", + "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.1604.0.tgz", + "integrity": "sha512-JSXNwKylbSZR2AL/jczOGJmPCZ/QpTys6SP89rhgy5LN677PJ6weQx5ShpPfGIcczGXjAeJDm8faWT53fYPCCw==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "buffer": "4.9.2", + "events": "1.1.1", + "ieee754": "1.1.13", + "jmespath": "0.16.0", + "querystring": "0.2.0", + "sax": "1.2.1", + "url": "0.10.3", + "util": "^0.12.4", + "uuid": "8.0.0", + "xml2js": "0.6.2" + }, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/aws-sdk/node_modules/buffer": { + "version": "4.9.2", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz", + "integrity": "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==", + "dev": true, + "dependencies": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4", + "isarray": "^1.0.0" + } + }, + "node_modules/aws-sdk/node_modules/ieee754": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", + "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==", + "dev": true + }, + "node_modules/aws-sdk/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true + }, + "node_modules/aws-sdk/node_modules/uuid": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.0.0.tgz", + "integrity": "sha512-jOXGuXZAWdsTH7eZLtyXMqUb9EcWMGZNbL9YcGBJl4MH4nrxHmZJhEHvyLFrkxo+28uLb/NYRcStH48fnD0Vzw==", + "dev": true, + "bin": { + "uuid": "dist/bin/uuid" + } + }, "node_modules/axios": { "version": "1.6.8", "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.8.tgz", @@ -4484,6 +5974,12 @@ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", "dev": true }, + "node_modules/bowser": { + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/bowser/-/bowser-2.11.0.tgz", + "integrity": "sha512-AlcaJBi/pqqJBIQ8U9Mcpc9i8Aqxn88Skv5d+xBX006BY5u8N3mGLHa5Lgppa7L/HfwgwLgZ6NYs+Ag6uUmJRA==", + "dev": true + }, "node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -6459,6 +7955,15 @@ "integrity": "sha512-tvtQIeLVHjDkJYnzf2dgVMxfuSGJeM/7UCG17TT4EumTfNtF+0nebF/4zWOIkCreAbtNqhGEboB6BWrwqNaw4Q==", "dev": true }, + "node_modules/events": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", + "integrity": "sha512-kEcvvCBByWXGnZy6JUlgAp2gBIUjfCAV6P6TgT1/aaQKcmuAEC4OZTV1I4EWQLz2gxZw76atuVyvHhTxvi0Flw==", + "dev": true, + "engines": { + "node": ">=0.4.x" + } + }, "node_modules/events-to-array": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/events-to-array/-/events-to-array-1.1.2.tgz", @@ -6665,6 +8170,28 @@ "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==" }, + "node_modules/fast-xml-parser": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.2.5.tgz", + "integrity": "sha512-B9/wizE4WngqQftFPmdaMYlXoJlJOYxGQOanC77fq9k8+Z0v5dDSVh+3glErdIROP//s/jgb7ZuxKfB8nVyo0g==", + "dev": true, + "funding": [ + { + "type": "paypal", + "url": "https://paypal.me/naturalintelligence" + }, + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "dependencies": { + "strnum": "^1.0.5" + }, + "bin": { + "fxparser": "src/cli/cli.js" + } + }, "node_modules/fastest-levenshtein": { "version": "1.0.16", "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz", @@ -8577,6 +10104,15 @@ "node": ">=8" } }, + "node_modules/jmespath": { + "version": "0.16.0", + "resolved": "https://registry.npmjs.org/jmespath/-/jmespath-0.16.0.tgz", + "integrity": "sha512-9FzQjJ7MATs1tSpnco1K6ayiYE3figslrXA72G2HQ/n76RzvYlofyi5QM+iX4YRs/pu3yzxlVQSST23+dMDknw==", + "dev": true, + "engines": { + "node": ">= 0.6.0" + } + }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -11253,6 +12789,16 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/querystring": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", + "integrity": "sha512-X/xY82scca2tau62i9mDyU9K+I+djTMUsvwf7xnUX5GLvVzgJybOJf4Y6o9Zx3oJK/LSXg5tTZBjwzqVPaPO2g==", + "deprecated": "The querystring API is considered Legacy. new code should use the URLSearchParams API instead.", + "dev": true, + "engines": { + "node": ">=0.4.x" + } + }, "node_modules/queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -11873,6 +13419,12 @@ "deprecated": "This package has been deprecated in favour of @sinonjs/samsam", "dev": true }, + "node_modules/sax": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.1.tgz", + "integrity": "sha512-8I2a3LovHTOpm7NV5yOyO8IHqgVsfK4+UuySrXU8YXkSRX7k6hCV9b3HrkKCr3nMpgj+0bmocaJJWpvp1oc7ZA==", + "dev": true + }, "node_modules/semver": { "version": "7.6.0", "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", @@ -12591,6 +14143,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/strnum": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.0.5.tgz", + "integrity": "sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==", + "dev": true + }, "node_modules/superagent": { "version": "8.1.2", "resolved": "https://registry.npmjs.org/superagent/-/superagent-8.1.2.tgz", @@ -15311,6 +16869,35 @@ "punycode": "^2.1.0" } }, + "node_modules/url": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/url/-/url-0.10.3.tgz", + "integrity": "sha512-hzSUW2q06EqL1gKM/a+obYHLIO6ct2hwPuviqTTOcfFVc61UbfJ2Q32+uGL/HCPxKqrdGB5QUwIe7UqlDgwsOQ==", + "dev": true, + "dependencies": { + "punycode": "1.3.2", + "querystring": "0.2.0" + } + }, + "node_modules/url/node_modules/punycode": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "integrity": "sha512-RofWgt/7fL5wP1Y7fxE7/EmTLzQVnB0ycyibJ0OOHIlJqTNzglYFxVwETOcIoJqJmpDXJ9xImDv+Fq34F/d4Dw==", + "dev": true + }, + "node_modules/util": { + "version": "0.12.5", + "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz", + "integrity": "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "is-arguments": "^1.0.4", + "is-generator-function": "^1.0.7", + "is-typed-array": "^1.1.3", + "which-typed-array": "^1.1.2" + } + }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -15575,6 +17162,28 @@ } } }, + "node_modules/xml2js": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.6.2.tgz", + "integrity": "sha512-T4rieHaC1EXcES0Kxxj4JWgaUQHDk+qwHcYOCFHfiwKz7tOVPLq7Hjq9dM1WCMhylqMEfP7hMcOIChvotiZegA==", + "dev": true, + "dependencies": { + "sax": ">=0.6.0", + "xmlbuilder": "~11.0.0" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/xmlbuilder": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", + "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, "node_modules/xmlcreate": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/xmlcreate/-/xmlcreate-2.0.4.tgz", diff --git a/package.json b/package.json index 9e4eb86a34..4a4610d9cc 100644 --- a/package.json +++ b/package.json @@ -193,7 +193,6 @@ "dependencies": { "@grpc/grpc-js": "^1.9.4", "@grpc/proto-loader": "^0.7.5", - "@newrelic/aws-sdk": "^7.3.0", "@newrelic/ritm": "^7.2.0", "@newrelic/security-agent": "^1.1.1", "@tyriar/fibonacci-heap": "^2.0.7", @@ -213,14 +212,19 @@ "@prisma/prisma-fmt-wasm": "^4.17.0-16.27eb2449f178cd9fe1a4b892d732cc4795f75085" }, "devDependencies": { + "@aws-sdk/client-s3": "^3.556.0", + "@aws-sdk/s3-request-presigner": "^3.556.0", "@koa/router": "^12.0.1", "@newrelic/eslint-config": "^0.3.0", "@newrelic/newrelic-oss-cli": "^0.1.2", "@newrelic/test-utilities": "^8.5.0", "@octokit/rest": "^18.0.15", "@slack/bolt": "^3.7.0", + "@smithy/eventstream-codec": "^2.2.0", + "@smithy/util-utf8": "^2.3.0", "ajv": "^6.12.6", "async": "^3.2.4", + "aws-sdk": "^2.1604.0", "c8": "^8.0.1", "clean-jsdoc-theme": "^4.2.18", "commander": "^7.0.0", diff --git a/test/lib/aws-server-stubs/ai-server/index.js b/test/lib/aws-server-stubs/ai-server/index.js new file mode 100644 index 0000000000..f9fd19ea1c --- /dev/null +++ b/test/lib/aws-server-stubs/ai-server/index.js @@ -0,0 +1,257 @@ +/* + * Copyright 2023 New Relic Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +'use strict' + +module.exports = createAiResponseServer + +const http = require('http') +const crypto = require('crypto') +const { Readable } = require('stream') +const { EventStreamCodec } = require('@smithy/eventstream-codec') +const { toUtf8, fromUtf8 } = require('@smithy/util-utf8') +const responses = require('./responses') + +/** + * Creates a new HTTP server to serve responses for Amazon AI requests + * (i.e. the Bedrock API). The returned server is listening on `localhost` + * and a random port. + * + * @returns {Promise} Has `server`, `host`, `port`, `baseUrl`, + * and `responses` properties. + */ +function createAiResponseServer() { + const server = http.createServer(handler) + const sockets = new Set() + + server.on('connection', (socket) => { + sockets.add(socket) + socket.once('close', () => sockets.delete(socket)) + }) + server.destroy = function destroy() { + sockets.forEach((s) => s.destroy()) + server.close() + } + + return new Promise((resolve, reject) => { + server.listen({ host: '127.0.0.1', port: 0 }, (error) => { + if (error) { + return reject(error) + } + + const addy = server.address() + return resolve({ + server, + host: addy.address, + port: addy.port, + baseUrl: `http://${addy.address}:${addy.port}`, + responses + }) + }) + }) +} + +function handler(req, res) { + if (req.method !== 'POST') { + res.statusCode = 400 + res.end() + return + } + + let data = Buffer.alloc(0) + req.on('data', (chunk) => { + data = Buffer.concat([data, chunk]) + }) + + req.on('end', () => { + const payload = JSON.parse(data.toString('utf8')) + + // Available model identifiers are listed at: + // https://docs.aws.amazon.com/bedrock/latest/userguide/model-ids-arns.html + const [, model] = /model\/(.+)\/invoke/.exec(req.url) + let response + switch (model) { + case 'ai21.j2-mid-v1': + case 'ai21.j2-ultra-v1': { + response = responses.ai21.get(payload.prompt) + break + } + + case 'amazon.titan-text-express-v1': + case 'amazon.titan-embed-text-v1': { + response = responses.amazon.get(payload.inputText) + break + } + + case 'anthropic.claude-v1': + case 'anthropic.claude-instant-v1': + // v1 seems to be the same as v2, just with less helpful responses. + case 'anthropic.claude-v2': + case 'anthropic.claude-v2:1': { + response = responses.claude.get(payload.prompt) + break + } + + case 'cohere.command-text-v14': + case 'cohere.command-light-text-v14': { + response = responses.cohere.get(payload.prompt) + break + } + + case 'cohere.embed-english-v3': + case 'cohere.embed-multilingual-v3': { + response = responses.cohere.get(payload.texts.join(' ')) + break + } + + case 'meta.llama2-13b-chat-v1': + case 'meta.llama2-70b-chat-v1': { + response = responses.llama2.get(payload.prompt) + break + } + + default: { + response = { statusCode: 418, body: {} } + } + } + + if (response === undefined) { + res.statusCode = 500 + res.end('could not match prompt') + return + } + + res.statusCode = response.statusCode + for (const [key, value] of Object.entries(response.headers)) { + res.setHeader(key, value) + } + + if (response.body === 'bad stream') { + const stream = infiniteStream() + let count = 0 + stream.on('data', () => { + if (count >= 100) { + stream.destroy() + res.destroy() + } + count += 1 + }) + stream.pipe(res) + return + } else if (response.headers['content-type'].endsWith('amazon.eventstream') === true) { + encodeChunks(response.chunks).pipe(res) + return + } + + res.end(JSON.stringify(response.body)) + }) +} + +/** + * Creates a stream that will generate new stream messages until the stream + * is destroyed. + * + * @returns {Readable} + */ +function infiniteStream() { + return new Readable({ + read(size = 16) { + const data = crypto.randomBytes(size) + this.push(JSON.stringify({ chunk: { bytes: data.toString('base64') } })) + } + }).pause() +} + +/** + * @typedef {object} BedrockModelResponse + * @property {string} completion A full, or partial, model response. + * @property {string|null} stop_reason Indicates why this response object + * should be the end of the response. Should be `null` if there are more + * objects to receive, otherwise is likely set to "stop_sequence". + * @property {string|null} stop When not `null`, indicates that this object + * is the last object in the response. + * @property {object} [amazon-bedrock-invocationMetrics] Should be present on the + * final response object in a streamed response. Has properties: + * `inputTokenCount`, `outputTokenCount`, `invocationLatency`, and + * `firstByteLatency` (all integers). + */ + +/** + * @typedef {object} BedrockStreamChunk + * @property {BedrockModelResponse} body A plain JavaScript object that + * constitutes a response from the model. + * @property {object} headers An object with keys that are header names and + * values that are objects with keys `type` and `value`. The `type` is any + * listed at https://github.com/smithy-lang/smithy-typescript/blob/9485a73/packages/eventstream-codec/src/HeaderMarshaller.ts#L30. + * The `value` is the value of the header. + */ + +/** + * Encodes a set of {@link BedrockStreamChunk} objects into binary packed + * message objects that can be sent as a streamed response. The binary + * format is mainly handled by the `EventStreamCodec` object from the AWS + * tooling, but understanding the format is likely beneficial to anyone + * reading this. The basics of the format are: + * + * 1. A 16 byte prelude starts each message. The first 4 bytes are a big endian + * uint32 representing the message length. The second 4 bytes are another + * uint32 representing the headers length. The third 4 bytes are a CRC32 + * checksum for the first 8 bytes. + * 2. The message length _includes_ all 16 bytes of the prelude block, the + * encoded headers block, and the encoded body block. + * 3. The whole message is terminated with a 4 byte CRC32 checksum value of + * the whole message. + * 4. The encoded headers block starts with the vertical tab byte 0x0b followed + * by an alternating set of: string (header name), 3 byte descriptor (leftmost + * byte being an indicator of the header type, e.g. 0x07 for "string", and the + * two remaining bytes an integer indicating the length of the value), the + * value of the header (e.g. a string for a string header), and a terminating + * byte set to 0x0d _except_ for the final header where there is not a + * terminating byte. + * 5. The encoded body block is a JSON string that represents an object with a + * `bytes` key set to a base64 encoded JSON representation of a + * {@link BedrockModelResponse} object. This block is added without any preamble + * or trailer. + * 6. The 4 byte whole message checksum. + * + * Messages in the data stream are not separated in any way. Each 4 byte message + * length is used to demarcate each message. Note that there may be some + * incorrect assumptions in the format description; we have not found any actual + * documentation on the format and had to derive it from network inspection and + * reversing of the parsing algorithm. + * + * @param {BedrockStreamChunk[]} chunks The chunks to encode. + * @returns {Readable} A paused stream that will write one coded chunk per + * read operation. + */ +function encodeChunks(chunks) { + const encodedChunks = [] + const codec = new EventStreamCodec(toUtf8, fromUtf8) + + for (const chunk of chunks) { + const b64Body = Buffer.from(JSON.stringify(chunk.body)).toString('base64') + const bytesObj = JSON.stringify({ bytes: b64Body }) + const bodyBuffer = Buffer.from(bytesObj) + const toEncode = { + headers: chunk.headers, + body: new Uint8Array(bodyBuffer, 0, bodyBuffer.byteLength) + } + encodedChunks.push(codec.encode(toEncode)) + } + + return new Readable({ + read() { + if (encodedChunks.length > 0) { + this.push(encodedChunks.shift()) + } else { + this.push(null) + } + } + }).pause() +} + +module.exports.internals = { + encodeChunks +} diff --git a/test/lib/aws-server-stubs/ai-server/responses/ai21.js b/test/lib/aws-server-stubs/ai-server/responses/ai21.js new file mode 100644 index 0000000000..ad167a9637 --- /dev/null +++ b/test/lib/aws-server-stubs/ai-server/responses/ai21.js @@ -0,0 +1,171 @@ +/* + * Copyright 2023 New Relic Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +'use strict' + +const responses = new Map() +const { contentType, reqId } = require('./constants') + +responses.set('text ai21 ultimate question', { + headers: { + 'content-type': contentType, + 'x-amzn-requestid': reqId, + 'x-amzn-bedrock-invocation-latency': '180', + 'x-amzn-bedrock-output-token-count': '4', + 'x-amzn-bedrock-input-token-count': '8' + }, + statusCode: 200, + body: { + id: 1234, + prompt: { + text: 'What is the answer to life, the universe, and everything?', + tokens: [ + { + generatedToken: { + token: '▁What▁is', + logprob: -6.8071370124816895, + raw_logprob: -6.8071370124816895 + }, + topTokens: null, + textRange: { start: 0, end: 7 } + }, + { + generatedToken: { + token: '▁the▁answer▁to', + logprob: -9.021844863891602, + raw_logprob: -9.021844863891602 + }, + topTokens: null, + textRange: { start: 7, end: 21 } + }, + { + generatedToken: { + token: '▁life', + logprob: -0.7543996572494507, + raw_logprob: -0.7543996572494507 + }, + topTokens: null, + textRange: { start: 21, end: 26 } + }, + { + generatedToken: { + token: ',', + logprob: -9.393946647644043, + raw_logprob: -9.393946647644043 + }, + topTokens: null, + textRange: { start: 26, end: 27 } + }, + { + generatedToken: { + token: '▁the▁universe', + logprob: -0.054497551172971725, + raw_logprob: -0.054497551172971725 + }, + topTokens: null, + textRange: { start: 27, end: 40 } + }, + { + generatedToken: { + token: ',', + logprob: -1.3849022388458252, + raw_logprob: -1.3849022388458252 + }, + topTokens: null, + textRange: { start: 40, end: 41 } + }, + { + generatedToken: { + token: '▁and▁everything', + logprob: -0.03310895338654518, + raw_logprob: -0.03310895338654518 + }, + topTokens: null, + textRange: { start: 41, end: 56 } + }, + { + generatedToken: { + token: '?', + logprob: -6.455468654632568, + raw_logprob: -6.455468654632568 + }, + topTokens: null, + textRange: { start: 56, end: 57 } + } + ] + }, + completions: [ + { + data: { + text: '42', + tokens: [ + { + generatedToken: { + token: '<|newline|>', + logprob: -5.245195097813848e-6, + raw_logprob: -5.245195097813848e-6 + }, + topTokens: null, + textRange: { start: 0, end: 1 } + }, + { + generatedToken: { + token: '▁', + logprob: -2.2998135089874268, + raw_logprob: -2.2998135089874268 + }, + topTokens: null, + textRange: { start: 1, end: 1 } + }, + { + generatedToken: { + token: '42', + logprob: -3.844952443614602e-4, + raw_logprob: -3.844952443614602e-4 + }, + topTokens: null, + textRange: { start: 1, end: 3 } + }, + { + generatedToken: { + token: '<|endoftext|>', + logprob: -4.766043566633016e-4, + raw_logprob: -4.766043566633016e-4 + }, + topTokens: null, + textRange: { start: 3, end: 3 } + } + ] + }, + finishReason: { reason: 'endoftext' } + } + ] + } +}) + +responses.set('text ai21 ultimate question error streamed', { + headers: { + 'content-type': contentType, + 'x-amzn-requestid': reqId, + 'x-amzn-errortype': 'ValidationException:http://internal.amazon.com/coral/com.amazon.bedrock/' + }, + statusCode: 400, + body: { message: 'The model is unsupported for streaming' } +}) + +responses.set('text ai21 ultimate question error', { + headers: { + 'content-type': contentType, + 'x-amzn-requestid': reqId, + 'x-amzn-errortype': 'ValidationException:http://internal.amazon.com/coral/com.amazon.bedrock/' + }, + statusCode: 400, + body: { + message: + 'Malformed input request: 2 schema violations found, please reformat your input and try again.' + } +}) + +module.exports = responses diff --git a/test/lib/aws-server-stubs/ai-server/responses/amazon.js b/test/lib/aws-server-stubs/ai-server/responses/amazon.js new file mode 100644 index 0000000000..69ce8836e2 --- /dev/null +++ b/test/lib/aws-server-stubs/ai-server/responses/amazon.js @@ -0,0 +1,171 @@ +/* + * Copyright 2023 New Relic Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +'use strict' + +const responses = new Map() +const { contentType, reqId } = require('./constants') +const errValidationException = + 'ValidationException:http://internal.amazon.com/coral/com.amazon.bedrock/' + +responses.set('embed text amazon success', { + headers: { + 'content-type': contentType, + 'x-amzn-requestid': '743dd35b-744b-4ddf-b5c6-c0f3de2e3142', + 'x-amzn-bedrock-invocation-latency': '195', + 'x-amzn-bedrock-input-token-count': '13' + }, + statusCode: 200, + body: { + embedding: [0.18945312, -0.36914062, -0.33984375, 0.14355469], + inputTextTokenCount: 13 + } +}) + +responses.set('text amazon ultimate question', { + headers: { + 'content-type': contentType, + 'x-amzn-requestid': reqId, + 'x-amzn-bedrock-invocation-latency': '2420', + 'x-amzn-bedrock-output-token-count': '4', + 'x-amzn-bedrock-input-token-count': '8' + }, + statusCode: 200, + body: { + inputTextTokenCount: 13, + results: [ + { + tokenCount: 4, + outputText: '42', + completionReason: 'endoftext' + } + ] + } +}) + +responses.set('text amazon ultimate question streamed', { + headers: { + 'content-type': 'application/vnd.amazon.eventstream', + 'x-amzn-requestid': reqId, + 'x-amzn-bedrock-content-type': 'application/json' + }, + statusCode: 200, + chunks: [ + { + body: { + outputText: '42', + index: 0, + totalOutputTextTokenCount: null, + completionReason: null, + inputTextTokenCount: 13 + }, + headers: { + ':event-type': { type: 'string', value: 'chunk' }, + ':message-type': { type: 'string', value: 'event' } + } + }, + { + body: { + 'outputText': '', + 'index': 0, + 'totalOutputTextTokenCount': 75, + 'completionReason': 'endoftext', + 'inputTextTokenCount': null, + 'amazon-bedrock-invocationMetrics': { + inputTokenCount: 8, + outputTokenCount: 4, + invocationLatency: 3879, + firstByteLatency: 3291 + } + }, + headers: { + ':event-type': { type: 'string', value: 'chunk' }, + ':message-type': { type: 'string', value: 'event' } + } + } + ] +}) + +responses.set('text amazon ultimate question error', { + headers: { + 'content-type': contentType, + 'x-amzn-requestid': reqId, + 'x-amzn-errortype': errValidationException + }, + statusCode: 400, + body: { + message: + 'Malformed input request: 2 schema violations found, please reformat your input and try again.' + } +}) + +responses.set('embed text amazon error', { + headers: { + 'content-type': contentType, + 'x-amzn-requestid': '743dd35b-744b-4ddf-b5c6-c0f3de2e3142', + 'x-amzn-errortype': errValidationException + }, + statusCode: 400, + body: { + message: + 'Malformed input request: 2 schema violations found, please reformat your input and try again.' + } +}) + +responses.set('embed text amazon error streamed', { + headers: { + 'content-type': contentType, + 'x-amzn-requestid': reqId, + 'x-amzn-errortype': errValidationException + }, + statusCode: 400, + body: { + message: 'The model is unsupported for streaming' + } +}) + +responses.set('text amazon bad stream', { + headers: { + 'content-type': contentType, + 'x-amzn-requestid': reqId, + 'x-amzn-errortype': + 'InternalServerException:http://internal.amazon.com/coral/com.amazon.bedrock/' + }, + statusCode: 500, + body: 'bad stream' +}) + +responses.set('text amazon user token count callback response', { + headers: { + 'content-type': contentType, + 'x-amzn-requestid': reqId, + 'x-amzn-bedrock-invocation-latency': '2420' + }, + statusCode: 200, + body: { + inputTextTokenCount: 13, + results: [ + { + tokenCount: 4, + outputText: '42', + completionReason: 'endoftext' + } + ] + } +}) + +responses.set('embed text amazon token count callback response', { + headers: { + 'content-type': contentType, + 'x-amzn-requestid': reqId + }, + statusCode: 200, + body: { + embedding: [0.1, 0.2, 0.3, 0.4], + inputTextTokenCount: 13 + } +}) + +module.exports = responses diff --git a/test/lib/aws-server-stubs/ai-server/responses/claude.js b/test/lib/aws-server-stubs/ai-server/responses/claude.js new file mode 100644 index 0000000000..f54c3f6aba --- /dev/null +++ b/test/lib/aws-server-stubs/ai-server/responses/claude.js @@ -0,0 +1,95 @@ +/* + * Copyright 2023 New Relic Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +'use strict' + +const responses = new Map() +const { contentType, reqId } = require('./constants') + +responses.set('claude insufficient context', { + headers: { + 'content-type': contentType, + 'x-amzn-requestid': '3d4ce4d4-dd79-44e8-96d5-89d3a733ded6', + 'x-amzn-bedrock-invocation-latency': '926', + 'x-amzn-bedrock-output-token-count': '36', + 'x-amzn-bedrock-input-token-count': '14' + }, + statusCode: 200, + body: { + completion: + " I'm afraid I don't have enough context to determine the answer to your question. Could you please provide some more details about what specific question you are asking?", + stop_reason: 'stop_sequence', + stop: '\n\nHuman:' + } +}) + +responses.set('text claude ultimate question', { + headers: { + 'content-type': contentType, + 'x-amzn-requestid': reqId, + 'x-amzn-bedrock-invocation-latency': '609', + 'x-amzn-bedrock-output-token-count': '4', + 'x-amzn-bedrock-input-token-count': '8' + }, + statusCode: 200, + body: { + // "What is the answer to life, the universe, and everything?" + completion: '42', + stop_reason: 'endoftext', + stop: '\n\nHuman:' + } +}) + +responses.set('text claude ultimate question streamed', { + headers: { + 'content-type': 'application/vnd.amazon.eventstream', + 'x-amzn-requestid': reqId, + 'x-amzn-bedrock-content-type': contentType + }, + statusCode: 200, + chunks: [ + { + body: { completion: '42', stop_reason: null, stop: null }, + headers: { + ':event-type': { type: 'string', value: 'chunk' }, + ':content-type': { type: 'string', value: 'application/json' }, + ':message-type': { type: 'string', value: 'event' } + } + }, + { + body: { + 'completion': '', + 'stop_reason': 'endoftext', + 'stop': '\n\nHuman:', + 'amazon-bedrock-invocationMetrics': { + inputTokenCount: 8, + outputTokenCount: 4, + invocationLatency: 511, + firstByteLatency: 358 + } + }, + headers: { + ':event-type': { type: 'string', value: 'chunk' }, + ':content-type': { type: 'string', value: 'application/json' }, + ':message-type': { type: 'string', value: 'event' } + } + } + ] +}) + +responses.set('text claude ultimate question error', { + headers: { + 'content-type': contentType, + 'x-amzn-requestid': reqId, + 'x-amzn-errortype': 'ValidationException:http://internal.amazon.com/coral/com.amazon.bedrock/' + }, + statusCode: 400, + body: { + message: + 'Malformed input request: 2 schema violations found, please reformat your input and try again.' + } +}) + +module.exports = responses diff --git a/test/lib/aws-server-stubs/ai-server/responses/cohere.js b/test/lib/aws-server-stubs/ai-server/responses/cohere.js new file mode 100644 index 0000000000..b19b9ab061 --- /dev/null +++ b/test/lib/aws-server-stubs/ai-server/responses/cohere.js @@ -0,0 +1,144 @@ +/* + * Copyright 2023 New Relic Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +'use strict' + +const responses = new Map() +const { contentType, reqId } = require('./constants') + +responses.set('text cohere ultimate question', { + headers: { + 'content-type': contentType, + 'x-amzn-requestid': reqId, + 'x-amzn-bedrock-invocation-latency': '9612', + 'x-amzn-bedrock-output-token-count': '4', + 'x-amzn-bedrock-input-token-count': '8' + }, + statusCode: 200, + body: { + generations: [ + { + finish_reason: 'endoftext', + id: '3eeb2e13-3d8e-42bb-9cb4-ae57502403c4', + text: '42' + } + ], + id: '1234', + prompt: 'What is the answer to life, the universe, and everything?' + } +}) + +responses.set('text cohere ultimate question streamed', { + headers: { + 'content-type': 'application/vnd.amazon.eventstream', + 'x-amzn-requestid': reqId, + 'x-amzn-bedrock-content-type': contentType + }, + statusCode: 200, + chunks: [ + { + headers: { + ':event-type': { type: 'string', value: 'chunk' }, + ':content-type': { type: 'string', value: contentType }, + ':message-type': { type: 'string', value: 'event' } + }, + body: { + 'generations': [ + { + finish_reason: 'endoftext', + id: 'f4ca64e7-93ce-4722-bebe-2d383440dedf', + text: '42' + } + ], + 'id': '1234', + 'prompt': 'What is the answer to life, the universe, and everything?', + 'amazon-bedrock-invocationMetrics': { + inputTokenCount: 8, + outputTokenCount: 4, + invocationLatency: 8623, + firstByteLatency: 8623 + } + } + } + ] +}) + +responses.set('embed text cohere success', { + headers: { + 'content-type': contentType, + 'x-amzn-requestid': '743dd35b-744b-4ddf-b5c6-c0f3de2e3142', + 'x-amzn-bedrock-invocation-latency': '195', + 'x-amzn-bedrock-input-token-count': '13' + }, + statusCode: 200, + body: { + embeddings: [ + [-0.019012451, 0.031707764, -0.053985596, -0.034484863, 0.019058228, -0.008850098], + [-2.2888184e-4, 0.02166748, -0.009109497, -0.04159546, -0.023513794, -0.007965088] + ], + id: '784e35b6-226c-40d2-99f3-71f66e6185da', + texts: ['embed', 'text'] + } +}) + +responses.set('embed text cohere stream', { + headers: { + 'content-type': 'application/vnd.amazon.eventstream', + 'x-amzn-requestid': reqId, + 'x-amzn-bedrock-content-type': 'application/json' + }, + statusCode: 200, + chunks: [ + { + headers: { + ':event-type': { type: 'string', value: 'chunk' }, + ':content-type': { type: 'string', value: 'application/json' }, + ':message-type': { type: 'string', value: 'event' } + }, + body: { + 'embeddings': [ + [-0.019012451, 0.031707764, -0.053985596, -0.034484863, 0.019058228, -0.008850098], + [-2.2888184e-4, 0.02166748, -0.009109497, -0.04159546, -0.023513794, -0.007965088] + ], + 'id': 'fbd3923c-3071-4ece-8761-6ba78058f747', + 'texts': ['foo', 'bar'], + 'amazon-bedrock-invocationMetrics': { + inputTokenCount: 4, + outputTokenCount: 8, + invocationLatency: 492, + firstByteLatency: 480 + } + } + } + ] +}) + +responses.set('text cohere ultimate question error', { + headers: { + 'content-type': contentType, + 'x-amzn-requestid': reqId, + 'x-amzn-errortype': 'ValidationException:http://internal.amazon.com/coral/com.amazon.bedrock/' + }, + statusCode: 400, + body: { + message: + 'Malformed input request: 2 schema violations found, please reformat your input and try again.' + } +}) + +responses.set('embed text cohere error', { + headers: { + 'content-type': contentType, + 'x-amzn-requestid': '743dd35b-744b-4ddf-b5c6-c0f3de2e3142', + 'x-amzn-errortype': 'ValidationException:http://internal.amazon.com/coral/com.amazon.bedrock/' + }, + statusCode: 400, + body: { + message: + 'Malformed input request: 2 schema violations found, please reformat your input and try again.' + } +}) + +module.exports = responses diff --git a/test/lib/aws-server-stubs/ai-server/responses/constants.js b/test/lib/aws-server-stubs/ai-server/responses/constants.js new file mode 100644 index 0000000000..486fda10e7 --- /dev/null +++ b/test/lib/aws-server-stubs/ai-server/responses/constants.js @@ -0,0 +1,12 @@ +/* + * Copyright 2024 New Relic Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +'use strict' + +// Appease sonarjs/no-duplicate-string warnings across models. +module.exports = { + contentType: 'application/json', + reqId: 'eda0760a-c3f0-4fc1-9a1e-75559d642866' +} diff --git a/test/lib/aws-server-stubs/ai-server/responses/index.js b/test/lib/aws-server-stubs/ai-server/responses/index.js new file mode 100644 index 0000000000..46facb6ccd --- /dev/null +++ b/test/lib/aws-server-stubs/ai-server/responses/index.js @@ -0,0 +1,20 @@ +/* + * Copyright 2023 New Relic Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +'use strict' + +const ai21 = require('./ai21') +const amazon = require('./amazon') +const claude = require('./claude') +const cohere = require('./cohere') +const llama2 = require('./llama2') + +module.exports = { + ai21, + amazon, + claude, + cohere, + llama2 +} diff --git a/test/lib/aws-server-stubs/ai-server/responses/llama2.js b/test/lib/aws-server-stubs/ai-server/responses/llama2.js new file mode 100644 index 0000000000..b2ddcfb8ca --- /dev/null +++ b/test/lib/aws-server-stubs/ai-server/responses/llama2.js @@ -0,0 +1,84 @@ +/* + * Copyright 2024 New Relic Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +'use strict' + +const responses = new Map() +const { contentType, reqId } = require('./constants') + +responses.set('text llama2 ultimate question', { + headers: { + 'content-type': contentType, + 'x-amzn-requestid': reqId, + 'x-amzn-bedrock-invocation-latency': 9677, + 'x-amzn-bedrock-output-token-count': 4, + 'x-amzn-bedrock-input-token-count': 8 + }, + statusCode: 200, + body: { + generation: '42', + prompt_token_count: 14, + generation_token_count: 205, + stop_reason: 'endoftext' + } +}) + +responses.set('text llama2 ultimate question streamed', { + headers: { + 'content-type': 'application/vnd.amazon.eventstream', + 'x-amzn-requestid': reqId, + 'x-amzn-bedrock-content-type': contentType + }, + statusCode: 200, + chunks: [ + { + headers: { + ':event-type': { type: 'string', value: 'chunk' }, + ':content-type': { type: 'string', value: 'application/json' }, + ':message-type': { type: 'string', value: 'event' } + }, + body: { + generation: '42', + prompt_token_count: null, + generation_token_count: 211, + stop_reason: null + } + }, + { + headers: { + ':event-type': { type: 'string', value: 'chunk' }, + ':content-type': { type: 'string', value: 'application/json' }, + ':message-type': { type: 'string', value: 'event' } + }, + body: { + 'generation': '', + 'prompt_token_count': null, + 'generation_token_count': 212, + 'stop_reason': 'endoftext', + 'amazon-bedrock-invocationMetrics': { + inputTokenCount: 8, + outputTokenCount: 4, + invocationLatency: 9825, + firstByteLatency: 283 + } + } + } + ] +}) + +responses.set('text llama2 ultimate question error', { + headers: { + 'content-type': contentType, + 'x-amzn-requestid': reqId, + 'x-amzn-errortype': 'ValidationException:http://internal.amazon.com/coral/com.amazon.bedrock/' + }, + statusCode: 400, + body: { + message: + 'Malformed input request: 2 schema violations found, please reformat your input and try again.' + } +}) + +module.exports = responses diff --git a/test/lib/aws-server-stubs/common.js b/test/lib/aws-server-stubs/common.js new file mode 100644 index 0000000000..89c1ae79dd --- /dev/null +++ b/test/lib/aws-server-stubs/common.js @@ -0,0 +1,27 @@ +/* + * Copyright 2021 New Relic Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +'use strict' + +/** + * Patches in a server.destroy method, which closes a server immediately + * by destroying any remaining open sockets. + * @param server An HTTP(S) server, from http(s).createServer + */ +exports.patchDestroy = function (server) { + const sockets = new Set() + server.on('connection', (socket) => { + sockets.add(socket) + socket.once('close', () => { + sockets.delete(socket) + }) + }) + server.destroy = function () { + sockets.forEach((socket) => { + socket.destroy() + }) + server.close() + } +} diff --git a/test/lib/aws-server-stubs/empty-response-server/index.js b/test/lib/aws-server-stubs/empty-response-server/index.js new file mode 100644 index 0000000000..b14f27bac4 --- /dev/null +++ b/test/lib/aws-server-stubs/empty-response-server/index.js @@ -0,0 +1,48 @@ +/* + * Copyright 2020 New Relic Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +'use strict' + +const http = require('http') +const { patchDestroy } = require('../common') + +function createEmptyResponseServer() { + const server = http.createServer(function (req, res) { + if ( + req.method === 'GET' || + req.method === 'POST' || + req.method === 'PUT' || + req.method === 'HEAD' || + req.method === 'DELETE' + ) { + handlePost(req, res) + return + } + + // sometimes the aws-sdk will obfuscate this error + // so logging out. + // eslint-disable-next-line no-console + console.log('Unhandled request method: ', req.method) + + res.statusCode = 500 + res.end('Unhandled request method') + }) + + patchDestroy(server) + + return server +} + +function handlePost(req, res) { + req.on('data', () => {}) + + req.on('end', () => { + // currently, some tests do not rely on real responses back. + // it is enough to return something valid to the client. + res.end() + }) +} + +module.exports = createEmptyResponseServer diff --git a/test/lib/aws-server-stubs/index.js b/test/lib/aws-server-stubs/index.js new file mode 100644 index 0000000000..b40d9fe2df --- /dev/null +++ b/test/lib/aws-server-stubs/index.js @@ -0,0 +1,22 @@ +/* + * Copyright 2020 New Relic Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +'use strict' + +const createEmptyResponseServer = require('./empty-response-server') +const createResponseServer = require('./response-server') + +// Specific values are unimportant because we'll be hitting our +// custom servers. But they need to be populated. +const FAKE_CREDENTIALS = { + accessKeyId: 'FAKE ID', + secretAccessKey: 'FAKE KEY' +} + +module.exports = { + createEmptyResponseServer, + createResponseServer, + FAKE_CREDENTIALS +} diff --git a/test/lib/aws-server-stubs/response-server/common.js b/test/lib/aws-server-stubs/response-server/common.js new file mode 100644 index 0000000000..ceeddd8ccb --- /dev/null +++ b/test/lib/aws-server-stubs/response-server/common.js @@ -0,0 +1,34 @@ +/* + * Copyright 2021 New Relic Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +'use strict' +const common = module.exports +const path = require('path') +const fs = require('fs') + +common.parseBody = function parseBody(body, headers) { + try { + const parsed = JSON.parse(body) + parsed.Action = headers['x-amz-target'].split('.')[1] + return parsed + } catch { + const parsed = Object.create(null) + + const items = body.split('&') + items.forEach((item) => { + const [key, value] = item.split('=') + parsed[key] = value + }) + + return parsed + } +} + +common.readFromXml = function readFromXml(filePath, callback) { + const fullPath = path.join(__dirname, filePath) + fs.readFile(fullPath, 'utf8', function (err, data) { + callback(err, data) + }) +} diff --git a/test/lib/aws-server-stubs/response-server/elasticache/index.js b/test/lib/aws-server-stubs/response-server/elasticache/index.js new file mode 100644 index 0000000000..30d0cf4c2a --- /dev/null +++ b/test/lib/aws-server-stubs/response-server/elasticache/index.js @@ -0,0 +1,28 @@ +/* + * Copyright 2021 New Relic Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +'use strict' +const helpers = module.exports +const { readFromXml } = require('../common') + +let addTagsResponse = null +helpers.getAddTagsResponse = function getAddTagsResponse(callback) { + if (addTagsResponse) { + setImmediate(() => { + callback(null, addTagsResponse) + }) + return + } + + readFromXml('./elasticache/responses/add-tags-response.xml', (err, data) => { + if (err) { + callback(err) + return + } + + addTagsResponse = data + callback(null, addTagsResponse) + }) +} diff --git a/test/lib/aws-server-stubs/response-server/elasticache/responses/add-tags-response.xml b/test/lib/aws-server-stubs/response-server/elasticache/responses/add-tags-response.xml new file mode 100644 index 0000000000..e6cd223429 --- /dev/null +++ b/test/lib/aws-server-stubs/response-server/elasticache/responses/add-tags-response.xml @@ -0,0 +1,9 @@ + + + node-1 + b8bee936-3b18-5c1c-bd66-b0c969b618b6 + + + 648b4fd5-c97e-5ece-a8ca-162a9a4270a3 + + diff --git a/test/lib/aws-server-stubs/response-server/index.js b/test/lib/aws-server-stubs/response-server/index.js new file mode 100644 index 0000000000..751d4f0803 --- /dev/null +++ b/test/lib/aws-server-stubs/response-server/index.js @@ -0,0 +1,97 @@ +/* + * Copyright 2020 New Relic Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +'use strict' + +const http = require('http') +const { getAddTagsResponse } = require('./elasticache') +const { getAcceptExchangeResponse } = require('./redshift') +const { getSendEmailResponse } = require('./ses') +const { getPublishResponse, getListTopicsResponse } = require('./sns') +const { + getCreateQueueResponse, + getSendMessageResponse, + getSendMessageBatchResponse, + getReceiveMessageResponse +} = require('./sqs') +const { parseBody } = require('./common') +const { patchDestroy } = require('../common') + +function createResponseServer() { + const server = http.createServer(function (req, res) { + if (req.method === 'POST') { + handlePost(req, res) + return + } + + res.statusCode = 500 + res.end() + }) + + patchDestroy(server) + + return server +} + +function handlePost(req, res) { + let body = '' + + req.on('data', (chunk) => { + body += chunk.toString() + }) + + req.on('end', () => { + const isJson = !!req.headers['x-amz-target'] + const endpoint = `http://localhost:${req.connection.localPort}` + const parsed = parseBody(body, req.headers) + + const getDataFunction = createGetDataFromAction(endpoint, parsed, isJson) + + getDataFunction((err, data) => { + if (err) { + res.statusCode = 500 + // eslint-disable-next-line no-console + console.log(err) + } + + if (isJson) { + res.setHeader('x-amz-request-id', data.ResponseMetadata.RequestId) + data = JSON.stringify(data) + } + res.end(data) + }) + }) +} + +function createGetDataFromAction(endpoint, body, isJson) { + switch (body.Action) { + case 'Publish': + return getPublishResponse.bind(null) + case 'ListTopics': + return getListTopicsResponse.bind(null) + case 'CreateQueue': + return getCreateQueueResponse.bind(null, endpoint, body.QueueName, isJson) + case 'SendMessage': + return getSendMessageResponse.bind(null, isJson) + case 'SendMessageBatch': + return getSendMessageBatchResponse.bind(null, isJson) + case 'ReceiveMessage': + return getReceiveMessageResponse.bind(null, isJson) + case 'SendEmail': + return getSendEmailResponse.bind(null) + case 'AcceptReservedNodeExchange': + return getAcceptExchangeResponse.bind(null) + case 'AddTagsToResource': + return getAddTagsResponse.bind(null) + default: + return function actionNotImplemented(callback) { + setImmediate(() => { + callback(new Error('Action not implemented')) + }) + } + } +} + +module.exports = createResponseServer diff --git a/test/lib/aws-server-stubs/response-server/redshift/index.js b/test/lib/aws-server-stubs/response-server/redshift/index.js new file mode 100644 index 0000000000..a0c69cb569 --- /dev/null +++ b/test/lib/aws-server-stubs/response-server/redshift/index.js @@ -0,0 +1,28 @@ +/* + * Copyright 2021 New Relic Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +'use strict' +const helpers = module.exports +const { readFromXml } = require('../common') + +let acceptExchangeResponse = null +helpers.getAcceptExchangeResponse = function getAcceptExchangeResponse(callback) { + if (acceptExchangeResponse) { + setImmediate(() => { + callback(null, acceptExchangeResponse) + }) + return + } + + readFromXml('./redshift/responses/accept-exchange-response.xml', (err, data) => { + if (err) { + callback(err) + return + } + + acceptExchangeResponse = data + callback(null, acceptExchangeResponse) + }) +} diff --git a/test/lib/aws-server-stubs/response-server/redshift/responses/accept-exchange-response.xml b/test/lib/aws-server-stubs/response-server/redshift/responses/accept-exchange-response.xml new file mode 100644 index 0000000000..2ede0eb432 --- /dev/null +++ b/test/lib/aws-server-stubs/response-server/redshift/responses/accept-exchange-response.xml @@ -0,0 +1,9 @@ + + + node-1 + b8bee936-3b18-5c1c-bd66-b0c969b618b6 + + + 648b4fd5-c97e-5ece-a8ca-162a9a4270a3 + + diff --git a/test/lib/aws-server-stubs/response-server/ses/index.js b/test/lib/aws-server-stubs/response-server/ses/index.js new file mode 100644 index 0000000000..b96b7c5a8b --- /dev/null +++ b/test/lib/aws-server-stubs/response-server/ses/index.js @@ -0,0 +1,28 @@ +/* + * Copyright 2021 New Relic Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +'use strict' +const helpers = module.exports +const { readFromXml } = require('../common') + +let sendEmailResponse = null +helpers.getSendEmailResponse = function getSendEmailResponse(callback) { + if (sendEmailResponse) { + setImmediate(() => { + callback(null, sendEmailResponse) + }) + return + } + + readFromXml('./ses/responses/send-email-response.xml', (err, data) => { + if (err) { + callback(err) + return + } + + sendEmailResponse = data + callback(null, sendEmailResponse) + }) +} diff --git a/test/lib/aws-server-stubs/response-server/ses/responses/send-email-response.xml b/test/lib/aws-server-stubs/response-server/ses/responses/send-email-response.xml new file mode 100644 index 0000000000..7155d69237 --- /dev/null +++ b/test/lib/aws-server-stubs/response-server/ses/responses/send-email-response.xml @@ -0,0 +1,8 @@ + + + b8bee936-3b18-5c1c-bd66-b0c969b618b6 + + + 648b4fd5-c97e-5ece-a8ca-162a9a4270a3 + + diff --git a/test/lib/aws-server-stubs/response-server/sns/index.js b/test/lib/aws-server-stubs/response-server/sns/index.js new file mode 100644 index 0000000000..312bd4223a --- /dev/null +++ b/test/lib/aws-server-stubs/response-server/sns/index.js @@ -0,0 +1,48 @@ +/* + * Copyright 2021 New Relic Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +'use strict' +const helpers = module.exports +const { readFromXml } = require('../common') + +let publishMessageResponse = null +helpers.getPublishResponse = function getPublishResponse(callback) { + if (publishMessageResponse) { + setImmediate(() => { + callback(null, publishMessageResponse) + }) + return + } + + readFromXml('./sns/responses/publish-message-response.xml', (err, data) => { + if (err) { + callback(err) + return + } + + publishMessageResponse = data + callback(null, publishMessageResponse) + }) +} + +let listTopicsResponse = null +helpers.getListTopicsResponse = function getListTopicsResponse(callback) { + if (listTopicsResponse) { + setImmediate(() => { + callback(null, listTopicsResponse) + }) + return + } + + readFromXml('./sns/responses/list-topics-response.xml', (err, data) => { + if (err) { + callback(err) + return + } + + listTopicsResponse = data + callback(null, listTopicsResponse) + }) +} diff --git a/test/lib/aws-server-stubs/response-server/sns/responses/list-topics-response.xml b/test/lib/aws-server-stubs/response-server/sns/responses/list-topics-response.xml new file mode 100644 index 0000000000..52db4cf6ed --- /dev/null +++ b/test/lib/aws-server-stubs/response-server/sns/responses/list-topics-response.xml @@ -0,0 +1,12 @@ + + + + + arn:sns:us-east-1:acctId:topic1 + + + arn:sns:us-east-1:acctId:topic2 + + + + diff --git a/test/lib/aws-server-stubs/response-server/sns/responses/publish-message-response.xml b/test/lib/aws-server-stubs/response-server/sns/responses/publish-message-response.xml new file mode 100644 index 0000000000..2d55d80fc7 --- /dev/null +++ b/test/lib/aws-server-stubs/response-server/sns/responses/publish-message-response.xml @@ -0,0 +1,9 @@ + + + 10000000000000080000 + b8bee936-3b18-5c1c-bd66-b0c969b618b6 + + + 648b4fd5-c97e-5ece-a8ca-162a9a4270a3 + + diff --git a/test/lib/aws-server-stubs/response-server/sqs/index.js b/test/lib/aws-server-stubs/response-server/sqs/index.js new file mode 100644 index 0000000000..cdc54b6f9e --- /dev/null +++ b/test/lib/aws-server-stubs/response-server/sqs/index.js @@ -0,0 +1,40 @@ +/* + * Copyright 2021 New Relic Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +'use strict' +const helpers = module.exports + +helpers.getCreateQueueResponse = function getCreateQueueResponse( + endpoint, + queueName, + isJson, + callback +) { + const createQueueResponse = require('./responses/create-queue-response')( + endpoint, + queueName, + isJson + ) + callback(null, createQueueResponse) +} + +helpers.formatUrl = function formatUrl(endpoint, queueName) { + return `${endpoint}/queue/${queueName}` +} + +helpers.getSendMessageResponse = function getSendMessageResponse(isJson, callback) { + const sendMessageResponse = require('./responses/send-message-response')(isJson) + callback(null, sendMessageResponse) +} + +helpers.getSendMessageBatchResponse = function getSendMessageBatchResponse(isJson, callback) { + const sendMessageBatchResponse = require('./responses/send-message-batch-response')(isJson) + callback(null, sendMessageBatchResponse) +} + +helpers.getReceiveMessageResponse = function getReceiveMessageResponse(isJson, callback) { + const receiveMessageResponse = require('./responses/receive-message-response')(isJson) + callback(null, receiveMessageResponse) +} diff --git a/test/lib/aws-server-stubs/response-server/sqs/responses/create-queue-response.js b/test/lib/aws-server-stubs/response-server/sqs/responses/create-queue-response.js new file mode 100644 index 0000000000..da086fb32c --- /dev/null +++ b/test/lib/aws-server-stubs/response-server/sqs/responses/create-queue-response.js @@ -0,0 +1,27 @@ +/* + * Copyright 2023 New Relic Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +'use strict' +const { formatUrl } = require('../index') + +module.exports = (endpoint, queueName, isJson) => { + if (isJson) { + return { + QueueUrl: formatUrl(endpoint, queueName), + ResponseMetadata: { + RequestId: 'cb919c0a-9bce-4afe-9b48-9bdf2412bb67' + } + } + } + return ` + + + ${formatUrl(endpoint, queueName)} + + + cb919c0a-9bce-4afe-9b48-9bdf2412bb67 + +` +} diff --git a/test/lib/aws-server-stubs/response-server/sqs/responses/receive-message-response.js b/test/lib/aws-server-stubs/response-server/sqs/responses/receive-message-response.js new file mode 100644 index 0000000000..3a8ba406db --- /dev/null +++ b/test/lib/aws-server-stubs/response-server/sqs/responses/receive-message-response.js @@ -0,0 +1,65 @@ +/* + * Copyright 2023 New Relic Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +'use strict' + +module.exports = (isJson) => { + if (isJson) { + return { + Messages: [ + { + MessageId: '5fea7756-0ea4-451a-a703-a558b933e274', + ReceiptHandle: + 'MbZj6wDWliJvwwJaBV3dcjk2YW2vA3STFFljTM8tJJg6HRG6PYSasuWXPJBCwLj1FjgXUv1uSj1gUPAWV66FU/WeR4mq2OKpEGYWbnLmpRCJVAyeMjeU5ZBdtcQQEauMZc8ZRv37sIW2iJKq3M9MFx1YvV11A2x/KSbkJ0=', + MD5OfBody: 'fafb00f5732ab283681e124bf8747ed1', + Body: 'This is a test message', + Attributes: { + SenderId: '195004372649', + SentTimestamp: '1238099229000', + ApproximateReceiveCount: '2', + ApproximateFirstReceiveTimestamp: '1595887234772' + } + } + ], + ResponseMetadata: { + RequestId: 'b6633655-283d-45b4-aee4-4e84e0ae6afa' + } + } + } + return ` + + + + 5fea7756-0ea4-451a-a703-a558b933e274 + + MbZj6wDWliJvwwJaBV3dcjk2YW2vA3STFFljTM8tJJg6HRG6PYSasuWXPJBCw + Lj1FjgXUv1uSj1gUPAWV66FU/WeR4mq2OKpEGYWbnLmpRCJVAyeMjeU5ZBdtcQQE + auMZc8ZRv37sIW2iJKq3M9MFx1YvV11A2x/KSbkJ0= + + fafb00f5732ab283681e124bf8747ed1 + This is a test message + + SenderId + 195004372649 + + + SentTimestamp + 1238099229000 + + + ApproximateReceiveCount + 2 + + + ApproximateFirstReceiveTimestamp + 1595887234772 + + + + + b6633655-283d-45b4-aee4-4e84e0ae6afa + +` +} diff --git a/test/lib/aws-server-stubs/response-server/sqs/responses/send-message-batch-response.js b/test/lib/aws-server-stubs/response-server/sqs/responses/send-message-batch-response.js new file mode 100644 index 0000000000..92338c6e83 --- /dev/null +++ b/test/lib/aws-server-stubs/response-server/sqs/responses/send-message-batch-response.js @@ -0,0 +1,47 @@ +/* + * Copyright 2023 New Relic Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +'use strict' + +module.exports = (isJson) => { + if (isJson) { + return { + Failed: [], + Successful: [ + { + Id: 'ONE', + MessageId: '0a5231c7-8bff-4955-be2e-8dc7c50a25fa', + MD5OfMessageBody: '8b2f30468657cfc118bbbebb6ad52b5a' + }, + { + Id: 'TWO', + MessageId: '15ee1ed3-87e7-40c1-bdaa-2e49968ea7e9', + MD5OfMessageBody: '446e666e0c0a8695b7a9693c082bc5da' + } + ], + ResponseMetadata: { + RequestId: 'ca1ad5d0-8271-408b-8d0f-1351bf547e74' + } + } + } + return ` + + + + ONE + 0a5231c7-8bff-4955-be2e-8dc7c50a25fa + 8b2f30468657cfc118bbbebb6ad52b5a + + + TWO + 15ee1ed3-87e7-40c1-bdaa-2e49968ea7e9 + 446e666e0c0a8695b7a9693c082bc5da + + + + ca1ad5d0-8271-408b-8d0f-1351bf547e74 + +` +} diff --git a/test/lib/aws-server-stubs/response-server/sqs/responses/send-message-response.js b/test/lib/aws-server-stubs/response-server/sqs/responses/send-message-response.js new file mode 100644 index 0000000000..6184374d9d --- /dev/null +++ b/test/lib/aws-server-stubs/response-server/sqs/responses/send-message-response.js @@ -0,0 +1,28 @@ +/* + * Copyright 2023 New Relic Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +'use strict' + +module.exports = (isJson) => { + if (isJson) { + return { + MD5OfMessageBody: 'fafb00f5732ab283681e124bf8747ed1', + MessageId: '5fea7756-0ea4-451a-a703-a558b933e274', + ResponseMetadata: { + RequestId: '27daac76-34dd-47df-bd01-1f6e873584a0' + } + } + } + return ` + + + fafb00f5732ab283681e124bf8747ed1 + 5fea7756-0ea4-451a-a703-a558b933e274 + + + 27daac76-34dd-47df-bd01-1f6e873584a0 + +` +} diff --git a/test/smoke/client-s3.tap.js b/test/smoke/client-s3.tap.js new file mode 100644 index 0000000000..56bbca7ffa --- /dev/null +++ b/test/smoke/client-s3.tap.js @@ -0,0 +1,77 @@ +/* + * Copyright 2023 New Relic Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +'use strict' + +const tap = require('tap') +const helper = require('../lib/agent_helper') +const { + DESTINATIONS: { TRANS_SEGMENT } +} = require('../../lib/config/attribute-filter') + +tap.test('@aws-sdk/client-s3 functionality', (t) => { + t.before(() => { + const { version, name } = require('@aws-sdk/client-s3/package') + // eslint-disable-next-line no-console + console.log(`AWS package: ${name} version: ${version}`) + }) + + t.beforeEach((t) => { + t.context.agent = helper.instrumentMockedAgent() + const { S3, ...lib } = require('@aws-sdk/client-s3') + t.context.client = new S3({ region: 'us-east-2' }) + t.context.GetObjectCommand = lib.GetObjectCommand + }) + + t.afterEach((t) => { + helper.unloadAgent(t.context.agent) + }) + + t.test('GetObjectCommand', (t) => { + const { agent, client, GetObjectCommand } = t.context + helper.runInTransaction(agent, async (transaction) => { + const command = new GetObjectCommand({ + Bucket: 'node-agent-aws-smoke-tests', + Key: 'test-file.json' + }) + + const { Body } = await client.send(command) + const fileContents = JSON.parse(await Body.transformToString()) + + t.same( + fileContents, + { items: [{ name: 'Item 1' }, { name: 'Item 2' }] }, + 'should successfully fetch test-file.json from S3' + ) + + transaction.end() + + const { url, procedure, ...awsAttributes } = + transaction.trace.root.children[1].attributes.get(TRANS_SEGMENT) + + delete awsAttributes.nr_exclusive_duration_millis + + t.equal( + url, + 'http://node-agent-aws-smoke-tests.s3.us-east-2.amazonaws.com/test-file.json', + 'should have url attribute in segment' + ) + t.equal(procedure, 'GET', 'should have method attribute in segment') + t.same( + awsAttributes, + { + 'aws.operation': 'GetObjectCommand', + 'aws.requestId': 'Unknown', + 'aws.service': 'S3', + 'aws.region': 'us-east-2' + }, + 'should have the proper AWS attributes in segment' + ) + + t.end() + }) + }) + t.end() +}) diff --git a/test/smoke/s3-presigned-url.tap.js b/test/smoke/s3-presigned-url.tap.js new file mode 100644 index 0000000000..000090529a --- /dev/null +++ b/test/smoke/s3-presigned-url.tap.js @@ -0,0 +1,72 @@ +/* + * Copyright 2023 New Relic Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +'use strict' + +const tap = require('tap') +const helper = require('../lib/agent_helper') +const https = require('https') + +tap.test('@aws-sdk/s3-request-presigner functionality', (t) => { + t.before(() => { + const { version, name } = require('@aws-sdk/s3-request-presigner/package') + // eslint-disable-next-line no-console + console.log(`AWS package: ${name} version: ${version}`) + }) + + t.beforeEach((t) => { + t.context.agent = helper.instrumentMockedAgent() + const { S3, ...lib } = require('@aws-sdk/client-s3') + t.context.client = new S3({ region: 'us-east-2' }) + t.context.GetObjectCommand = lib.GetObjectCommand + + const requestPresigner = require('@aws-sdk/s3-request-presigner') + t.context.getSignedUrl = requestPresigner.getSignedUrl + }) + + t.afterEach((t) => { + helper.unloadAgent(t.context.agent) + }) + + t.test('GetObjectCommand', (t) => { + const { agent, client, GetObjectCommand, getSignedUrl } = t.context + helper.runInTransaction(agent, async () => { + const command = new GetObjectCommand({ + Bucket: 'node-agent-aws-smoke-tests', + Key: 'test-file.json' + }) + + // VERY IMPORTANT: DO NOT LOG THIS OUT IN CI, ANYONE WITH ACCESS TO THE URL GETS ACCESS TO THE OBJECT + const url = await getSignedUrl(client, command, { expiresIn: 2 }) + + https + .get(url, (res) => { + const { statusCode } = res + + t.equal(statusCode, 200, 'should successfully access the object using the presigned url') + + let buff = '' + res.on('data', (chunk) => { + buff = buff + chunk.toString() + }) + + res.on('end', () => { + const body = JSON.parse(buff) + + t.same( + body, + { items: [{ name: 'Item 1' }, { name: 'Item 2' }] }, + 'should successfully fetch the object using the presigned url' + ) + t.end() + }) + }) + .on('error', () => { + throw new Error('Fetching object using presigned url failed, debug locally') + }) + }) + }) + t.end() +}) diff --git a/test/unit/api/api-instrument-loaded-module.test.js b/test/unit/api/api-instrument-loaded-module.test.js index b0e1acc2d9..43bfb28fb9 100644 --- a/test/unit/api/api-instrument-loaded-module.test.js +++ b/test/unit/api/api-instrument-loaded-module.test.js @@ -90,18 +90,18 @@ tap.test('Agent API - instrumentLoadedModule', (t) => { t.test('should not throw if supported module is not installed', function (t) { // We need a supported module in our test. We need that module _not_ to be - // installed. We'll use aws-sdk. This first bit ensures + // installed. We'll use mysql. This first bit ensures const EMPTY_MODULE = {} - let awsSdk = EMPTY_MODULE + let mod = EMPTY_MODULE try { // eslint-disable-next-line node/no-missing-require - awsSdk = require('aws-sdk') + mod = require('mysql') } catch (e) {} - t.ok(awsSdk === EMPTY_MODULE, 'aws-sdk is not installed') + t.ok(mod === EMPTY_MODULE, 'mysql is not installed') // attempt to instrument -- if nothing throws we're good try { - api.instrumentLoadedModule('aws-sdk', awsSdk) + api.instrumentLoadedModule('mysql', mod) } catch (e) { t.error(e) } diff --git a/test/unit/instrumentation/aws-sdk/util.test.js b/test/unit/instrumentation/aws-sdk/util.test.js new file mode 100644 index 0000000000..9ccfcecc41 --- /dev/null +++ b/test/unit/instrumentation/aws-sdk/util.test.js @@ -0,0 +1,97 @@ +/* + * Copyright 2020 New Relic Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +'use strict' +const tap = require('tap') +const { + grabLastUrlSegment, + setDynamoParameters +} = require('../../../../lib/instrumentation/aws-sdk/util') + +tap.test('Utility Functions', (t) => { + t.ok(grabLastUrlSegment, 'imported function successfully') + + const fixtures = [ + { + input: '/foo/baz/bar', + output: 'bar' + }, + { + input: null, + output: '' + }, + { + input: undefined, + output: '' + }, + { + input: NaN, + output: '' + } + ] + + for (const [, fixture] of fixtures.entries()) { + const result = grabLastUrlSegment(fixture.input) + t.equal(result, fixture.output, `expecting ${result} to equal ${fixture.output}`) + } + t.end() +}) + +tap.test('DB parameters', (t) => { + t.autoend() + + t.test('default values', (t) => { + const input = {} + const endpoint = {} + const result = setDynamoParameters(endpoint, input) + t.same( + result, + { + host: undefined, + database_name: null, + port_path_or_id: 443, + collection: 'Unknown' + }, + 'should set default values for parameters' + ) + t.end() + }) + + // v2 uses host key + t.test('host, port, collection', (t) => { + const input = { TableName: 'unit-test' } + const endpoint = { host: 'unit-test-host', port: '123' } + const result = setDynamoParameters(endpoint, input) + t.same( + result, + { + host: endpoint.host, + database_name: null, + port_path_or_id: endpoint.port, + collection: input.TableName + }, + 'should set appropriate parameters' + ) + t.end() + }) + + // v3 uses hostname key + t.test('hostname, port, collection', (t) => { + const input = { TableName: 'unit-test' } + const endpoint = { hostname: 'unit-test-host', port: '123' } + const result = setDynamoParameters(endpoint, input) + t.same( + result, + { + host: endpoint.hostname, + database_name: null, + port_path_or_id: endpoint.port, + collection: input.TableName + }, + 'should set appropriate parameters' + ) + t.end() + }) +}) diff --git a/test/unit/llm-events/aws-bedrock/bedrock-command.test.js b/test/unit/llm-events/aws-bedrock/bedrock-command.test.js new file mode 100644 index 0000000000..2f2e8ee2d2 --- /dev/null +++ b/test/unit/llm-events/aws-bedrock/bedrock-command.test.js @@ -0,0 +1,240 @@ +/* + * Copyright 2024 New Relic Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +'use strict' + +const tap = require('tap') +const structuredClone = require('./clone') +const BedrockCommand = require('../../../../lib/llm-events/aws-bedrock/bedrock-command') + +const ai21 = { + modelId: 'ai21.j2-mid-v1', + body: { + prompt: 'who are you' + } +} + +const claude = { + modelId: 'anthropic.claude-v1', + body: { + prompt: '\n\nHuman: yes\n\nAssistant:' + } +} + +const cohere = { + modelId: 'cohere.command-text-v14', + body: { + prompt: 'who are you' + } +} + +const cohereEmbed = { + modelId: 'cohere.embed-english-v3', + body: { + texts: ['who', 'are', 'you'], + input_type: 'search_document' + } +} + +const llama2 = { + modelId: 'meta.llama2-13b-chat-v1', + body: { + prompt: 'who are you' + } +} + +const titan = { + modelId: 'amazon.titan-text-lite-v1', + body: { + inputText: 'who are you' + } +} + +const titanEmbed = { + modelId: 'amazon.titan-embed-text-v1', + body: { + inputText: 'who are you' + } +} + +tap.beforeEach((t) => { + t.context.input = { + body: JSON.stringify('{"foo":"foo"}') + } + + t.context.updatePayload = (payload) => { + t.context.input.modelId = payload.modelId + t.context.input.body = JSON.stringify(payload.body) + } +}) + +tap.test('non-conforming command is handled gracefully', async (t) => { + const cmd = new BedrockCommand(t.context.input) + for (const model of [ + 'Ai21', + 'Claude', + 'Cohere', + 'CohereEmbed', + 'Llama2', + 'Titan', + 'TitanEmbed' + ]) { + t.equal(cmd[`is${model}`](), false) + } + t.equal(cmd.maxTokens, undefined) + t.equal(cmd.modelId, '') + t.equal(cmd.modelType, 'completion') + t.equal(cmd.prompt, undefined) + t.equal(cmd.temperature, undefined) +}) + +tap.test('ai21 minimal command works', async (t) => { + t.context.updatePayload(structuredClone(ai21)) + const cmd = new BedrockCommand(t.context.input) + t.equal(cmd.isAi21(), true) + t.equal(cmd.maxTokens, undefined) + t.equal(cmd.modelId, ai21.modelId) + t.equal(cmd.modelType, 'completion') + t.equal(cmd.prompt, ai21.body.prompt) + t.equal(cmd.temperature, undefined) +}) + +tap.test('ai21 complete command works', async (t) => { + const payload = structuredClone(ai21) + payload.body.maxTokens = 25 + payload.body.temperature = 0.5 + t.context.updatePayload(payload) + const cmd = new BedrockCommand(t.context.input) + t.equal(cmd.isAi21(), true) + t.equal(cmd.maxTokens, 25) + t.equal(cmd.modelId, payload.modelId) + t.equal(cmd.modelType, 'completion') + t.equal(cmd.prompt, payload.body.prompt) + t.equal(cmd.temperature, payload.body.temperature) +}) + +tap.test('claude minimal command works', async (t) => { + t.context.updatePayload(structuredClone(claude)) + const cmd = new BedrockCommand(t.context.input) + t.equal(cmd.isClaude(), true) + t.equal(cmd.maxTokens, undefined) + t.equal(cmd.modelId, claude.modelId) + t.equal(cmd.modelType, 'completion') + t.equal(cmd.prompt, claude.body.prompt) + t.equal(cmd.temperature, undefined) +}) + +tap.test('claude complete command works', async (t) => { + const payload = structuredClone(claude) + payload.body.max_tokens_to_sample = 25 + payload.body.temperature = 0.5 + t.context.updatePayload(payload) + const cmd = new BedrockCommand(t.context.input) + t.equal(cmd.isClaude(), true) + t.equal(cmd.maxTokens, 25) + t.equal(cmd.modelId, payload.modelId) + t.equal(cmd.modelType, 'completion') + t.equal(cmd.prompt, payload.body.prompt) + t.equal(cmd.temperature, payload.body.temperature) +}) + +tap.test('cohere minimal command works', async (t) => { + t.context.updatePayload(structuredClone(cohere)) + const cmd = new BedrockCommand(t.context.input) + t.equal(cmd.isCohere(), true) + t.equal(cmd.maxTokens, undefined) + t.equal(cmd.modelId, cohere.modelId) + t.equal(cmd.modelType, 'completion') + t.equal(cmd.prompt, cohere.body.prompt) + t.equal(cmd.temperature, undefined) +}) + +tap.test('cohere complete command works', async (t) => { + const payload = structuredClone(cohere) + payload.body.max_tokens = 25 + payload.body.temperature = 0.5 + t.context.updatePayload(payload) + const cmd = new BedrockCommand(t.context.input) + t.equal(cmd.isCohere(), true) + t.equal(cmd.maxTokens, 25) + t.equal(cmd.modelId, payload.modelId) + t.equal(cmd.modelType, 'completion') + t.equal(cmd.prompt, payload.body.prompt) + t.equal(cmd.temperature, payload.body.temperature) +}) + +tap.test('cohere embed minimal command works', async (t) => { + t.context.updatePayload(structuredClone(cohereEmbed)) + const cmd = new BedrockCommand(t.context.input) + t.equal(cmd.isCohereEmbed(), true) + t.equal(cmd.maxTokens, undefined) + t.equal(cmd.modelId, cohereEmbed.modelId) + t.equal(cmd.modelType, 'embedding') + t.same(cmd.prompt, cohereEmbed.body.texts.join(' ')) + t.equal(cmd.temperature, undefined) +}) + +tap.test('llama2 minimal command works', async (t) => { + t.context.updatePayload(structuredClone(llama2)) + const cmd = new BedrockCommand(t.context.input) + t.equal(cmd.isLlama2(), true) + t.equal(cmd.maxTokens, undefined) + t.equal(cmd.modelId, llama2.modelId) + t.equal(cmd.modelType, 'completion') + t.equal(cmd.prompt, llama2.body.prompt) + t.equal(cmd.temperature, undefined) +}) + +tap.test('llama2 complete command works', async (t) => { + const payload = structuredClone(llama2) + payload.body.max_gen_length = 25 + payload.body.temperature = 0.5 + t.context.updatePayload(payload) + const cmd = new BedrockCommand(t.context.input) + t.equal(cmd.isLlama2(), true) + t.equal(cmd.maxTokens, 25) + t.equal(cmd.modelId, payload.modelId) + t.equal(cmd.modelType, 'completion') + t.equal(cmd.prompt, payload.body.prompt) + t.equal(cmd.temperature, payload.body.temperature) +}) + +tap.test('titan minimal command works', async (t) => { + t.context.updatePayload(structuredClone(titan)) + const cmd = new BedrockCommand(t.context.input) + t.equal(cmd.isTitan(), true) + t.equal(cmd.maxTokens, undefined) + t.equal(cmd.modelId, titan.modelId) + t.equal(cmd.modelType, 'completion') + t.equal(cmd.prompt, titan.body.inputText) + t.equal(cmd.temperature, undefined) +}) + +tap.test('titan complete command works', async (t) => { + const payload = structuredClone(titan) + payload.body.textGenerationConfig = { + maxTokenCount: 25, + temperature: 0.5 + } + t.context.updatePayload(payload) + const cmd = new BedrockCommand(t.context.input) + t.equal(cmd.isTitan(), true) + t.equal(cmd.maxTokens, 25) + t.equal(cmd.modelId, payload.modelId) + t.equal(cmd.modelType, 'completion') + t.equal(cmd.prompt, payload.body.inputText) + t.equal(cmd.temperature, payload.body.textGenerationConfig.temperature) +}) + +tap.test('titan embed minimal command works', async (t) => { + t.context.updatePayload(structuredClone(titanEmbed)) + const cmd = new BedrockCommand(t.context.input) + t.equal(cmd.isTitanEmbed(), true) + t.equal(cmd.maxTokens, undefined) + t.equal(cmd.modelId, titanEmbed.modelId) + t.equal(cmd.modelType, 'embedding') + t.equal(cmd.prompt, titanEmbed.body.inputText) + t.equal(cmd.temperature, undefined) +}) diff --git a/test/unit/llm-events/aws-bedrock/bedrock-response.test.js b/test/unit/llm-events/aws-bedrock/bedrock-response.test.js new file mode 100644 index 0000000000..f28cd775c7 --- /dev/null +++ b/test/unit/llm-events/aws-bedrock/bedrock-response.test.js @@ -0,0 +1,231 @@ +/* + * Copyright 2024 New Relic Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +'use strict' + +const tap = require('tap') +const structuredClone = require('./clone') +const BedrockResponse = require('../../../../lib/llm-events/aws-bedrock/bedrock-response') + +const ai21 = { + id: 'ai21-response-1', + completions: [ + { + data: { + text: 'ai21-response' + }, + finishReason: { + reason: 'done' + } + } + ] +} + +const claude = { + completion: 'claude-response', + stop_reason: 'done' +} + +const cohere = { + id: 'cohere-response-1', + generations: [ + { + text: 'cohere-response', + finish_reason: 'done' + } + ] +} + +const llama2 = { + generation: 'llama2-response', + stop_reason: 'done' +} + +const titan = { + results: [ + { + outputText: 'titan-response', + completionReason: 'done' + } + ] +} + +tap.beforeEach((t) => { + t.context.response = { + response: { + statusCode: 200, + headers: { + 'x-amzn-requestid': 'aws-request-1', + 'x-foo': 'foo' + } + }, + output: { + body: new TextEncoder().encode('{"foo":"foo"}') + } + } + + t.context.bedrockCommand = { + isAi21() { + return false + }, + isClaude() { + return false + }, + isCohere() { + return false + }, + isLlama2() { + return false + }, + isTitan() { + return false + } + } + + t.context.updatePayload = (payload) => { + t.context.response.output.body = new TextEncoder().encode(JSON.stringify(payload)) + } +}) + +tap.test('non-conforming response is handled gracefully', async (t) => { + delete t.context.response.response.headers + const res = new BedrockResponse(t.context) + t.same(res.completions, []) + t.equal(res.finishReason, undefined) + t.same(res.headers, undefined) + t.equal(res.id, undefined) + t.equal(res.requestId, undefined) + t.equal(res.statusCode, 200) +}) + +tap.test('ai21 malformed responses work', async (t) => { + t.context.bedrockCommand.isAi21 = () => true + const res = new BedrockResponse(t.context) + t.same(res.completions, []) + t.equal(res.finishReason, undefined) + t.same(res.headers, t.context.response.response.headers) + t.equal(res.id, undefined) + t.equal(res.requestId, 'aws-request-1') + t.equal(res.statusCode, 200) +}) + +tap.test('ai21 complete responses work', async (t) => { + t.context.bedrockCommand.isAi21 = () => true + t.context.updatePayload(structuredClone(ai21)) + const res = new BedrockResponse(t.context) + t.same(res.completions, ['ai21-response']) + t.equal(res.finishReason, 'done') + t.same(res.headers, t.context.response.response.headers) + t.equal(res.id, 'ai21-response-1') + t.equal(res.requestId, 'aws-request-1') + t.equal(res.statusCode, 200) +}) + +tap.test('claude malformed responses work', async (t) => { + t.context.bedrockCommand.isClaude = () => true + const res = new BedrockResponse(t.context) + t.same(res.completions, []) + t.equal(res.finishReason, undefined) + t.same(res.headers, t.context.response.response.headers) + t.equal(res.id, undefined) + t.equal(res.requestId, 'aws-request-1') + t.equal(res.statusCode, 200) +}) + +tap.test('claude complete responses work', async (t) => { + t.context.bedrockCommand.isClaude = () => true + t.context.updatePayload(structuredClone(claude)) + const res = new BedrockResponse(t.context) + t.same(res.completions, ['claude-response']) + t.equal(res.finishReason, 'done') + t.same(res.headers, t.context.response.response.headers) + t.equal(res.id, undefined) + t.equal(res.requestId, 'aws-request-1') + t.equal(res.statusCode, 200) +}) + +tap.test('cohere malformed responses work', async (t) => { + t.context.bedrockCommand.isCohere = () => true + const res = new BedrockResponse(t.context) + t.same(res.completions, []) + t.equal(res.finishReason, undefined) + t.same(res.headers, t.context.response.response.headers) + t.equal(res.id, undefined) + t.equal(res.requestId, 'aws-request-1') + t.equal(res.statusCode, 200) +}) + +tap.test('cohere complete responses work', async (t) => { + t.context.bedrockCommand.isCohere = () => true + t.context.updatePayload(structuredClone(cohere)) + const res = new BedrockResponse(t.context) + t.same(res.completions, ['cohere-response']) + t.equal(res.finishReason, 'done') + t.same(res.headers, t.context.response.response.headers) + t.equal(res.id, 'cohere-response-1') + t.equal(res.requestId, 'aws-request-1') + t.equal(res.statusCode, 200) +}) + +tap.test('llama2 malformed responses work', async (t) => { + t.context.bedrockCommand.isLlama2 = () => true + const res = new BedrockResponse(t.context) + t.same(res.completions, []) + t.equal(res.finishReason, undefined) + t.same(res.headers, t.context.response.response.headers) + t.equal(res.id, undefined) + t.equal(res.requestId, 'aws-request-1') + t.equal(res.statusCode, 200) +}) + +tap.test('llama2 complete responses work', async (t) => { + t.context.bedrockCommand.isLlama2 = () => true + t.context.updatePayload(structuredClone(llama2)) + const res = new BedrockResponse(t.context) + t.same(res.completions, ['llama2-response']) + t.equal(res.finishReason, 'done') + t.same(res.headers, t.context.response.response.headers) + t.equal(res.id, undefined) + t.equal(res.requestId, 'aws-request-1') + t.equal(res.statusCode, 200) +}) + +tap.test('titan malformed responses work', async (t) => { + t.context.bedrockCommand.isTitan = () => true + const res = new BedrockResponse(t.context) + t.same(res.completions, []) + t.equal(res.finishReason, undefined) + t.same(res.headers, t.context.response.response.headers) + t.equal(res.id, undefined) + t.equal(res.requestId, 'aws-request-1') + t.equal(res.statusCode, 200) +}) + +tap.test('titan complete responses work', async (t) => { + t.context.bedrockCommand.isTitan = () => true + t.context.updatePayload(structuredClone(titan)) + const res = new BedrockResponse(t.context) + t.same(res.completions, ['titan-response']) + t.equal(res.finishReason, 'done') + t.same(res.headers, t.context.response.response.headers) + t.equal(res.id, undefined) + t.equal(res.requestId, 'aws-request-1') + t.equal(res.statusCode, 200) +}) + +tap.test('should only set data from raw response on error', (t) => { + t.context.response.$response = { ...t.context.response.response } + delete t.context.response.response + delete t.context.response.output + t.context.isError = true + const res = new BedrockResponse(t.context) + t.same(res.completions, []) + t.equal(res.id, undefined) + t.equal(res.finishReason, undefined) + t.same(res.headers, t.context.response.$response.headers) + t.equal(res.requestId, 'aws-request-1') + t.equal(res.statusCode, 200) + t.end() +}) diff --git a/test/unit/llm-events/aws-bedrock/chat-completion-message.test.js b/test/unit/llm-events/aws-bedrock/chat-completion-message.test.js new file mode 100644 index 0000000000..1dcebf7ff5 --- /dev/null +++ b/test/unit/llm-events/aws-bedrock/chat-completion-message.test.js @@ -0,0 +1,153 @@ +/* + * Copyright 2023 New Relic Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +'use strict' + +const tap = require('tap') +const { + DESTINATIONS: { TRANS_SCOPE } +} = require('../../../../lib/config/attribute-filter') +const LlmChatCompletionMessage = require('../../../../lib/llm-events/aws-bedrock/chat-completion-message') + +tap.beforeEach((t) => { + t.context.agent = { + llm: {}, + config: { + applications() { + return ['test-app'] + }, + ai_monitoring: { + enabled: true, + record_content: { + enabled: true + } + } + }, + tracer: { + getTransaction() { + return { + trace: { + custom: { + get(key) { + t.equal(key, TRANS_SCOPE) + return { + ['llm.conversation_id']: 'conversation-1' + } + } + } + } + } + } + } + } + + t.context.completionId = 'completion-1' + + t.context.content = 'a prompt' + + t.context.segment = { + id: 'segment-1', + transaction: { + id: 'tx-1', + traceId: 'trace-1' + } + } + + t.context.bedrockResponse = { + headers: { + 'x-amzn-requestid': 'request-1' + }, + get inputTokenCount() { + return 8 + }, + get outputTokenCount() { + return 4 + } + } + + t.context.bedrockCommand = { + id: 'cmd-1', + prompt: 'who are you', + isAi21() { + return false + }, + isClaude() { + return false + }, + isCohere() { + return false + }, + isTitan() { + return false + } + } +}) + +tap.test('create creates a non-response instance', async (t) => { + t.context.agent.llm.tokenCountCallback = () => 3 + const event = new LlmChatCompletionMessage(t.context) + t.equal(event.is_response, false) + t.equal(event['llm.conversation_id'], 'conversation-1') + t.equal(event.completion_id, 'completion-1') + t.equal(event.sequence, 0) + t.equal(event.content, 'who are you') + t.equal(event.role, 'user') + t.match(event.id, /[\w-]{36}/) + t.equal(event.token_count, 3) +}) + +tap.test('create creates a titan response instance', async (t) => { + t.context.bedrockCommand.isTitan = () => true + t.context.content = 'a response' + t.context.isResponse = true + const event = new LlmChatCompletionMessage(t.context) + t.equal(event.is_response, true) + t.equal(event['llm.conversation_id'], 'conversation-1') + t.equal(event.completion_id, 'completion-1') + t.equal(event.sequence, 0) + t.equal(event.content, 'a response') + t.equal(event.role, 'assistant') + t.match(event.id, /[\w-]{36}-0/) +}) + +tap.test('create creates a cohere response instance', async (t) => { + t.context.bedrockCommand.isCohere = () => true + t.context.content = 'a response' + t.context.isResponse = true + t.context.bedrockResponse.id = 42 + const event = new LlmChatCompletionMessage(t.context) + t.equal(event.is_response, true) + t.equal(event['llm.conversation_id'], 'conversation-1') + t.equal(event.completion_id, 'completion-1') + t.equal(event.sequence, 0) + t.equal(event.content, 'a response') + t.equal(event.role, 'assistant') + t.match(event.id, /42-0/) +}) + +tap.test('create creates a ai21 response instance when response.id is undefined', async (t) => { + t.context.bedrockCommand.isAi21 = () => true + t.context.content = 'a response' + t.context.isResponse = true + delete t.context.bedrockResponse.id + const event = new LlmChatCompletionMessage(t.context) + t.equal(event.is_response, true) + t.equal(event['llm.conversation_id'], 'conversation-1') + t.equal(event.completion_id, 'completion-1') + t.equal(event.sequence, 0) + t.equal(event.content, 'a response') + t.equal(event.role, 'assistant') + t.match(event.id, /[\w-]{36}-0/) +}) + +tap.test( + 'should not capture content when `ai_monitoring.record_content.enabled` is false', + async (t) => { + const { agent } = t.context + agent.config.ai_monitoring.record_content.enabled = false + const event = new LlmChatCompletionMessage(t.context) + t.equal(event.content, undefined, 'content should be empty') + } +) diff --git a/test/unit/llm-events/aws-bedrock/chat-completion-summary.test.js b/test/unit/llm-events/aws-bedrock/chat-completion-summary.test.js new file mode 100644 index 0000000000..a7cfdf90f8 --- /dev/null +++ b/test/unit/llm-events/aws-bedrock/chat-completion-summary.test.js @@ -0,0 +1,142 @@ +/* + * Copyright 2024 New Relic Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +'use strict' + +const tap = require('tap') +const { + DESTINATIONS: { TRANS_SCOPE } +} = require('../../../../lib/config/attribute-filter') +const LlmChatCompletionSummary = require('../../../../lib/llm-events/aws-bedrock/chat-completion-summary') + +tap.beforeEach((t) => { + t.context.agent = { + config: { + applications() { + return ['test-app'] + } + }, + tracer: { + getTransaction() { + return { + trace: { + custom: { + get(key) { + t.equal(key, TRANS_SCOPE) + return { + ['llm.conversation_id']: 'conversation-1' + } + } + } + } + } + } + } + } + + t.context.segment = { + transaction: { + id: 'tx-1' + }, + getDurationInMillis() { + return 100 + } + } + + t.context.bedrockCommand = { + maxTokens: 25, + temperature: 0.5, + isAi21() { + return false + }, + isClaude() { + return false + }, + isCohere() { + return false + }, + isLlama2() { + return false + }, + isTitan() { + return false + } + } + + t.context.bedrockResponse = { + headers: { + 'x-amzn-request-id': 'aws-request-1' + }, + finishReason: 'done', + completions: ['completion-1'] + } +}) + +tap.test('creates a basic summary', async (t) => { + t.context.bedrockResponse.inputTokenCount = 0 + t.context.bedrockResponse.outputTokenCount = 0 + const event = new LlmChatCompletionSummary(t.context) + t.equal(event['llm.conversation_id'], 'conversation-1') + t.equal(event.duration, 100) + t.equal(event['request.max_tokens'], 25) + t.equal(event['request.temperature'], 0.5) + t.equal(event['response.choices.finish_reason'], 'done') + t.equal(event['response.number_of_messages'], 2) +}) + +tap.test('creates an ai21 summary', async (t) => { + t.context.bedrockCommand.isAi21 = () => true + const event = new LlmChatCompletionSummary(t.context) + t.equal(event['llm.conversation_id'], 'conversation-1') + t.equal(event.duration, 100) + t.equal(event['request.max_tokens'], 25) + t.equal(event['request.temperature'], 0.5) + t.equal(event['response.choices.finish_reason'], 'done') + t.equal(event['response.number_of_messages'], 2) +}) + +tap.test('creates an claude summary', async (t) => { + t.context.bedrockCommand.isClaude = () => true + const event = new LlmChatCompletionSummary(t.context) + t.equal(event['llm.conversation_id'], 'conversation-1') + t.equal(event.duration, 100) + t.equal(event['request.max_tokens'], 25) + t.equal(event['request.temperature'], 0.5) + t.equal(event['response.choices.finish_reason'], 'done') + t.equal(event['response.number_of_messages'], 2) +}) + +tap.test('creates a cohere summary', async (t) => { + t.context.bedrockCommand.isCohere = () => true + const event = new LlmChatCompletionSummary(t.context) + t.equal(event['llm.conversation_id'], 'conversation-1') + t.equal(event.duration, 100) + t.equal(event['request.max_tokens'], 25) + t.equal(event['request.temperature'], 0.5) + t.equal(event['response.choices.finish_reason'], 'done') + t.equal(event['response.number_of_messages'], 2) +}) + +tap.test('creates a llama2 summary', async (t) => { + t.context.bedrockCommand.isLlama2 = () => true + const event = new LlmChatCompletionSummary(t.context) + t.equal(event['llm.conversation_id'], 'conversation-1') + t.equal(event.duration, 100) + t.equal(event['request.max_tokens'], 25) + t.equal(event['request.temperature'], 0.5) + t.equal(event['response.choices.finish_reason'], 'done') + t.equal(event['response.number_of_messages'], 2) +}) + +tap.test('creates a titan summary', async (t) => { + t.context.bedrockCommand.isTitan = () => true + const event = new LlmChatCompletionSummary(t.context) + t.equal(event['llm.conversation_id'], 'conversation-1') + t.equal(event.duration, 100) + t.equal(event['request.max_tokens'], 25) + t.equal(event['request.temperature'], 0.5) + t.equal(event['response.choices.finish_reason'], 'done') + t.equal(event['response.number_of_messages'], 2) +}) diff --git a/test/unit/llm-events/aws-bedrock/clone.js b/test/unit/llm-events/aws-bedrock/clone.js new file mode 100644 index 0000000000..723d5e5451 --- /dev/null +++ b/test/unit/llm-events/aws-bedrock/clone.js @@ -0,0 +1,25 @@ +/* + * Copyright 2024 New Relic Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +'use strict' + +if (global.structuredClone) { + module.exports = global.structuredClone +} else { + module.exports = function sc(input) { + const result = {} + for (const [k, v] of Object.entries(input)) { + if (Array.isArray(v) === true) { + result[k] = [] + Array.prototype.push.apply(result[k], v) + } else if (Object.prototype.toString.call(v) === '[object Object]') { + result[k] = sc(v) + } else { + result[k] = v + } + } + return result + } +} diff --git a/test/unit/llm-events/aws-bedrock/embedding.test.js b/test/unit/llm-events/aws-bedrock/embedding.test.js new file mode 100644 index 0000000000..b3457211e9 --- /dev/null +++ b/test/unit/llm-events/aws-bedrock/embedding.test.js @@ -0,0 +1,84 @@ +/* + * Copyright 2024 New Relic Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +'use strict' + +const tap = require('tap') +const { + DESTINATIONS: { TRANS_SCOPE } +} = require('../../../../lib/config/attribute-filter') +const LlmEmbedding = require('../../../../lib/llm-events/aws-bedrock/embedding') + +tap.beforeEach((t) => { + t.context.agent = { + llm: {}, + config: { + applications() { + return ['test-app'] + }, + ai_monitoring: { + enabled: true, + record_content: { + enabled: true + } + } + }, + tracer: { + getTransaction() { + return { + trace: { + custom: { + get(key) { + t.equal(key, TRANS_SCOPE) + return { + ['llm.conversation_id']: 'conversation-1' + } + } + } + } + } + } + } + } + + t.context.bedrockCommand = { + prompt: 'who are you' + } + + t.context.bedrockResponse = { + headers: { + 'x-amzn-requestid': 'request-1' + } + } + t.context.segment = { + transaction: { traceId: 'id' }, + getDurationInMillis() { + return 1.008 + } + } +}) + +tap.test('creates a basic embedding', async (t) => { + const event = new LlmEmbedding(t.context) + t.equal(event.input, 'who are you') + t.equal(event.duration, 1.008) + t.equal(event.token_count, undefined) +}) + +tap.test( + 'should not capture input when `ai_monitoring.record_content.enabled` is false', + async (t) => { + const { agent } = t.context + agent.config.ai_monitoring.record_content.enabled = false + const event = new LlmEmbedding(t.context) + t.equal(event.input, undefined, 'input should be empty') + } +) + +tap.test('should capture token_count when callback is defined', async (t) => { + t.context.agent.llm.tokenCountCallback = () => 3 + const event = new LlmEmbedding(t.context) + t.equal(event.token_count, 3) +}) diff --git a/test/unit/llm-events/aws-bedrock/error.test.js b/test/unit/llm-events/aws-bedrock/error.test.js new file mode 100644 index 0000000000..36e79d6aee --- /dev/null +++ b/test/unit/llm-events/aws-bedrock/error.test.js @@ -0,0 +1,56 @@ +/* + * Copyright 2024 New Relic Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +'use strict' + +const tap = require('tap') +const LlmError = require('../../../../lib/llm-events/aws-bedrock/error') + +tap.beforeEach((t) => { + t.context.bedrockResponse = { + statusCode: 400 + } + + t.context.err = { + message: 'No soup for you', + name: 'SoupRule' + } + + t.context.summary = { + id: 'completion-id' + } +}) + +tap.test('create creates a new instance', (t) => { + const err = new LlmError(t.context) + t.equal(err['http.statusCode'], 400) + t.equal(err['error.message'], 'No soup for you') + t.equal(err['error.code'], 'SoupRule') + t.equal(err.completion_id, 'completion-id') + t.notOk(err.embedding_id) + t.end() +}) + +tap.test('create error with embedding_id', (t) => { + delete t.context.summary + t.context.embedding = { id: 'embedding-id' } + const err = new LlmError(t.context) + t.equal(err['http.statusCode'], 400) + t.equal(err['error.message'], 'No soup for you') + t.equal(err['error.code'], 'SoupRule') + t.equal(err.embedding_id, 'embedding-id') + t.notOk(err.completion_id) + t.end() +}) + +tap.test('empty error', (t) => { + const err = new LlmError() + t.notOk(err['http.statusCode']) + t.notOk(err['error.message']) + t.notOk(err['error.code']) + t.notOk(err.completion_id) + t.notOk(err.embedding_id) + t.end() +}) diff --git a/test/unit/llm-events/aws-bedrock/event.test.js b/test/unit/llm-events/aws-bedrock/event.test.js new file mode 100644 index 0000000000..5100c72e5a --- /dev/null +++ b/test/unit/llm-events/aws-bedrock/event.test.js @@ -0,0 +1,80 @@ +/* + * Copyright 2023 New Relic Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +'use strict' + +const tap = require('tap') +const { + DESTINATIONS: { TRANS_SCOPE } +} = require('../../../../lib/config/attribute-filter') +const LlmEvent = require('../../../../lib/llm-events/aws-bedrock/event') + +tap.beforeEach((t) => { + t.context.agent = { + config: { + applications() { + return ['test-app'] + } + }, + tracer: { + getTransaction() { + return { + trace: { + custom: { + get(key) { + t.equal(key, TRANS_SCOPE) + return { + ['llm.conversation_id']: 'conversation-1', + omit: 'me' + } + } + } + } + } + } + } + } + + t.context.segment = { + id: 'segment-1', + transaction: { + traceId: 'trace-1' + } + } + + t.context.bedrockResponse = { + requestId: 'request-1' + } + + t.context.bedrockCommand = { + modelId: 'model-1' + } +}) + +tap.test('create creates a new instance', async (t) => { + const event = new LlmEvent(t.context) + t.ok(event) + t.match(event.id, /[a-z0-9]{7}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{12}/) + t.equal(event.vendor, 'bedrock') + t.equal(event.ingest_source, 'Node') + t.equal(event.appName, 'test-app') + t.equal(event.span_id, 'segment-1') + t.equal(event.trace_id, 'trace-1') + t.equal(event.request_id, 'request-1') + t.equal(event['response.model'], 'model-1') + t.equal(event['request.model'], 'model-1') + t.equal(event['request.max_tokens'], null) + t.equal(event['llm.conversation_id'], 'conversation-1') + t.equal(event.omit, undefined) +}) + +tap.test('serializes the event', (t) => { + const event = new LlmEvent(t.context) + event.serialize() + t.notOk(event.bedrockCommand) + t.notOk(event.bedrockResponse) + t.notOk(event.constructionParams) + t.end() +}) diff --git a/test/unit/llm-events/aws-bedrock/stream-handler.test.js b/test/unit/llm-events/aws-bedrock/stream-handler.test.js new file mode 100644 index 0000000000..67a1b7e5eb --- /dev/null +++ b/test/unit/llm-events/aws-bedrock/stream-handler.test.js @@ -0,0 +1,296 @@ +/* + * Copyright 2024 New Relic Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +'use strict' + +const tap = require('tap') +const { + BedrockCommand, + BedrockResponse, + StreamHandler +} = require('../../../../lib/llm-events/aws-bedrock') + +tap.beforeEach((t) => { + t.context.response = { + response: { + headers: { + 'x-amzn-requestid': 'aws-req-1' + }, + statusCode: 200 + }, + output: { + body: {} + } + } + + t.context.passThroughParams = { + response: t.context.response, + segment: { + touch() { + t.pass() + } + }, + bedrockCommand: { + isCohere() { + return false + }, + isCohereEmbed() { + return false + }, + isClaude() { + return false + }, + isLlama2() { + return false + }, + isTitan() { + return false + } + } + } + + t.context.onComplete = (params) => { + t.same(params, t.context.passThroughParams) + } + + t.context.chunks = [{ foo: 'foo' }] + + /* eslint-disable prettier/prettier */ // It doesn't like the IIFE syntax + t.context.stream = (async function* originalStream() { + const encoder = new TextEncoder() + for (const chunk of t.context.chunks) { + const json = JSON.stringify(chunk) + const bytes = encoder.encode(json) + yield { chunk: { bytes } } + } + }()) + /* eslint-enable prettier/prettier */ +}) + +tap.test('unrecognized or unhandled model uses original stream', async (t) => { + t.context.modelId = 'amazon.titan-embed-text-v1' + const handler = new StreamHandler(t.context) + t.equal(handler.generator.name, undefined) + t.equal(handler.generator, t.context.stream) +}) + +tap.test('handles claude streams', async (t) => { + t.context.passThroughParams.bedrockCommand.isClaude = () => true + t.context.chunks = [ + { completion: '1', stop_reason: null }, + { completion: '2', stop_reason: 'done', ...t.context.metrics } + ] + const handler = new StreamHandler(t.context) + + t.equal(handler.generator.name, 'handleClaude') + for await (const event of handler.generator()) { + t.type(event.chunk.bytes, Uint8Array) + } + t.same(handler.response, { + response: { + headers: { + 'x-amzn-requestid': 'aws-req-1' + }, + statusCode: 200 + }, + output: { + body: new TextEncoder().encode(JSON.stringify({ completion: '12', stop_reason: 'done' })) + } + }) + + const bc = new BedrockCommand({ + modelId: 'anthropic.claude', + body: JSON.stringify({ + prompt: 'prompt', + maxTokens: 5 + }) + }) + const br = new BedrockResponse({ bedrockCommand: bc, response: handler.response }) + t.equal(br.completions.length, 1) + t.equal(br.finishReason, 'done') + t.equal(br.requestId, 'aws-req-1') + t.equal(br.statusCode, 200) +}) + +tap.test('handles cohere streams', async (t) => { + t.context.passThroughParams.bedrockCommand.isCohere = () => true + t.context.chunks = [ + { generations: [{ text: '1', finish_reason: null }] }, + { generations: [{ text: '2', finish_reason: 'done' }], ...t.context.metrics } + ] + const handler = new StreamHandler(t.context) + + t.equal(handler.generator.name, 'handleCohere') + for await (const event of handler.generator()) { + t.type(event.chunk.bytes, Uint8Array) + } + t.same(handler.response, { + response: { + headers: { + 'x-amzn-requestid': 'aws-req-1' + }, + statusCode: 200 + }, + output: { + body: new TextEncoder().encode( + JSON.stringify({ + generations: [ + { text: '1', finish_reason: null }, + { text: '2', finish_reason: 'done' } + ] + }) + ) + } + }) + + const bc = new BedrockCommand({ + modelId: 'cohere.', + body: JSON.stringify({ + texts: ['prompt'], + max_tokens: 5 + }) + }) + const br = new BedrockResponse({ bedrockCommand: bc, response: handler.response }) + t.equal(br.completions.length, 2) + t.equal(br.finishReason, 'done') + t.equal(br.requestId, 'aws-req-1') + t.equal(br.statusCode, 200) +}) + +tap.test('handles cohere embedding streams', async (t) => { + t.context.passThroughParams.bedrockCommand.isCohereEmbed = () => true + t.context.chunks = [ + { + embeddings: [ + [1, 2], + [3, 4] + ], + ...t.context.metrics + } + ] + const handler = new StreamHandler(t.context) + + t.equal(handler.generator.name, 'handleCohereEmbed') + for await (const event of handler.generator()) { + t.type(event.chunk.bytes, Uint8Array) + } + t.same(handler.response, { + response: { + headers: { + 'x-amzn-requestid': 'aws-req-1' + }, + statusCode: 200 + }, + output: { + body: new TextEncoder().encode( + JSON.stringify({ + embeddings: [ + [1, 2], + [3, 4] + ] + }) + ) + } + }) + + const bc = new BedrockCommand({ + modelId: 'cohere.', + body: JSON.stringify({ + texts: ['prompt'], + max_tokens: 5 + }) + }) + const br = new BedrockResponse({ bedrockCommand: bc, response: handler.response }) + t.equal(br.completions.length, 0) + t.equal(br.finishReason, undefined) + t.equal(br.requestId, 'aws-req-1') + t.equal(br.statusCode, 200) +}) + +tap.test('handles llama2 streams', async (t) => { + t.context.passThroughParams.bedrockCommand.isLlama2 = () => true + t.context.chunks = [ + { generation: '1', stop_reason: null }, + { generation: '2', stop_reason: 'done', ...t.context.metrics } + ] + const handler = new StreamHandler(t.context) + + t.equal(handler.generator.name, 'handleLlama2') + for await (const event of handler.generator()) { + t.type(event.chunk.bytes, Uint8Array) + } + t.same(handler.response, { + response: { + headers: { + 'x-amzn-requestid': 'aws-req-1' + }, + statusCode: 200 + }, + output: { + body: new TextEncoder().encode(JSON.stringify({ generation: '12', stop_reason: 'done' })) + } + }) + + const bc = new BedrockCommand({ + modelId: 'meta.llama2', + body: JSON.stringify({ + prompt: 'prompt', + max_gen_length: 5 + }) + }) + const br = new BedrockResponse({ bedrockCommand: bc, response: handler.response }) + t.equal(br.completions.length, 1) + t.equal(br.finishReason, 'done') + t.equal(br.requestId, 'aws-req-1') + t.equal(br.statusCode, 200) +}) + +tap.test('handles titan streams', async (t) => { + t.context.passThroughParams.bedrockCommand.isTitan = () => true + t.context.chunks = [ + { outputText: '1', completionReason: null }, + { outputText: '2', completionReason: 'done', ...t.context.metrics } + ] + const handler = new StreamHandler(t.context) + + t.equal(handler.generator.name, 'handleTitan') + for await (const event of handler.generator()) { + t.type(event.chunk.bytes, Uint8Array) + } + t.same(handler.response, { + response: { + headers: { + 'x-amzn-requestid': 'aws-req-1' + }, + statusCode: 200 + }, + output: { + body: new TextEncoder().encode( + JSON.stringify({ + results: [ + { outputText: '1', completionReason: null }, + { outputText: '2', completionReason: 'done' } + ] + }) + ) + } + }) + + const bc = new BedrockCommand({ + modelId: 'amazon.titan', + body: JSON.stringify({ + inputText: 'prompt', + textGenerationConfig: { + maxTokenCount: 5, + temperature: 0.5 + } + }) + }) + const br = new BedrockResponse({ bedrockCommand: bc, response: handler.response }) + t.equal(br.completions.length, 2) + t.equal(br.finishReason, 'done') + t.equal(br.requestId, 'aws-req-1') + t.equal(br.statusCode, 200) +}) diff --git a/test/versioned-external/external-repos.js b/test/versioned-external/external-repos.js index f6c2565958..73b4b52412 100644 --- a/test/versioned-external/external-repos.js +++ b/test/versioned-external/external-repos.js @@ -12,11 +12,6 @@ * additionalFiles: String array of files/folders to checkout in addition to lib and tests/versioned. */ const repos = [ - { - name: 'aws-sdk', - repository: 'https://github.com/newrelic/node-newrelic-aws-sdk.git', - branch: 'main' - }, { name: 'next', repository: 'https://github.com/newrelic/newrelic-node-nextjs.git', diff --git a/test/versioned/aws-sdk-v2/amazon-dax-client.tap.js b/test/versioned/aws-sdk-v2/amazon-dax-client.tap.js new file mode 100644 index 0000000000..e9b1d95db3 --- /dev/null +++ b/test/versioned/aws-sdk-v2/amazon-dax-client.tap.js @@ -0,0 +1,100 @@ +/* + * Copyright 2020 New Relic Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +'use strict' + +const tap = require('tap') +const common = require('../aws-sdk-v3/common') +const helper = require('../../lib/agent_helper') +const { FAKE_CREDENTIALS } = require('../../lib/aws-server-stubs') + +// This will not resolve / allow web requests. Even with real ones, requests +// have to execute within the same VPC as the DAX configuration. When adding DAX support, +// we may be able to fake part of this via nock or similar. +const DAX_ENDPOINTS = [ + 'this.is.not.real1.amazonaws.com:8111', + 'this.is.not.real2.amazonaws.com:8111' +] + +tap.test('amazon-dax-client', (t) => { + t.autoend() + + t.beforeEach(() => { + t.context.agent = helper.instrumentMockedAgent() + const AWS = require('aws-sdk') + const AmazonDaxClient = require('amazon-dax-client') + + const daxClient = new AmazonDaxClient({ + credentials: FAKE_CREDENTIALS, + endpoints: DAX_ENDPOINTS, + maxRetries: 0 // fail fast + }) + t.context.docClient = new AWS.DynamoDB.DocumentClient({ service: daxClient }) + }) + + t.afterEach((t) => { + helper.unloadAgent(t.context.agent) + }) + + t.test('should not crash when using DAX', (t) => { + const { agent, docClient } = t.context + helper.runInTransaction(agent, () => { + // We don't need a successful case to repro + const getParam = getDocItemParams('TableDoesNotExist', 'ArtistDoesNotExist') + docClient.get(getParam, (err) => { + t.ok(err) + t.end() + }) + }) + }) + + t.test('should capture instance data as unknown using DAX', (t) => { + const { agent, docClient } = t.context + helper.runInTransaction(agent, (transaction) => { + // We don't need a successful case to repro + const getParam = getDocItemParams('TableDoesNotExist', 'ArtistDoesNotExist') + docClient.get(getParam, (err) => { + t.ok(err) + + const root = transaction.trace.root + + // Won't have the attributes cause not making web request... + const segments = common.getMatchingSegments(t, root, common.DATASTORE_PATTERN) + + t.equal(segments.length, 1) + + const externalSegments = common.checkAWSAttributes(t, root, common.EXTERN_PATTERN) + t.equal(externalSegments.length, 0, 'should not have any External segments') + + const segment = segments[0] + t.equal(segment.name, 'Datastore/operation/DynamoDB/getItem') + + const attrs = segment.attributes.get(common.SEGMENT_DESTINATION) + t.match( + attrs, + { + host: 'unknown', + port_path_or_id: 'unknown', + collection: 'TableDoesNotExist', + product: 'DynamoDB' + }, + 'should have expected attributes' + ) + + t.end() + }) + }) + }) +}) + +function getDocItemParams(tableName, uniqueArtist) { + return { + Key: { + Artist: uniqueArtist, + SongTitle: 'Call Me Today' + }, + TableName: tableName + } +} diff --git a/test/versioned/aws-sdk-v2/aws-sdk.tap.js b/test/versioned/aws-sdk-v2/aws-sdk.tap.js new file mode 100644 index 0000000000..d942436d9c --- /dev/null +++ b/test/versioned/aws-sdk-v2/aws-sdk.tap.js @@ -0,0 +1,117 @@ +/* + * Copyright 2020 New Relic Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +'use strict' + +const sinon = require('sinon') +const tap = require('tap') +const helper = require('../../lib/agent_helper') +const symbols = require('../../../lib/symbols') + +const { createEmptyResponseServer, FAKE_CREDENTIALS } = require('../../lib/aws-server-stubs') + +tap.test('aws-sdk', (t) => { + t.autoend() + + t.beforeEach(async (t) => { + const server = createEmptyResponseServer() + + await new Promise((resolve) => { + server.listen(0, resolve) + }) + + t.context.server = server + + t.context.agent = helper.instrumentMockedAgent() + const AWS = require('aws-sdk') + AWS.config.update({ region: 'us-east-1' }) + t.context.AWS = AWS + + t.context.endpoint = `http://localhost:${server.address().port}` + }) + + t.afterEach((t) => { + t.context.server.close() + helper.unloadAgent(t.context.agent) + }) + + t.test('should mark requests to be dt-disabled', (t) => { + const { AWS, endpoint } = t.context + // http because we've changed endpoint to be http + const http = require('http') + sinon.spy(http, 'request') + t.teardown(() => { + // `afterEach` runs before `tearDown`, so the sinon spy may have already + // been removed. + if (http.request.restore) { + http.request.restore() + } + }) + + const s3 = new AWS.S3({ + apiVersion: '2006-03-01', + credentials: FAKE_CREDENTIALS, + endpoint: endpoint, + // allows using generic endpoint, instead of needing a + // bucket.endpoint server setup. + s3ForcePathStyle: true, + params: { Bucket: 'bucket' } + }) + s3.listObjects({ Delimiter: '/' }, (err) => { + t.error(err) + + if (t.ok(http.request.calledOnce, 'should call http.request')) { + const args = http.request.getCall(0).args + const headers = args[0].headers + t.equal(headers[symbols.disableDT], true) + } + t.end() + }) + }) + + t.test('should maintain transaction state in promises', (t) => { + const { AWS, endpoint, agent } = t.context + const service = new AWS.SES({ + credentials: FAKE_CREDENTIALS, + endpoint + }) + + helper.runInTransaction(agent, (tx) => { + service + .cloneReceiptRuleSet({ + OriginalRuleSetName: 'RuleSetToClone', + RuleSetName: 'RuleSetToCreate' + }) + .promise() + .then(() => { + t.equal(tx.id, agent.getTransaction().id) + tx.end() + ender() + }) + }) + + // Run two concurrent promises to check for conflation + helper.runInTransaction(agent, (tx) => { + service + .cloneReceiptRuleSet({ + OriginalRuleSetName: 'RuleSetToClone', + RuleSetName: 'RuleSetToCreate' + }) + .promise() + .then(() => { + t.equal(tx.id, agent.getTransaction().id) + tx.end() + ender() + }) + }) + + let count = 0 + function ender() { + if (++count === 2) { + t.end() + } + } + }) +}) diff --git a/test/versioned/aws-sdk-v2/dynamodb.tap.js b/test/versioned/aws-sdk-v2/dynamodb.tap.js new file mode 100644 index 0000000000..88cf85078d --- /dev/null +++ b/test/versioned/aws-sdk-v2/dynamodb.tap.js @@ -0,0 +1,251 @@ +/* + * Copyright 2020 New Relic Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +'use strict' + +const tap = require('tap') +const helper = require('../../lib/agent_helper') +const common = require('../aws-sdk-v3/common') +const { createEmptyResponseServer, FAKE_CREDENTIALS } = require('../../lib/aws-server-stubs') + +tap.test('DynamoDB', (t) => { + t.autoend() + + t.beforeEach(async (t) => { + const server = createEmptyResponseServer() + + await new Promise((resolve) => { + server.listen(0, resolve) + }) + + t.context.server = server + + t.context.agent = helper.instrumentMockedAgent() + + const AWS = require('aws-sdk') + + const endpoint = `http://localhost:${server.address().port}` + const ddb = new AWS.DynamoDB({ + credentials: FAKE_CREDENTIALS, + endpoint, + region: 'us-east-1' + }) + const docClient = new AWS.DynamoDB.DocumentClient({ + credentials: FAKE_CREDENTIALS, + endpoint, + region: 'us-east-1' + }) + + const tableName = `delete-aws-sdk-test-table-${Math.floor(Math.random() * 100000)}` + t.context.tests = createTests(ddb, docClient, tableName) + }) + + t.afterEach((t) => { + t.context.server.close() + helper.unloadAgent(t.context.agent) + }) + + t.test('commands with callback', (t) => { + const { tests, agent } = t.context + helper.runInTransaction(agent, async (tx) => { + for (const test of tests) { + t.comment(`Testing ${test.method}`) + + await new Promise((resolve) => { + test.api[test.method](test.params, (err) => { + t.error(err) + + return setImmediate(resolve) + }) + }) + } + + tx.end() + + const args = [t, tests, tx] + setImmediate(finish, ...args) + }) + }) + + t.test('commands with promises', (t) => { + const { tests, agent } = t.context + helper.runInTransaction(agent, async function (tx) { + // Execute commands in order + // Await works because this is in a for-loop / no callback api + for (let i = 0; i < tests.length; i++) { + const cfg = tests[i] + + t.comment(`Testing ${cfg.method}`) + + try { + await cfg.api[cfg.method](cfg.params).promise() + } catch (err) { + t.error(err) + } + } + + tx.end() + + const args = [t, tests, tx] + setImmediate(finish, ...args) + }) + }) +}) + +function finish(t, tests, tx) { + const root = tx.trace.root + const segments = common.checkAWSAttributes(t, root, common.DATASTORE_PATTERN) + + t.equal(segments.length, tests.length, `should have ${tests.length} aws datastore segments`) + + const externalSegments = common.checkAWSAttributes(t, root, common.EXTERN_PATTERN) + t.equal(externalSegments.length, 0, 'should not have any External segments') + + segments.forEach((segment, i) => { + const operation = tests[i].operation + t.equal( + segment.name, + `Datastore/operation/DynamoDB/${operation}`, + 'should have operation in segment name' + ) + const attrs = segment.attributes.get(common.SEGMENT_DESTINATION) + attrs.port_path_or_id = parseInt(attrs.port_path_or_id, 10) + t.match( + attrs, + { + 'host': String, + 'port_path_or_id': Number, + 'product': 'DynamoDB', + 'collection': String, + 'aws.operation': operation, + 'aws.requestId': String, + 'aws.region': 'us-east-1', + 'aws.service': 'DynamoDB' + }, + 'should have expected attributes' + ) + }) + + t.end() +} + +function createTests(ddb, docClient, tableName) { + const ddbUniqueArtist = `DELETE_One You Know ${Math.floor(Math.random() * 100000)}` + const createTblParams = getCreateTableParams(tableName) + const putItemParams = getPutItemParams(tableName, ddbUniqueArtist) + const itemParams = getItemParams(tableName, ddbUniqueArtist) + const queryParams = getQueryParams(tableName, ddbUniqueArtist) + const deleteTableParams = getDeleteTableParams(tableName) + + const docUniqueArtist = `DELETE_One You Know ${Math.floor(Math.random() * 100000)}` + const docPutParams = getDocPutItemParams(tableName, docUniqueArtist) + const docItemParams = getDocItemParams(tableName, docUniqueArtist) + const docQueryParams = getDocQueryParams(tableName, docUniqueArtist) + + return [ + { api: ddb, method: 'createTable', params: createTblParams, operation: 'createTable' }, + { api: ddb, method: 'putItem', params: putItemParams, operation: 'putItem' }, + { api: ddb, method: 'getItem', params: itemParams, operation: 'getItem' }, + { api: ddb, method: 'updateItem', params: itemParams, operation: 'updateItem' }, + { api: ddb, method: 'scan', params: { TableName: tableName }, operation: 'scan' }, + { api: ddb, method: 'query', params: queryParams, operation: 'query' }, + { api: ddb, method: 'deleteItem', params: itemParams, operation: 'deleteItem' }, + + { api: docClient, method: 'put', params: docPutParams, operation: 'putItem' }, + { api: docClient, method: 'get', params: docItemParams, operation: 'getItem' }, + { api: docClient, method: 'update', params: docItemParams, operation: 'updateItem' }, + { api: docClient, method: 'scan', params: { TableName: tableName }, operation: 'scan' }, + { api: docClient, method: 'query', params: docQueryParams, operation: 'query' }, + { api: docClient, method: 'delete', params: docItemParams, operation: 'deleteItem' }, + + { api: ddb, method: 'deleteTable', params: deleteTableParams, operation: 'deleteTable' } + ] +} + +function getCreateTableParams(tableName) { + return { + AttributeDefinitions: [ + { AttributeName: 'Artist', AttributeType: 'S' }, + { AttributeName: 'SongTitle', AttributeType: 'S' } + ], + KeySchema: [ + { AttributeName: 'Artist', KeyType: 'HASH' }, + { AttributeName: 'SongTitle', KeyType: 'RANGE' } + ], + ProvisionedThroughput: { + ReadCapacityUnits: 5, + WriteCapacityUnits: 5 + }, + TableName: tableName + } +} + +function getPutItemParams(tableName, uniqueArtist) { + return { + Item: { + AlbumTitle: { S: 'Somewhat Famous' }, + Artist: { S: uniqueArtist }, + SongTitle: { S: 'Call Me Today' } + }, + TableName: tableName + } +} + +function getItemParams(tableName, uniqueArtist) { + return { + Key: { + Artist: { S: uniqueArtist }, + SongTitle: { S: 'Call Me Today' } + }, + TableName: tableName + } +} + +function getQueryParams(tableName, uniqueArtist) { + return { + ExpressionAttributeValues: { + ':v1': { S: uniqueArtist } + }, + KeyConditionExpression: 'Artist = :v1', + TableName: tableName + } +} + +function getDeleteTableParams(tableName) { + return { + TableName: tableName + } +} + +function getDocPutItemParams(tableName, uniqueArtist) { + return { + Item: { + AlbumTitle: 'Somewhat Famous', + Artist: uniqueArtist, + SongTitle: 'Call Me Today' + }, + TableName: tableName + } +} + +function getDocItemParams(tableName, uniqueArtist) { + return { + Key: { + Artist: uniqueArtist, + SongTitle: 'Call Me Today' + }, + TableName: tableName + } +} + +function getDocQueryParams(tableName, uniqueArtist) { + return { + ExpressionAttributeValues: { + ':v1': uniqueArtist + }, + KeyConditionExpression: 'Artist = :v1', + TableName: tableName + } +} diff --git a/test/versioned/aws-sdk-v2/http-services.tap.js b/test/versioned/aws-sdk-v2/http-services.tap.js new file mode 100644 index 0000000000..679e6b11b1 --- /dev/null +++ b/test/versioned/aws-sdk-v2/http-services.tap.js @@ -0,0 +1,257 @@ +/* + * Copyright 2020 New Relic Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +'use strict' + +const tap = require('tap') +const helper = require('../../lib/agent_helper') +const common = require('../aws-sdk-v3/common') +const { createEmptyResponseServer, FAKE_CREDENTIALS } = require('../../lib/aws-server-stubs') + +tap.test('AWS HTTP Services', (t) => { + t.autoend() + + t.beforeEach(async (t) => { + const server = createEmptyResponseServer() + + await new Promise((resolve) => { + server.listen(0, resolve) + }) + + t.context.server = server + + t.context.agent = helper.instrumentMockedAgent() + const AWS = require('aws-sdk') + AWS.config.update({ region: 'us-east-1' }) + + t.context.endpoint = `http://localhost:${server.address().port}` + t.context.AWS = AWS + }) + + t.afterEach((t) => { + t.context.server.close() + helper.unloadAgent(t.context.agent) + }) + + t.test('APIGateway', (t) => { + const { agent, endpoint, AWS } = t.context + helper.runInTransaction(agent, (tx) => { + const service = new AWS.APIGateway({ + credentials: FAKE_CREDENTIALS, + endpoint + }) + service.createApiKey( + { + customerId: 'STRING_VALUE', + description: 'STRING_VALUE', + enabled: true, + generateDistinctId: true, + name: 'STRING_VALUE', + stageKeys: [ + { + restApiId: 'STRING_VALUE', + stageName: 'STRING_VALUE' + } + ], + value: 'STRING_VALUE' + }, + () => { + tx.end() + setImmediate(finish, t, 'API Gateway', 'createApiKey', tx) + } + ) + }) + }) + + t.test('ELB', (t) => { + const { agent, endpoint, AWS } = t.context + helper.runInTransaction(agent, (tx) => { + const service = new AWS.ELB({ + credentials: FAKE_CREDENTIALS, + endpoint: endpoint + }) + service.addTags( + { + LoadBalancerNames: ['my-load-balancer'], + Tags: [ + { + Key: 'project', + Value: 'lima' + }, + { + Key: 'department', + Value: 'digital-media' + } + ] + }, + () => { + tx.end() + setImmediate(finish, t, 'Elastic Load Balancing', 'addTags', tx) + } + ) + }) + }) + + t.test('ElastiCache', (t) => { + const { agent, endpoint, AWS } = t.context + helper.runInTransaction(agent, (tx) => { + const service = new AWS.ElastiCache({ + credentials: FAKE_CREDENTIALS, + endpoint: endpoint + }) + service.addTagsToResource( + { + ResourceName: 'STRING_VALUE' /* required */, + Tags: [ + /* required */ + { + Key: 'STRING_VALUE', + Value: 'STRING_VALUE' + } + ] + }, + () => { + tx.end() + setImmediate(finish, t, 'ElastiCache', 'addTagsToResource', tx) + } + ) + }) + }) + + t.test('Lambda', (t) => { + const { agent, endpoint, AWS } = t.context + helper.runInTransaction(agent, (tx) => { + const service = new AWS.Lambda({ + credentials: FAKE_CREDENTIALS, + endpoint: endpoint + }) + service.addLayerVersionPermission( + { + Action: 'lambda:GetLayerVersion' /* required */, + LayerName: 'STRING_VALUE' /* required */, + Principal: '*' /* required */, + StatementId: 'STRING_VALUE' /* required */, + VersionNumber: 2 /* required */, + OrganizationId: 'o-0123456789', + RevisionId: 'STRING_VALUE' + }, + () => { + tx.end() + setImmediate(finish, t, 'Lambda', 'addLayerVersionPermission', tx) + } + ) + }) + }) + + t.test('RDS', (t) => { + const { agent, endpoint, AWS } = t.context + helper.runInTransaction(agent, (tx) => { + const service = new AWS.RDS({ + credentials: FAKE_CREDENTIALS, + endpoint: endpoint + }) + service.addRoleToDBCluster( + { + DBClusterIdentifier: 'STRING_VALUE' /* required */, + RoleArn: 'arn:aws:iam::123456789012:role/AuroraAccessRole' /* required */ + }, + () => { + tx.end() + setImmediate(finish, t, 'Amazon RDS', 'addRoleToDBCluster', tx) + } + ) + }) + }) + + t.test('Redshift', (t) => { + const { agent, endpoint, AWS } = t.context + helper.runInTransaction(agent, (tx) => { + const service = new AWS.Redshift({ + credentials: FAKE_CREDENTIALS, + endpoint: endpoint + }) + service.acceptReservedNodeExchange( + { + ReservedNodeId: 'STRING_VALUE' /* required */, + TargetReservedNodeOfferingId: 'STRING_VALUE' /* required */ + }, + () => { + tx.end() + setImmediate(finish, t, 'Redshift', 'acceptReservedNodeExchange', tx) + } + ) + }) + }) + + t.test('Rekognition', (t) => { + const { agent, endpoint, AWS } = t.context + helper.runInTransaction(agent, (tx) => { + const service = new AWS.Rekognition({ + credentials: FAKE_CREDENTIALS, + endpoint: endpoint + }) + service.compareFaces( + { + SimilarityThreshold: 90, + SourceImage: { + S3Object: { + Bucket: 'mybucket', + Name: 'mysourceimage' + } + }, + TargetImage: { + S3Object: { + Bucket: 'mybucket', + Name: 'mytargetimage' + } + } + }, + () => { + tx.end() + setImmediate(finish, t, 'Rekognition', 'compareFaces', tx) + } + ) + }) + }) + + t.test('SES', (t) => { + const { agent, endpoint, AWS } = t.context + helper.runInTransaction(agent, (tx) => { + const service = new AWS.SES({ + credentials: FAKE_CREDENTIALS, + endpoint: endpoint + }) + service.cloneReceiptRuleSet( + { + OriginalRuleSetName: 'RuleSetToClone', + RuleSetName: 'RuleSetToCreate' + }, + () => { + tx.end() + setImmediate(finish, t, 'Amazon SES', 'cloneReceiptRuleSet', tx) + } + ) + }) + }) +}) + +function finish(t, service, operation, tx) { + const externals = common.checkAWSAttributes(t, tx.trace.root, common.EXTERN_PATTERN) + if (t.equal(externals.length, 1, 'should have an aws external')) { + const attrs = externals[0].attributes.get(common.SEGMENT_DESTINATION) + t.match( + attrs, + { + 'aws.operation': operation, + 'aws.requestId': String, + 'aws.service': service, + 'aws.region': 'us-east-1' + }, + 'should have expected attributes' + ) + } + + t.end() +} diff --git a/test/versioned/aws-sdk-v2/instrumentation-supported.tap.js b/test/versioned/aws-sdk-v2/instrumentation-supported.tap.js new file mode 100644 index 0000000000..1e4b8aed36 --- /dev/null +++ b/test/versioned/aws-sdk-v2/instrumentation-supported.tap.js @@ -0,0 +1,42 @@ +/* + * Copyright 2020 New Relic Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +'use strict' + +const tap = require('tap') +const helper = require('../../lib/agent_helper') +const instrumentationHelper = require('../../../lib/instrumentation/aws-sdk/v2/instrumentation-helper') + +tap.test('instrumentation is supported', (t) => { + t.autoend() + + t.beforeEach((t) => { + t.context.agent = helper.instrumentMockedAgent() + t.context.AWS = require('aws-sdk') + }) + + t.afterEach((t) => { + helper.unloadAgent(t.context.agent) + }) + + t.test('AWS should be instrumented', (t) => { + const { AWS } = t.context + t.equal( + AWS.NodeHttpClient.prototype.handleRequest.name, + 'wrappedHandleRequest', + 'AWS has a wrapped NodeHttpClient' + ) + t.end() + }) + + t.test('instrumentation supported function', (t) => { + const { AWS } = t.context + t.ok( + instrumentationHelper.instrumentationSupported(AWS), + 'instrumentationSupported returned true' + ) + t.end() + }) +}) diff --git a/test/versioned/aws-sdk-v2/instrumentation-unsupported.tap.js b/test/versioned/aws-sdk-v2/instrumentation-unsupported.tap.js new file mode 100644 index 0000000000..1c2db1e73f --- /dev/null +++ b/test/versioned/aws-sdk-v2/instrumentation-unsupported.tap.js @@ -0,0 +1,42 @@ +/* + * Copyright 2020 New Relic Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +'use strict' + +const tap = require('tap') +const helper = require('../../lib/agent_helper') +const instrumentationHelper = require('../../../lib/instrumentation/aws-sdk/v2/instrumentation-helper') + +tap.test('instrumentation is not supported', (t) => { + t.autoend() + + t.beforeEach((t) => { + t.context.agent = helper.instrumentMockedAgent() + t.context.AWS = require('aws-sdk') + }) + + t.afterEach((t) => { + helper.unloadAgent(t.context.agent) + }) + + t.test('AWS should not be instrumented', (t) => { + const { AWS } = t.context + t.not( + AWS.NodeHttpClient.prototype.handleRequest.name, + 'wrappedHandleRequest', + 'AWS does not have a wrapped NodeHttpClient' + ) + t.end() + }) + + t.test('instrumentation supported function', (t) => { + const { AWS } = t.context + t.notOk( + instrumentationHelper.instrumentationSupported(AWS), + 'instrumentationSupported returned false' + ) + t.end() + }) +}) diff --git a/test/versioned/aws-sdk-v2/newrelic.js b/test/versioned/aws-sdk-v2/newrelic.js new file mode 100644 index 0000000000..5bfe53711f --- /dev/null +++ b/test/versioned/aws-sdk-v2/newrelic.js @@ -0,0 +1,25 @@ +/* + * Copyright 2020 New Relic Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +'use strict' + +exports.config = { + app_name: ['My Application'], + license_key: 'license key here', + logging: { + level: 'trace', + filepath: '../../../newrelic_agent.log' + }, + utilization: { + detect_aws: false, + detect_pcf: false, + detect_azure: false, + detect_gcp: false, + detect_docker: false + }, + transaction_tracer: { + enabled: true + } +} diff --git a/test/versioned/aws-sdk-v2/package.json b/test/versioned/aws-sdk-v2/package.json new file mode 100644 index 0000000000..55b54fa3cb --- /dev/null +++ b/test/versioned/aws-sdk-v2/package.json @@ -0,0 +1,59 @@ +{ + "name": "aws-sdk-v2-tests", + "version": "0.0.0", + "targets": [ + {"name":"aws-sdk","minAgentVersion": "6.2.0"} + ], + "private": true, + "tests": [ + { + "engines": { + "node": ">=16.0" + }, + "dependencies": { + "aws-sdk": { + "versions": "2.2.48" + } + }, + "files": [ + "instrumentation-unsupported.tap.js" + ] + }, + { + "engines": { + "node": ">=16.0" + }, + "dependencies": { + "aws-sdk": { + "versions": ">=2.463.0", + "samples": 10 + } + }, + "files": [ + "aws-sdk.tap.js", + "dynamodb.tap.js", + "http-services.tap.js", + "instrumentation-supported.tap.js", + "s3.tap.js", + "sns.tap.js", + "sqs.tap.js" + ] + }, + { + "engines": { + "node": ">=16.0" + }, + "dependencies": { + "aws-sdk": { + "versions": ">=2.463.0", + "samples": 10 + }, + "amazon-dax-client": ">=1.2.5" + }, + "files": [ + "amazon-dax-client.tap.js" + ] + } + ], + "dependencies": {} +} diff --git a/test/versioned/aws-sdk-v2/s3.tap.js b/test/versioned/aws-sdk-v2/s3.tap.js new file mode 100644 index 0000000000..420f3608d6 --- /dev/null +++ b/test/versioned/aws-sdk-v2/s3.tap.js @@ -0,0 +1,121 @@ +/* + * Copyright 2020 New Relic Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +'use strict' + +const tap = require('tap') +const helper = require('../../lib/agent_helper') +const common = require('../aws-sdk-v3/common') +const { createEmptyResponseServer, FAKE_CREDENTIALS } = require('../../lib/aws-server-stubs') + +tap.test('S3 buckets', (t) => { + t.autoend() + + t.beforeEach(async (t) => { + const server = createEmptyResponseServer() + + await new Promise((resolve) => { + server.listen(0, resolve) + }) + + t.context.server = server + + t.context.agent = helper.instrumentMockedAgent() + const AWS = require('aws-sdk') + t.context.S3 = new AWS.S3({ + credentials: FAKE_CREDENTIALS, + endpoint: `http://localhost:${server.address().port}`, + // allows using generic endpoint, instead of needing a + // bucket.endpoint server setup. + s3ForcePathStyle: true, + apiVersion: '2006-03-01' + }) + }) + + t.afterEach((t) => { + t.context.server.close() + helper.unloadAgent(t.context.agent) + }) + + t.test('commands with callbacks', (t) => { + const { agent, S3 } = t.context + const Bucket = 'delete-aws-sdk-test-bucket-' + Math.floor(Math.random() * 100000) + + helper.runInTransaction(agent, (tx) => { + S3.headBucket({ Bucket }, (err) => { + t.error(err) + + S3.createBucket({ Bucket }, (err) => { + t.error(err) + + S3.deleteBucket({ Bucket }, (err) => { + t.error(err) + tx.end() + + const args = [t, tx] + setImmediate(finish, ...args) + }) + }) + }) + }) + }) + + t.test('commands with promises', (t) => { + const { agent, S3 } = t.context + const Bucket = 'delete-aws-sdk-test-bucket-' + Math.floor(Math.random() * 100000) + + helper.runInTransaction(agent, async (tx) => { + try { + await S3.headBucket({ Bucket }).promise() + } catch (err) { + t.error(err) + } + + try { + // using pathstyle will result in the params being mutated due to this call, + // which is why the params are manually pasted in each call. + await S3.createBucket({ Bucket }).promise() + } catch (err) { + t.error(err) + } + + try { + await S3.deleteBucket({ Bucket }).promise() + } catch (err) { + t.error(err) + } + + tx.end() + + const args = [t, tx] + setImmediate(finish, ...args) + }) + }) +}) + +function finish(t, tx) { + const externals = common.checkAWSAttributes(t, tx.trace.root, common.EXTERN_PATTERN) + t.equal(externals.length, 3, 'should have 3 aws externals') + const [head, create, del] = externals + checkAttrs(t, head, 'headBucket') + checkAttrs(t, create, 'createBucket') + checkAttrs(t, del, 'deleteBucket') + + t.end() +} + +function checkAttrs(t, segment, operation) { + const attrs = segment.attributes.get(common.SEGMENT_DESTINATION) + t.match( + attrs, + { + 'aws.operation': operation, + 'aws.requestId': String, + 'aws.service': 'Amazon S3', + 'aws.region': 'us-east-1' + }, + `should have expected attributes for ${operation}` + ) +} diff --git a/test/versioned/aws-sdk-v2/sns.tap.js b/test/versioned/aws-sdk-v2/sns.tap.js new file mode 100644 index 0000000000..99d37ad834 --- /dev/null +++ b/test/versioned/aws-sdk-v2/sns.tap.js @@ -0,0 +1,96 @@ +/* + * Copyright 2020 New Relic Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +'use strict' + +const tap = require('tap') +const helper = require('../../lib/agent_helper') +const common = require('../aws-sdk-v3/common') +const { createEmptyResponseServer, FAKE_CREDENTIALS } = require('../../lib/aws-server-stubs') +const TopicArn = null + +tap.test('SNS', (t) => { + t.autoend() + + t.beforeEach(async (t) => { + const server = createEmptyResponseServer() + + await new Promise((resolve) => { + server.listen(0, resolve) + }) + + t.context.server = server + + t.context.agent = helper.instrumentMockedAgent() + const AWS = require('aws-sdk') + t.context.sns = new AWS.SNS({ + credentials: FAKE_CREDENTIALS, + endpoint: `http://localhost:${server.address().port}`, + region: 'us-east-1' + }) + }) + + t.afterEach((t) => { + t.context.server.close() + helper.unloadAgent(t.context.agent) + }) + + t.test('publish with callback', (t) => { + const { agent, sns } = t.context + helper.runInTransaction(agent, (tx) => { + const params = { TopicArn, Message: 'Hello!' } + + sns.publish(params, (err) => { + t.error(err) + tx.end() + + const args = [t, tx] + setImmediate(finish, ...args) + }) + }) + }) + + t.test('publish with promise', (t) => { + const { agent, sns } = t.context + helper.runInTransaction(agent, async (tx) => { + const params = { TopicArn, Message: 'Hello!' } + + try { + await sns.publish(params).promise() + } catch (error) { + t.error(error) + } + + tx.end() + + const args = [t, tx] + setImmediate(finish, ...args) + }) + }) +}) + +function finish(t, tx) { + const root = tx.trace.root + + const messages = common.checkAWSAttributes(t, root, common.SNS_PATTERN) + t.equal(messages.length, 1, 'should have 1 message broker segment') + + const externalSegments = common.checkAWSAttributes(t, root, common.EXTERN_PATTERN) + t.equal(externalSegments.length, 0, 'should not have any External segments') + + const attrs = messages[0].attributes.get(common.SEGMENT_DESTINATION) + t.match( + attrs, + { + 'aws.operation': 'publish', + 'aws.requestId': String, + 'aws.service': 'Amazon SNS', + 'aws.region': 'us-east-1' + }, + 'should have expected attributes for publish' + ) + + t.end() +} diff --git a/test/versioned/aws-sdk-v2/sqs.tap.js b/test/versioned/aws-sdk-v2/sqs.tap.js new file mode 100644 index 0000000000..2326aad760 --- /dev/null +++ b/test/versioned/aws-sdk-v2/sqs.tap.js @@ -0,0 +1,247 @@ +/* + * Copyright 2020 New Relic Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +'use strict' + +const tap = require('tap') +const helper = require('../../lib/agent_helper') +const common = require('../aws-sdk-v3/common') +const { createResponseServer, FAKE_CREDENTIALS } = require('../../lib/aws-server-stubs') +const AWS_REGION = 'us-east-1' + +tap.test('SQS API', (t) => { + t.autoend() + + let sendMessageRequestId = null + let sendMessageBatchRequestId = null + let receiveMessageRequestId = null + + t.beforeEach(async (t) => { + const server = createResponseServer() + + await new Promise((resolve) => { + server.listen(0, resolve) + }) + + t.context.server = server + t.context.agent = helper.instrumentMockedAgent() + const AWS = require('aws-sdk') + const endpoint = `http://localhost:${server.address().port}` + t.context.sqs = new AWS.SQS({ + credentials: FAKE_CREDENTIALS, + endpoint: endpoint, + apiVersion: '2012-11-05', + region: AWS_REGION + }) + + t.context.queueName = 'delete-aws-sdk-test-queue-' + Math.floor(Math.random() * 100000) + }) + + t.afterEach((t) => { + t.context.server.close() + helper.unloadAgent(t.context.agent) + }) + + t.test('commands with callback', (t) => { + const { agent, queueName, sqs } = t.context + const createParams = getCreateParams(queueName) + sqs.createQueue(createParams, function (createErr, createData) { + t.error(createErr) + + const queueUrl = createData.QueueUrl + + helper.runInTransaction(agent, (transaction) => { + const sendMessageParams = getSendMessageParams(queueUrl) + sqs.sendMessage(sendMessageParams, function sendMessageCb(sendErr, sendData) { + t.error(sendErr) + t.ok(sendData.MessageId) + + sendMessageRequestId = this.requestId + + const sendMessageBatchParams = getSendMessageBatchParams(queueUrl) + sqs.sendMessageBatch( + sendMessageBatchParams, + function sendBatchCb(sendBatchErr, sendBatchData) { + t.error(sendBatchErr) + t.ok(sendBatchData.Successful) + + sendMessageBatchRequestId = this.requestId + + const receiveMessageParams = getReceiveMessageParams(queueUrl) + sqs.receiveMessage( + receiveMessageParams, + function receiveMsgCb(receiveErr, receiveData) { + t.error(receiveErr) + t.ok(receiveData.Messages) + + receiveMessageRequestId = this.requestId + + transaction.end() + + const args = { t, transaction, queueName } + setImmediate(finish, args) + } + ) + } + ) + }) + }) + }) + }) + + t.test('commands with promises', (t) => { + const { agent, queueName, sqs } = t.context + const createParams = getCreateParams(queueName) + sqs.createQueue(createParams, function (createErr, createData) { + t.error(createErr) + + const queueUrl = createData.QueueUrl + + helper.runInTransaction(agent, async (transaction) => { + try { + const sendMessageParams = getSendMessageParams(queueUrl) + const sendData = await sqs.sendMessage(sendMessageParams).promise() + t.ok(sendData.MessageId) + + sendMessageRequestId = getRequestId(sendData) + } catch (error) { + t.error(error) + } + + try { + const sendMessageBatchParams = getSendMessageBatchParams(queueUrl) + const sendBatchData = await sqs.sendMessageBatch(sendMessageBatchParams).promise() + t.ok(sendBatchData.Successful) + + sendMessageBatchRequestId = getRequestId(sendBatchData) + } catch (error) { + t.error(error) + } + + try { + const receiveMessageParams = getReceiveMessageParams(queueUrl) + const receiveData = await sqs.receiveMessage(receiveMessageParams).promise() + t.ok(receiveData.Messages) + + receiveMessageRequestId = getRequestId(receiveData) + } catch (error) { + t.error(error) + } + + transaction.end() + + const args = { t, transaction, queueName } + setImmediate(finish, args) + }) + }) + }) + + function finish({ t, transaction, queueName }) { + const expectedSegmentCount = 3 + + const root = transaction.trace.root + const segments = common.checkAWSAttributes(t, root, common.SQS_PATTERN) + + t.equal( + segments.length, + expectedSegmentCount, + `should have ${expectedSegmentCount} AWS MessageBroker/SQS segments` + ) + + const externalSegments = common.checkAWSAttributes(t, root, common.EXTERN_PATTERN) + t.equal(externalSegments.length, 0, 'should not have any External segments') + + const [sendMessage, sendMessageBatch, receiveMessage] = segments + + checkName(t, sendMessage.name, 'Produce', queueName) + checkAttributes(t, sendMessage, 'sendMessage', sendMessageRequestId) + + checkName(t, sendMessageBatch.name, 'Produce', queueName) + checkAttributes(t, sendMessageBatch, 'sendMessageBatch', sendMessageBatchRequestId) + + checkName(t, receiveMessage.name, 'Consume', queueName) + checkAttributes(t, receiveMessage, 'receiveMessage', receiveMessageRequestId) + + t.end() + } +}) + +function checkName(t, name, action, queueName) { + const specificName = `/${action}/Named/${queueName}` + + t.match(name, specificName, 'should have correct name') +} + +function checkAttributes(t, segment, operation, expectedRequestId) { + const actualAttributes = segment.attributes.get(common.SEGMENT_DESTINATION) + + const expectedAttributes = { + 'aws.operation': operation, + 'aws.requestId': expectedRequestId, + 'aws.service': 'Amazon SQS', + 'aws.region': AWS_REGION + } + + t.match(actualAttributes, expectedAttributes, `should have expected attributes for ${operation}`) +} + +function getRequestId(data) { + return data?.$response?.requestId +} + +function getCreateParams(queueName) { + return { + QueueName: queueName, + Attributes: { + MessageRetentionPeriod: '1200' // 20 minutes + } + } +} + +function getSendMessageParams(queueUrl) { + return { + MessageAttributes: { + Attr1: { + DataType: 'String', + StringValue: 'One' + } + }, + MessageBody: 'This is a test message', + QueueUrl: queueUrl + } +} + +function getSendMessageBatchParams(queueUrl) { + return { + Entries: [ + { + Id: 'ONE', + MessageBody: 'ONE BODY', + MessageAttributes: { + Attribute1: { DataType: 'String', StringValue: 'Value 1' }, + Attribute2: { DataType: 'String', StringValue: 'Value 2' } + } + }, + { + Id: 'TWO', + MessageBody: 'TWO BODY', + MessageAttributes: { + Attribute1: { DataType: 'String', StringValue: 'Value 1' }, + Attribute2: { DataType: 'String', StringValue: 'Value 2' } + } + } + ], + QueueUrl: queueUrl + } +} + +function getReceiveMessageParams(queueUrl) { + return { + AttributeNames: ['SentTimestamp'], + MaxNumberOfMessages: 2, + MessageAttributeNames: ['All'], + QueueUrl: queueUrl + } +} diff --git a/test/versioned/aws-sdk-v3/api-gateway.tap.js b/test/versioned/aws-sdk-v3/api-gateway.tap.js new file mode 100644 index 0000000000..7910710156 --- /dev/null +++ b/test/versioned/aws-sdk-v3/api-gateway.tap.js @@ -0,0 +1,64 @@ +/* + * Copyright 2021 New Relic Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +'use strict' + +const tap = require('tap') +const helper = require('../../lib/agent_helper') +require('./common') +const { createEmptyResponseServer, FAKE_CREDENTIALS } = require('../../lib/aws-server-stubs') + +tap.test('APIGatewayClient', (t) => { + t.beforeEach(async (t) => { + const server = createEmptyResponseServer() + await new Promise((resolve) => { + server.listen(0, resolve) + }) + + t.context.server = server + t.context.agent = helper.instrumentMockedAgent() + const { APIGatewayClient, ...lib } = require('@aws-sdk/client-api-gateway') + t.context.CreateApiKeyCommand = lib.CreateApiKeyCommand + const endpoint = `http://localhost:${server.address().port}` + t.context.service = new APIGatewayClient({ + credentials: FAKE_CREDENTIALS, + endpoint, + region: 'us-east-1' + }) + }) + + t.afterEach((t) => { + t.context.server.destroy() + helper.unloadAgent(t.context.agent) + }) + + t.test('CreateApiKeyCommand', (t) => { + const { agent, service, CreateApiKeyCommand } = t.context + helper.runInTransaction(agent, async (tx) => { + const cmd = new CreateApiKeyCommand({ + customerId: 'STRING_VALUE', + description: 'STRING_VALUE', + enabled: true, + generateDistinctId: true, + name: 'STRING_VALUE', + stageKeys: [ + { + restApiId: 'STRING_VALUE', + stageName: 'STRING_VALUE' + } + ], + value: 'STRING_VALUE' + }) + await service.send(cmd) + tx.end() + setImmediate(t.checkExternals, { + service: 'API Gateway', + operations: ['CreateApiKeyCommand'], + tx + }) + }) + }) + t.end() +}) diff --git a/test/versioned/aws-sdk-v3/bedrock-chat-completions.tap.js b/test/versioned/aws-sdk-v3/bedrock-chat-completions.tap.js new file mode 100644 index 0000000000..517f8a5141 --- /dev/null +++ b/test/versioned/aws-sdk-v3/bedrock-chat-completions.tap.js @@ -0,0 +1,620 @@ +/* + * Copyright 2023 New Relic Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +'use strict' + +const tap = require('tap') +require('./common') +const helper = require('../../lib/agent_helper') +require('../../lib/metrics_helper') +const createAiResponseServer = require('../../lib/aws-server-stubs/ai-server') +const { FAKE_CREDENTIALS } = require('../../lib/aws-server-stubs') +const { version: pkgVersion } = require('@smithy/smithy-client/package.json') +const { DESTINATIONS } = require('../../../lib/config/attribute-filter') + +const requests = { + ai21: (prompt, modelId) => ({ + body: JSON.stringify({ prompt, temperature: 0.5, maxTokens: 100 }), + modelId + }), + amazon: (prompt, modelId) => ({ + body: JSON.stringify({ + inputText: prompt, + textGenerationConfig: { temperature: 0.5, maxTokenCount: 100 } + }), + modelId + }), + claude: (prompt, modelId) => ({ + body: JSON.stringify({ prompt, temperature: 0.5, max_tokens_to_sample: 100 }), + modelId + }), + cohere: (prompt, modelId) => ({ + body: JSON.stringify({ prompt, temperature: 0.5, max_tokens: 100 }), + modelId + }), + llama2: (prompt, modelId) => ({ + body: JSON.stringify({ prompt, max_gen_length: 100, temperature: 0.5 }), + modelId + }) +} + +tap.beforeEach(async (t) => { + t.context.agent = helper.instrumentMockedAgent({ + ai_monitoring: { + enabled: true + } + }) + const bedrock = require('@aws-sdk/client-bedrock-runtime') + t.context.bedrock = bedrock + + const { server, baseUrl, responses, host, port } = await createAiResponseServer() + t.context.server = server + t.context.baseUrl = baseUrl + t.context.responses = responses + t.context.expectedExternalPath = (modelId, method = 'invoke') => + `External/${host}:${port}/model/${modelId}/${method}` + + const client = new bedrock.BedrockRuntimeClient({ + region: 'us-east-1', + credentials: FAKE_CREDENTIALS, + endpoint: baseUrl, + maxAttempts: 1 + }) + t.context.client = client +}) + +tap.afterEach(async (t) => { + helper.unloadAgent(t.context.agent) + t.context.server.destroy() + Object.keys(require.cache).forEach((key) => { + if ( + key.includes('@smithy/smithy-client') || + key.includes('@aws-sdk/smithy-client') || + key.includes('@aws-sdk/client-bedrock-runtime') + ) { + delete require.cache[key] + } + }) +}) +;[ + { modelId: 'ai21.j2-ultra-v1', resKey: 'ai21' }, + { modelId: 'amazon.titan-text-express-v1', resKey: 'amazon' }, + { modelId: 'anthropic.claude-v2', resKey: 'claude' }, + { modelId: 'cohere.command-text-v14', resKey: 'cohere' }, + { modelId: 'meta.llama2-13b-chat-v1', resKey: 'llama2' } +].forEach(({ modelId, resKey }) => { + tap.test(`${modelId}: should properly create completion segment`, (t) => { + const { bedrock, client, responses, agent, expectedExternalPath } = t.context + const prompt = `text ${resKey} ultimate question` + const input = requests[resKey](prompt, modelId) + + const command = new bedrock.InvokeModelCommand(input) + + const expected = responses[resKey].get(prompt) + helper.runInTransaction(agent, async (tx) => { + const response = await client.send(command) + const body = JSON.parse(response.body.transformToString('utf8')) + t.equal(response.$metadata.requestId, expected.headers['x-amzn-requestid']) + t.same(body, expected.body) + t.assertSegments( + tx.trace.root, + ['Llm/completion/Bedrock/InvokeModelCommand', [expectedExternalPath(modelId)]], + { exact: false } + ) + tx.end() + t.end() + }) + }) + + tap.test( + `${modelId}: properly create the LlmChatCompletionMessage(s) and LlmChatCompletionSummary events`, + (t) => { + const { bedrock, client, agent } = t.context + const prompt = `text ${resKey} ultimate question` + const input = requests[resKey](prompt, modelId) + const command = new bedrock.InvokeModelCommand(input) + + const api = helper.getAgentApi() + helper.runInTransaction(agent, async (tx) => { + api.addCustomAttribute('llm.conversation_id', 'convo-id') + await client.send(command) + const events = agent.customEventAggregator.events.toArray() + t.equal(events.length, 3) + const chatSummary = events.filter(([{ type }]) => type === 'LlmChatCompletionSummary')[0] + const chatMsgs = events.filter(([{ type }]) => type === 'LlmChatCompletionMessage') + + t.llmMessages({ + modelId, + prompt, + resContent: '42', + tx, + expectedId: modelId.includes('ai21') || modelId.includes('cohere') ? '1234' : null, + chatMsgs + }) + + t.llmSummary({ tx, modelId, chatSummary }) + + tx.end() + t.end() + }) + } + ) + + tap.test(`${modelId}: text answer (streamed)`, (t) => { + if (modelId.includes('ai21')) { + t.skip('model does not support streaming') + t.end() + return + } + + const { bedrock, client, agent } = t.context + const prompt = `text ${resKey} ultimate question streamed` + const input = requests[resKey](prompt, modelId) + const command = new bedrock.InvokeModelWithResponseStreamCommand(input) + + const api = helper.getAgentApi() + helper.runInTransaction(agent, async (tx) => { + api.addCustomAttribute('llm.conversation_id', 'convo-id') + + const response = await client.send(command) + for await (const event of response.body) { + // no-op iteration over the stream in order to exercise the instrumentation + event + } + + const events = agent.customEventAggregator.events.toArray() + const chatSummary = events.filter(([{ type }]) => type === 'LlmChatCompletionSummary')[0] + const chatMsgs = events.filter(([{ type }]) => type === 'LlmChatCompletionMessage') + t.equal(events.length > 2, true) + + t.llmMessages({ + modelId, + prompt, + resContent: '42', + tx, + expectedId: modelId.includes('ai21') || modelId.includes('cohere') ? '1234' : null, + chatMsgs + }) + + t.llmSummary({ tx, modelId, chatSummary, numMsgs: events.length - 1 }) + + tx.end() + t.end() + }) + }) + + tap.test('should record feedback message accordingly', (t) => { + const { bedrock, client, agent } = t.context + const prompt = `text ${resKey} ultimate question` + const input = requests[resKey](prompt, modelId) + const command = new bedrock.InvokeModelCommand(input) + + const api = helper.getAgentApi() + helper.runInTransaction(agent, async (tx) => { + await client.send(command) + const { traceId } = api.getTraceMetadata() + api.recordLlmFeedbackEvent({ + traceId, + category: 'test-event', + rating: '5 star', + message: 'You are a mathematician.', + metadata: { foo: 'foo' } + }) + const recordedEvents = agent.customEventAggregator.getEvents() + const [[, feedback]] = recordedEvents.filter(([{ type }]) => type === 'LlmFeedbackMessage') + + t.match(feedback, { + id: /[\w\d]{32}/, + trace_id: traceId, + category: 'test-event', + rating: '5 star', + message: 'You are a mathematician.', + ingest_source: 'Node', + foo: 'foo' + }) + + tx.end() + t.end() + }) + }) + + tap.test(`${modelId}: should increment tracking metric for each chat completion event`, (t) => { + const { bedrock, client, agent } = t.context + const prompt = `text ${resKey} ultimate question` + const input = requests[resKey](prompt, modelId) + const command = new bedrock.InvokeModelCommand(input) + helper.runInTransaction(agent, async (tx) => { + await client.send(command) + const metrics = agent.metrics.getOrCreateMetric( + `Supportability/Nodejs/ML/Bedrock/${pkgVersion}` + ) + t.equal(metrics.callCount > 0, true) + tx.end() + t.end() + }) + }) + + tap.test(`${modelId}: should properly create errors on create completion`, (t) => { + const { bedrock, client, agent, expectedExternalPath } = t.context + const prompt = `text ${resKey} ultimate question error` + const input = requests[resKey](prompt, modelId) + + const command = new bedrock.InvokeModelCommand(input) + const expectedMsg = + 'Malformed input request: 2 schema violations found, please reformat your input and try again.' + const expectedType = 'ValidationException' + + const api = helper.getAgentApi() + helper.runInTransaction(agent, async (tx) => { + api.addCustomAttribute('llm.conversation_id', 'convo-id') + try { + await client.send(command) + } catch (err) { + t.equal(err.message, expectedMsg) + t.equal(err.name, expectedType) + } + + t.equal(tx.exceptions.length, 1) + t.match(tx.exceptions[0], { + error: { + name: expectedType, + message: expectedMsg + }, + customAttributes: { + 'http.statusCode': 400, + 'error.message': expectedMsg, + 'error.code': expectedType, + 'completion_id': /[\w]{8}-[\w]{4}-[\w]{4}-[\w]{4}-[\w]{12}/ + }, + agentAttributes: { + spanId: /[\w\d]+/ + } + }) + + t.assertSegments( + tx.trace.root, + ['Llm/completion/Bedrock/InvokeModelCommand', [expectedExternalPath(modelId)]], + { exact: false } + ) + + const events = agent.customEventAggregator.events.toArray() + t.equal(events.length, 2) + const chatSummary = events.filter(([{ type }]) => type === 'LlmChatCompletionSummary')[0] + const chatMsgs = events.filter(([{ type }]) => type === 'LlmChatCompletionMessage') + + t.llmMessages({ + modelId, + prompt, + tx, + chatMsgs + }) + + t.llmSummary({ tx, modelId, chatSummary, error: true }) + tx.end() + t.end() + }) + }) + + tap.test(`{${modelId}:}: should add llm attribute to transaction`, (t) => { + const { bedrock, client, agent } = t.context + const prompt = `text ${resKey} ultimate question` + const input = requests[resKey](prompt, modelId) + const command = new bedrock.InvokeModelCommand(input) + + helper.runInTransaction(agent, async (tx) => { + await client.send(command) + const attributes = tx.trace.attributes.get(DESTINATIONS.TRANS_EVENT) + t.equal(attributes.llm, true) + + tx.end() + t.end() + }) + }) + + tap.test(`${modelId}: should decorate messages with custom attrs`, (t) => { + const { bedrock, client, agent } = t.context + const prompt = `text ${resKey} ultimate question` + const input = requests[resKey](prompt, modelId) + const command = new bedrock.InvokeModelCommand(input) + + helper.runInTransaction(agent, async (tx) => { + const api = helper.getAgentApi() + api.addCustomAttribute('llm.foo', 'bar') + + await client.send(command) + + const events = tx.agent.customEventAggregator.events.toArray() + const summary = events + .filter((e) => e[0].type === 'LlmChatCompletionSummary') + .map((e) => e[1]) + .pop() + const completion = events + .filter((e) => e[0].type === 'LlmChatCompletionMessage') + .map((e) => e[1]) + .pop() + + t.equal(summary['llm.foo'], 'bar') + t.equal(completion['llm.foo'], 'bar') + + tx.end() + t.end() + }) + }) +}) + +tap.test(`cohere embedding streaming works`, (t) => { + const { bedrock, client, agent } = t.context + const prompt = `embed text cohere stream` + const input = { + body: JSON.stringify({ + texts: prompt.split(' '), + input_type: 'search_document' + }), + modelId: 'cohere.embed-english-v3' + } + const command = new bedrock.InvokeModelWithResponseStreamCommand(input) + + const api = helper.getAgentApi() + helper.runInTransaction(agent, async (tx) => { + api.addCustomAttribute('llm.conversation_id', 'convo-id') + + const response = await client.send(command) + for await (const event of response.body) { + // no-op iteration over the stream in order to exercise the instrumentation + event + } + + const events = agent.customEventAggregator.events.toArray() + t.equal(events.length, 1) + const embedding = events.shift()[1] + t.equal(embedding.error, false) + t.equal(embedding.input, prompt) + + tx.end() + t.end() + }) +}) + +tap.test(`ai21: should properly create errors on create completion (streamed)`, (t) => { + const { bedrock, client, agent, expectedExternalPath } = t.context + const modelId = 'ai21.j2-mid-v1' + const prompt = `text ai21 ultimate question error streamed` + const input = requests.ai21(prompt, modelId) + + const command = new bedrock.InvokeModelWithResponseStreamCommand(input) + const expectedMsg = 'The model is unsupported for streaming' + const expectedType = 'ValidationException' + + const api = helper.getAgentApi() + helper.runInTransaction(agent, async (tx) => { + api.addCustomAttribute('llm.conversation_id', 'convo-id') + try { + await client.send(command) + } catch (err) { + t.equal(err.message, expectedMsg) + t.equal(err.name, expectedType) + } + + t.equal(tx.exceptions.length, 1) + t.match(tx.exceptions[0], { + error: { + name: expectedType, + message: expectedMsg + }, + customAttributes: { + 'http.statusCode': 400, + 'error.message': expectedMsg, + 'error.code': expectedType, + 'completion_id': /[\w]{8}-[\w]{4}-[\w]{4}-[\w]{4}-[\w]{12}/ + }, + agentAttributes: { + spanId: /[\w\d]+/ + } + }) + + t.assertSegments( + tx.trace.root, + [ + 'Llm/completion/Bedrock/InvokeModelWithResponseStreamCommand', + [expectedExternalPath(modelId, 'invoke-with-response-stream')] + ], + { exact: false } + ) + + const events = agent.customEventAggregator.events.toArray() + t.equal(events.length, 2) + const chatSummary = events.filter(([{ type }]) => type === 'LlmChatCompletionSummary')[0] + const chatMsgs = events.filter(([{ type }]) => type === 'LlmChatCompletionMessage') + + t.llmMessages({ + modelId, + prompt, + tx, + chatMsgs + }) + + t.llmSummary({ tx, modelId, chatSummary, error: true }) + tx.end() + t.end() + }) +}) + +tap.test(`models that do not support streaming should be handled`, (t) => { + const { bedrock, client, agent, expectedExternalPath } = t.context + const modelId = 'amazon.titan-embed-text-v1' + const prompt = `embed text amazon error streamed` + const input = requests.amazon(prompt, modelId) + + const command = new bedrock.InvokeModelWithResponseStreamCommand(input) + const expectedMsg = 'The model is unsupported for streaming' + const expectedType = 'ValidationException' + + const api = helper.getAgentApi() + helper.runInTransaction(agent, async (tx) => { + api.addCustomAttribute('llm.conversation_id', 'convo-id') + try { + await client.send(command) + } catch (err) { + t.equal(err.message, expectedMsg) + t.equal(err.name, expectedType) + } + + t.equal(tx.exceptions.length, 1) + t.match(tx.exceptions[0], { + error: { + name: expectedType, + message: expectedMsg + }, + customAttributes: { + 'http.statusCode': 400, + 'error.message': expectedMsg, + 'error.code': expectedType, + 'completion_id': undefined + }, + agentAttributes: { + spanId: /[\w\d]+/ + } + }) + + t.assertSegments( + tx.trace.root, + [ + 'Llm/embedding/Bedrock/InvokeModelWithResponseStreamCommand', + [expectedExternalPath(modelId, 'invoke-with-response-stream')] + ], + { exact: false } + ) + + const events = agent.customEventAggregator.events.toArray() + t.equal(events.length, 1) + const embedding = events.shift()[1] + t.equal(embedding.error, true) + + tx.end() + t.end() + }) +}) + +tap.test(`models should properly create errors on stream interruption`, (t) => { + const { bedrock, client, agent } = t.context + const modelId = 'amazon.titan-text-express-v1' + const prompt = `text amazon bad stream` + const input = requests.amazon(prompt, modelId) + + const command = new bedrock.InvokeModelWithResponseStreamCommand(input) + helper.runInTransaction(agent, async (tx) => { + try { + await client.send(command) + } catch (error) { + t.match(error, { + code: 'ECONNRESET', + message: 'aborted', + $response: { + statusCode: 500 + } + }) + } + + const events = agent.customEventAggregator.events.toArray() + const summary = events.find((e) => e[0].type === 'LlmChatCompletionSummary')[1] + t.equal(tx.exceptions.length, 1) + t.equal(events.length, 2) + t.equal(summary.error, true) + + tx.end() + t.end() + }) +}) + +tap.test('should not instrument stream when disabled', (t) => { + const modelId = 'amazon.titan-text-express-v1' + const { bedrock, client, agent } = t.context + agent.config.ai_monitoring.streaming.enabled = false + const prompt = `text amazon ultimate question streamed` + const input = requests.amazon(prompt, modelId) + const command = new bedrock.InvokeModelWithResponseStreamCommand(input) + + helper.runInTransaction(agent, async (tx) => { + const response = await client.send(command) + let chunk = {} + let inputCount = null + let completion = '' + // build up the response to assert it does not get tainted when streaming is disabled + for await (const event of response.body) { + const obj = JSON.parse(new TextDecoder('utf-8').decode(event.chunk.bytes)) + chunk = { ...obj } + completion += obj.outputText + if (obj.inputTextTokenCount) { + inputCount = obj.inputTextTokenCount + } + } + chunk.inputTextTokenCount = inputCount + chunk.outputText = completion + t.same( + chunk, + { + 'outputText': '42', + 'index': 0, + 'totalOutputTextTokenCount': 75, + 'completionReason': 'endoftext', + 'inputTextTokenCount': 13, + 'amazon-bedrock-invocationMetrics': { + inputTokenCount: 8, + outputTokenCount: 4, + invocationLatency: 3879, + firstByteLatency: 3291 + } + }, + 'should not interfere with stream' + ) + + const events = agent.customEventAggregator.events.toArray() + t.equal(events.length, 0, 'should not create Llm events when streaming is disabled') + const attributes = tx.trace.attributes.get(DESTINATIONS.TRANS_EVENT) + t.equal(attributes.llm, true, 'should assign llm attribute to transaction trace') + const metrics = agent.metrics.getOrCreateMetric( + `Supportability/Nodejs/ML/Bedrock/${pkgVersion}` + ) + t.equal(metrics.callCount > 0, true, 'should set framework metric') + const supportabilityMetrics = agent.metrics.getOrCreateMetric( + `Supportability/Nodejs/ML/Streaming/Disabled` + ) + t.equal(supportabilityMetrics.callCount > 0, true, 'should increment streaming disabled metric') + + tx.end() + t.end() + }) +}) + +tap.test('should utilize tokenCountCallback when set', (t) => { + t.plan(5) + + const { bedrock, client, agent } = t.context + const prompt = 'text amazon user token count callback response' + const input = requests.amazon(prompt, 'amazon.titan-text-express-v1') + + agent.config.ai_monitoring.record_content.enabled = false + agent.llm.tokenCountCallback = function (model, content) { + t.equal(model, 'amazon.titan-text-express-v1') + t.equal([prompt, '42'].includes(content), true) + return content?.split(' ')?.length + } + const command = new bedrock.InvokeModelCommand(input) + + helper.runInTransaction(agent, async (tx) => { + await client.send(command) + + // Chat completion messages should have the correct `token_count` value. + const events = agent.customEventAggregator.events.toArray() + const completions = events.filter((e) => e[0].type === 'LlmChatCompletionMessage') + t.equal( + completions.some((e) => e[1].token_count === 7), + true + ) + + tx.end() + t.end() + }) +}) diff --git a/test/versioned/aws-sdk-v3/bedrock-embeddings.tap.js b/test/versioned/aws-sdk-v3/bedrock-embeddings.tap.js new file mode 100644 index 0000000000..5290b67f4d --- /dev/null +++ b/test/versioned/aws-sdk-v3/bedrock-embeddings.tap.js @@ -0,0 +1,266 @@ +/* + * Copyright 2023 New Relic Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +'use strict' + +const tap = require('tap') +require('./common') +const helper = require('../../lib/agent_helper') +require('../../lib/metrics_helper') +const createAiResponseServer = require('../../lib/aws-server-stubs/ai-server') +const { FAKE_CREDENTIALS } = require('../../lib/aws-server-stubs') +const { DESTINATIONS } = require('../../../lib/config/attribute-filter') +const requests = { + amazon: (prompt, modelId) => ({ + body: JSON.stringify({ inputText: prompt }), + modelId + }), + cohere: (prompt, modelId) => ({ + body: JSON.stringify({ input_type: 'search_document', texts: prompt.split(' ') }), + modelId + }) +} + +tap.beforeEach(async (t) => { + t.context.agent = helper.instrumentMockedAgent({ + ai_monitoring: { + enabled: true + } + }) + + const bedrock = require('@aws-sdk/client-bedrock-runtime') + t.context.bedrock = bedrock + + const { server, baseUrl, responses, host, port } = await createAiResponseServer() + t.context.server = server + t.context.baseUrl = baseUrl + t.context.responses = responses + t.context.expectedExternalPath = (modelId) => `External/${host}:${port}/model/${modelId}/invoke` + + const client = new bedrock.BedrockRuntimeClient({ + region: 'us-east-1', + credentials: FAKE_CREDENTIALS, + endpoint: baseUrl + }) + t.context.client = client +}) + +tap.afterEach(async (t) => { + helper.unloadAgent(t.context.agent) + t.context.server.destroy() + Object.keys(require.cache).forEach((key) => { + if ( + key.includes('@smithy/smithy-client') || + key.includes('@aws-sdk/smithy-client') || + key.includes('@aws-sdk/client-bedrock-runtime') + ) { + delete require.cache[key] + } + }) +}) +;[ + { modelId: 'amazon.titan-embed-text-v1', resKey: 'amazon' }, + { modelId: 'cohere.embed-english-v3', resKey: 'cohere' } +].forEach(({ modelId, resKey }) => { + tap.test(`${modelId}: should properly create embedding segment`, (t) => { + const { bedrock, client, responses, agent, expectedExternalPath } = t.context + const prompt = `text ${resKey} ultimate question` + const input = requests[resKey](prompt, modelId) + + const command = new bedrock.InvokeModelCommand(input) + + const expected = responses[resKey].get(prompt) + helper.runInTransaction(agent, async (tx) => { + const response = await client.send(command) + const body = JSON.parse(response.body.transformToString('utf8')) + t.equal(response.$metadata.requestId, expected.headers['x-amzn-requestid']) + t.same(body, expected.body) + t.assertSegments( + tx.trace.root, + ['Llm/embedding/Bedrock/InvokeModelCommand', [expectedExternalPath(modelId)]], + { exact: false } + ) + tx.end() + t.end() + }) + }) + + tap.test(`${modelId}: should properly create the LlmEmbedding event`, (t) => { + const { bedrock, client, agent } = t.context + const prompt = `embed text ${resKey} success` + const input = requests[resKey](prompt, modelId) + const command = new bedrock.InvokeModelCommand(input) + + helper.runInTransaction(agent, async (tx) => { + await client.send(command) + const events = agent.customEventAggregator.events.toArray() + t.equal(events.length, 1) + const embedding = events.filter(([{ type }]) => type === 'LlmEmbedding')[0] + const expectedEmbedding = { + 'id': /[\w]{8}-[\w]{4}-[\w]{4}-[\w]{4}-[\w]{12}/, + 'appName': 'New Relic for Node.js tests', + 'request_id': '743dd35b-744b-4ddf-b5c6-c0f3de2e3142', + 'trace_id': tx.traceId, + 'span_id': tx.trace.root.children[0].id, + 'response.model': modelId, + 'vendor': 'bedrock', + 'ingest_source': 'Node', + 'request.model': modelId, + 'duration': tx.trace.root.children[0].getDurationInMillis(), + 'input': prompt, + 'error': false + } + + t.equal(embedding[0].type, 'LlmEmbedding') + t.match(embedding[1], expectedEmbedding, 'should match embedding message') + + tx.end() + t.end() + }) + }) + + tap.test(`${modelId}: text answer (streamed)`, async (t) => { + const { bedrock, client, responses } = t.context + const prompt = `text ${resKey} ultimate question streamed` + const input = requests[resKey](prompt, modelId) + const command = new bedrock.InvokeModelWithResponseStreamCommand(input) + + const expected = responses[resKey].get(prompt) + try { + await client.send(command) + } catch (error) { + t.equal(error.message, expected.body.message) + } + }) + + tap.test(`${modelId}: should properly create errors on embeddings`, (t) => { + const { bedrock, client, agent, expectedExternalPath } = t.context + const prompt = `embed text ${resKey} error` + const input = requests[resKey](prompt, modelId) + const command = new bedrock.InvokeModelCommand(input) + const expectedMsg = + 'Malformed input request: 2 schema violations found, please reformat your input and try again.' + const expectedType = 'ValidationException' + + helper.runInTransaction(agent, async (tx) => { + try { + await client.send(command) + } catch (err) { + t.equal(err.message, expectedMsg) + t.equal(err.name, expectedType) + } + t.equal(tx.exceptions.length, 1) + t.match(tx.exceptions[0], { + error: { + name: expectedType, + message: expectedMsg + }, + customAttributes: { + 'http.statusCode': 400, + 'error.message': expectedMsg, + 'error.code': expectedType, + 'embedding_id': /[\w]{8}-[\w]{4}-[\w]{4}-[\w]{4}-[\w]{12}/ + }, + agentAttributes: { + spanId: /[\w\d]+/ + } + }) + + t.assertSegments( + tx.trace.root, + ['Llm/embedding/Bedrock/InvokeModelCommand', [expectedExternalPath(modelId)]], + { exact: false } + ) + const events = agent.customEventAggregator.events.toArray() + t.equal(events.length, 1) + const embedding = events.filter(([{ type }]) => type === 'LlmEmbedding')[0] + const expectedEmbedding = { + 'id': /[\w]{8}-[\w]{4}-[\w]{4}-[\w]{4}-[\w]{12}/, + 'appName': 'New Relic for Node.js tests', + 'request_id': '743dd35b-744b-4ddf-b5c6-c0f3de2e3142', + 'trace_id': tx.traceId, + 'span_id': tx.trace.root.children[0].id, + 'response.model': modelId, + 'vendor': 'bedrock', + 'ingest_source': 'Node', + 'request.model': modelId, + 'duration': tx.trace.root.children[0].getDurationInMillis(), + 'input': prompt, + 'error': true + } + + t.equal(embedding[0].type, 'LlmEmbedding') + t.match(embedding[1], expectedEmbedding, 'should match embedding message') + + tx.end() + t.end() + }) + }) + + tap.test(`${modelId}: should add llm attribute to transaction`, (t) => { + const { bedrock, client, agent } = t.context + const prompt = `embed text ${resKey} success` + const input = requests[resKey](prompt, modelId) + const command = new bedrock.InvokeModelCommand(input) + + helper.runInTransaction(agent, async (tx) => { + await client.send(command) + const attributes = tx.trace.attributes.get(DESTINATIONS.TRANS_EVENT) + t.equal(attributes.llm, true) + + tx.end() + t.end() + }) + }) + + tap.test(`${modelId}: should decorate messages with custom attrs`, (t) => { + const { bedrock, client, agent } = t.context + const prompt = `embed text ${resKey} success` + const input = requests[resKey](prompt, modelId) + const command = new bedrock.InvokeModelCommand(input) + + helper.runInTransaction(agent, async (tx) => { + const api = helper.getAgentApi() + api.addCustomAttribute('llm.foo', 'bar') + + await client.send(command) + const events = tx.agent.customEventAggregator.events.toArray() + const msg = events[0][1] + t.equal(msg['llm.foo'], 'bar') + + tx.end() + t.end() + }) + }) +}) + +tap.test('should utilize tokenCountCallback when set', (t) => { + t.plan(3) + + const { bedrock, client, agent } = t.context + const prompt = 'embed text amazon token count callback response' + const modelId = 'amazon.titan-embed-text-v1' + const input = requests.amazon(prompt, modelId) + + agent.config.ai_monitoring.record_content.enabled = false + agent.llm.tokenCountCallback = function (model, content) { + t.equal(model, modelId) + t.equal(content, prompt) + return content?.split(' ')?.length + } + const command = new bedrock.InvokeModelCommand(input) + + helper.runInTransaction(agent, async (tx) => { + await client.send(command) + + const events = agent.customEventAggregator.events.toArray() + const embeddings = events.filter((e) => e[0].type === 'LlmEmbedding') + const msg = embeddings[0][1] + t.equal(msg.token_count, 7) + + tx.end() + t.end() + }) +}) diff --git a/test/versioned/aws-sdk-v3/bedrock-negative-tests.tap.js b/test/versioned/aws-sdk-v3/bedrock-negative-tests.tap.js new file mode 100644 index 0000000000..cdf467bd3a --- /dev/null +++ b/test/versioned/aws-sdk-v3/bedrock-negative-tests.tap.js @@ -0,0 +1,76 @@ +/* + * Copyright 2023 New Relic Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +'use strict' + +const tap = require('tap') +require('./common') +const helper = require('../../lib/agent_helper') +require('../../lib/metrics_helper') +const createAiResponseServer = require('../../lib/aws-server-stubs/ai-server') +const { FAKE_CREDENTIALS } = require('../../lib/aws-server-stubs') +const sinon = require('sinon') + +tap.beforeEach(async (t) => { + t.context.agent = helper.instrumentMockedAgent() + const bedrock = require('@aws-sdk/client-bedrock-runtime') + t.context.bedrock = bedrock + + const { server, baseUrl, responses, host, port } = await createAiResponseServer() + t.context.server = server + t.context.baseUrl = baseUrl + t.context.responses = responses + t.context.expectedExternalPath = (modelId) => `External/${host}:${port}/model/${modelId}/invoke` + + const client = new bedrock.BedrockRuntimeClient({ + region: 'us-east-1', + credentials: FAKE_CREDENTIALS, + endpoint: baseUrl + }) + sinon.spy(client.middlewareStack, 'add') + t.context.client = client +}) + +tap.afterEach(async (t) => { + helper.unloadAgent(t.context.agent) + t.context.server.destroy() + Object.keys(require.cache).forEach((key) => { + if ( + key.includes('@smithy/smithy-client') || + key.includes('@aws-sdk/smithy-client') || + key.includes('@aws-sdk/client-bedrock-runtime') + ) { + delete require.cache[key] + } + }) +}) + +tap.test( + 'should not register instrumentation middleware when ai_monitoring is not enabled', + (t) => { + const { bedrock, client, responses, agent } = t.context + const resKey = 'amazon' + const modelId = 'amazon.titan-text-express-v1' + agent.config.ai_monitoring.enabled = false + const prompt = `text ${resKey} ultimate question` + const input = { + body: JSON.stringify({ inputText: prompt }), + modelId + } + + const command = new bedrock.InvokeModelCommand(input) + + const expected = responses[resKey].get(prompt) + helper.runInTransaction(agent, async (tx) => { + const response = await client.send(command) + t.equal(response.$metadata.requestId, expected.headers['x-amzn-requestid']) + t.equal(client.middlewareStack.add.callCount, 2) + const fns = client.middlewareStack.add.args.map(([mw]) => mw.name) + t.not(fns.includes('bound bedrockMiddleware')) + tx.end() + t.end() + }) + } +) diff --git a/test/versioned/aws-sdk-v3/client-dynamodb.tap.js b/test/versioned/aws-sdk-v3/client-dynamodb.tap.js new file mode 100644 index 0000000000..c3f2647616 --- /dev/null +++ b/test/versioned/aws-sdk-v3/client-dynamodb.tap.js @@ -0,0 +1,319 @@ +/* + * Copyright 2021 New Relic Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +'use strict' + +const tap = require('tap') +const helper = require('../../lib/agent_helper') +const common = require('./common') +const { createEmptyResponseServer, FAKE_CREDENTIALS } = require('../../lib/aws-server-stubs') +const sinon = require('sinon') + +const AWS_REGION = 'us-east-1' + +tap.test('DynamoDB', (t) => { + t.beforeEach(async (t) => { + const server = createEmptyResponseServer() + + await new Promise((resolve) => { + server.listen(0, resolve) + }) + + t.context.server = server + t.context.agent = helper.instrumentMockedAgent() + const Shim = require('../../../lib/shim/datastore-shim') + t.context.setDatastoreSpy = sinon.spy(Shim.prototype, 'setDatastore') + const lib = require('@aws-sdk/client-dynamodb') + t.context.lib = lib + const DynamoDBClient = lib.DynamoDBClient + t.context.DynamoDBClient = DynamoDBClient + t.context.client = new DynamoDBClient({ + credentials: FAKE_CREDENTIALS, + endpoint: `http://localhost:${server.address().port}`, + region: AWS_REGION + }) + + const tableName = `delete-aws-sdk-test-table-${Math.floor(Math.random() * 100000)}` + t.context.tableName = tableName + t.context.commands = createCommands({ lib, tableName }) + }) + + t.afterEach(async (t) => { + t.context.setDatastoreSpy.restore() + t.context.server.destroy() + helper.unloadAgent(t.context.agent) + Object.keys(require.cache).forEach((key) => { + if ( + key.includes('@aws-sdk/client-dynamodb') || + key.includes('@aws-sdk/smithy-client') || + key.includes('@smithy/smithy-client') + ) { + delete require.cache[key] + } + }) + }) + + // See: https://github.com/newrelic/node-newrelic-aws-sdk/issues/160 + // I do not care if this fails. the test is to make sure the instrumentation + // does not crash + t.test('real endpoint test', async (t) => { + const { + DynamoDBClient, + lib: { QueryCommand }, + tableName + } = t.context + const realClient = new DynamoDBClient({ + credentials: FAKE_CREDENTIALS, + region: AWS_REGION + }) + + const cmd = new QueryCommand(getQueryParams(tableName, 'randomtest')) + try { + await realClient.send(cmd) + throw new Error('this should fail with IncompleteSignatureException') + } catch (err) { + t.equal(err.name, 'IncompleteSignatureException') + } + }) + + t.test('commands, promise-style', (t) => { + const { agent, commands, client } = t.context + helper.runInTransaction(agent, async (tx) => { + for (const command of commands) { + t.comment(`Testing ${command.constructor.name}`) + try { + await client.send(command) + } catch (err) { + t.error(err) + } + } + tx.end() + finish(t, commands, tx) + }) + }) + + t.test('commands, callback-style', (t) => { + const { agent, commands, client } = t.context + helper.runInTransaction(agent, async (tx) => { + for (const command of commands) { + t.comment(`Testing ${command.constructor.name}`) + + await new Promise((resolve) => { + client.send(command, (err) => { + t.error(err) + + return setImmediate(resolve) + }) + }) + } + + tx.end() + finish(t, commands, tx) + }) + }) + t.end() + + function createCommands({ lib, tableName }) { + const { + CreateTableCommand, + PutItemCommand, + GetItemCommand, + UpdateItemCommand, + ScanCommand, + QueryCommand, + DeleteItemCommand, + BatchWriteItemCommand, + BatchGetItemCommand, + BatchExecuteStatementCommand, + UpdateTableCommand, + DeleteTableCommand + } = lib + const ddbUniqueArtist = `DELETE_One You Know ${Math.floor(Math.random() * 100000)}` + const createTblParams = getCreateTableParams(tableName) + const putItemParams = getPutItemParams(tableName, ddbUniqueArtist) + const itemParams = getItemParams(tableName, ddbUniqueArtist) + const queryParams = getQueryParams(tableName, ddbUniqueArtist) + const batchWriteItemCommandParams = getBatchWriteItemCommandParams(tableName, ddbUniqueArtist) + const batchGetItemCommandParams = getBatchGetItemCommandParams(tableName, ddbUniqueArtist) + const batchExecuteStatementCommandParams = getBatchExecuteStatementCommandParams( + tableName, + ddbUniqueArtist + ) + const updateTableCommandParams = getUpdateTableCommandParams(tableName) + const deleteTableParams = getDeleteTableParams(tableName) + const createTableCommand = new CreateTableCommand(createTblParams) + const putItemCommand = new PutItemCommand(putItemParams) + const getItemCommand = new GetItemCommand(itemParams) + const updateItemCommand = new UpdateItemCommand(itemParams) + const scanCommand = new ScanCommand({ TableName: tableName }) + const queryCommand = new QueryCommand(queryParams) + const deleteItemCommand = new DeleteItemCommand(itemParams) + const batchWriteItemCommand = new BatchWriteItemCommand(batchWriteItemCommandParams) + const batchGetItemCommand = new BatchGetItemCommand(batchGetItemCommandParams) + const batchExecuteStatementCommand = new BatchExecuteStatementCommand( + batchExecuteStatementCommandParams + ) + const updateTableCommand = new UpdateTableCommand(updateTableCommandParams) + const deleteTableCommand = new DeleteTableCommand(deleteTableParams) + return [ + createTableCommand, + putItemCommand, + getItemCommand, + updateItemCommand, + scanCommand, + queryCommand, + deleteItemCommand, + batchWriteItemCommand, + batchGetItemCommand, + batchExecuteStatementCommand, + updateTableCommand, + deleteTableCommand + ] + } + + function finish(t, cmds, tx) { + const root = tx.trace.root + const segments = common.checkAWSAttributes(t, root, common.DATASTORE_PATTERN) + + t.equal(segments.length, cmds.length, `should have ${cmds.length} AWS datastore segments`) + + const externalSegments = common.checkAWSAttributes(t, root, common.EXTERN_PATTERN) + t.equal(externalSegments.length, 0, 'should not have any External segments') + + segments.forEach((segment, i) => { + const command = cmds[i] + t.ok(command) + t.equal( + segment.name, + `Datastore/operation/DynamoDB/${command.constructor.name}`, + 'should have operation in segment name' + ) + const attrs = segment.attributes.get(common.SEGMENT_DESTINATION) + attrs.port_path_or_id = parseInt(attrs.port_path_or_id, 10) + + t.match( + attrs, + { + 'host': String, + 'port_path_or_id': Number, + 'product': 'DynamoDB', + 'collection': String, + 'aws.operation': command.constructor.name, + 'aws.requestId': String, + 'aws.region': 'us-east-1', + 'aws.service': /dynamodb|DynamoDB/ + }, + 'should have expected attributes' + ) + }) + + t.equal( + t.context.setDatastoreSpy.callCount, + 1, + 'should only call setDatastore once and not per call' + ) + t.end() + } +}) + +function getCreateTableParams(tableName) { + return { + AttributeDefinitions: [ + { AttributeName: 'Artist', AttributeType: 'S' }, + { AttributeName: 'SongTitle', AttributeType: 'S' } + ], + KeySchema: [ + { AttributeName: 'Artist', KeyType: 'HASH' }, + { AttributeName: 'SongTitle', KeyType: 'RANGE' } + ], + ProvisionedThroughput: { + ReadCapacityUnits: 5, + WriteCapacityUnits: 5 + }, + TableName: tableName + } +} + +function getPutItemParams(tableName, uniqueArtist) { + return { + Item: { + AlbumTitle: { S: 'Somewhat Famous' }, + Artist: { S: uniqueArtist }, + SongTitle: { S: 'Call Me Today' } + }, + TableName: tableName + } +} + +function getItemParams(tableName, uniqueArtist) { + return { + Key: { + Artist: { S: uniqueArtist }, + SongTitle: { S: 'Call Me Today' } + }, + TableName: tableName + } +} + +function getQueryParams(tableName, uniqueArtist) { + return { + ExpressionAttributeValues: { + ':v1': { S: uniqueArtist } + }, + KeyConditionExpression: 'Artist = :v1', + TableName: tableName + } +} + +function getDeleteTableParams(tableName) { + return { + TableName: tableName + } +} + +function getBatchWriteItemCommandParams(tableName, uniqueArtist) { + const params = {} + params[tableName] = { + RequestItems: [ + { + PutRequest: { + Key: { + AlbumTitle: { S: 'Deltron 3030' }, + Artist: { S: uniqueArtist }, + SongTitle: { S: 'Virus' } + } + } + } + ] + } + return params +} + +function getBatchGetItemCommandParams(tableName, uniqueArtist) { + const params = {} + params[tableName] = { + RequestItems: { + ConsistentRead: true, + Keys: { + Artist: { S: uniqueArtist } + } + } + } + return params +} + +function getBatchExecuteStatementCommandParams(tableName, uniqueArtist) { + const Statement = `SELECT * FROM ${tableName} x WHERE x.Artist = ${uniqueArtist}` + return { + Statements: [{ Statement }] + } +} + +function getUpdateTableCommandParams(tableName) { + return { + AttributeDefinitions: [{ AttributeName: 'AlbumTitle', AttributeType: 'S' }], + TableName: tableName + } +} diff --git a/test/versioned/aws-sdk-v3/common.js b/test/versioned/aws-sdk-v3/common.js new file mode 100644 index 0000000000..033b1b9932 --- /dev/null +++ b/test/versioned/aws-sdk-v3/common.js @@ -0,0 +1,150 @@ +/* + * Copyright 2020 New Relic Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +'use strict' + +const DATASTORE_PATTERN = /^Datastore/ +const EXTERN_PATTERN = /^External\/.*/ +const SNS_PATTERN = /^MessageBroker\/SNS\/Topic/ +const SQS_PATTERN = /^MessageBroker\/SQS\/Queue/ +const { + DESTINATIONS: { TRANS_SEGMENT } +} = require('../../../lib/config/attribute-filter') +const tap = require('tap') +const SEGMENT_DESTINATION = TRANS_SEGMENT + +tap.Test.prototype.addAssert('checkExternals', 1, checkExternals) +tap.Test.prototype.addAssert('llmMessages', 1, assertChatCompletionMessages) +tap.Test.prototype.addAssert('llmSummary', 1, assertChatCompletionSummary) + +// TODO: migrate to tap assertion, issue is variable number of args +// which doesn't seem to play nice with addAssert in tap +function checkAWSAttributes(t, segment, pattern, markedSegments = []) { + const expectedAttrs = { + 'aws.operation': String, + 'aws.service': String, + 'aws.requestId': String, + 'aws.region': String + } + + if (pattern.test(segment.name)) { + markedSegments.push(segment) + const attrs = segment.attributes.get(TRANS_SEGMENT) + t.match(attrs, expectedAttrs, 'should have aws attributes') + } + segment.children.forEach((child) => { + checkAWSAttributes(t, child, pattern, markedSegments) + }) + + return markedSegments +} + +function getMatchingSegments(t, segment, pattern, markedSegments = []) { + if (pattern.test(segment.name)) { + markedSegments.push(segment) + } + + segment.children.forEach((child) => { + getMatchingSegments(t, child, pattern, markedSegments) + }) + + return markedSegments +} + +function checkExternals({ service, operations, tx }) { + const externals = checkAWSAttributes(this, tx.trace.root, EXTERN_PATTERN) + this.equal(externals.length, operations.length, `should have ${operations.length} aws externals`) + operations.forEach((operation, index) => { + const attrs = externals[index].attributes.get(TRANS_SEGMENT) + this.match( + attrs, + { + 'aws.operation': operation, + 'aws.requestId': String, + // in 3.1.0 they fixed service names from lower case + // see: https://github.com/aws/aws-sdk-js-v3/commit/0011af27a62d0d201296225e2a70276645b3231a + 'aws.service': new RegExp(`${service}|${service.toLowerCase().replace(/ /g, '')}`), + 'aws.region': 'us-east-1' + }, + 'should have expected attributes' + ) + }) + this.end() +} + +function assertChatCompletionMessages({ tx, chatMsgs, expectedId, modelId, prompt, resContent }) { + const baseMsg = { + 'appName': 'New Relic for Node.js tests', + 'request_id': 'eda0760a-c3f0-4fc1-9a1e-75559d642866', + 'trace_id': tx.traceId, + 'span_id': tx.trace.root.children[0].id, + 'response.model': modelId, + 'vendor': 'bedrock', + 'ingest_source': 'Node', + 'role': 'user', + 'is_response': false, + 'completion_id': /[\w]{8}-[\w]{4}-[\w]{4}-[\w]{4}-[\w]{12}/ + } + + chatMsgs.forEach((msg) => { + if (msg[1].sequence > 1) { + // Streamed responses may have more than two messages. + // We only care about the start and end of the conversation. + return + } + + const expectedChatMsg = { ...baseMsg } + const id = expectedId ? `${expectedId}-${msg[1].sequence}` : msg[1].id + if (msg[1].sequence === 0) { + expectedChatMsg.sequence = 0 + expectedChatMsg.id = id + expectedChatMsg.content = prompt + } else if (msg[1].sequence === 1) { + expectedChatMsg.sequence = 1 + expectedChatMsg.role = 'assistant' + expectedChatMsg.id = id + expectedChatMsg.content = resContent + expectedChatMsg.is_response = true + } + + this.equal(msg[0].type, 'LlmChatCompletionMessage') + this.match(msg[1], expectedChatMsg, 'should match chat completion message') + }) +} + +function assertChatCompletionSummary({ tx, modelId, chatSummary, error = false, numMsgs = 2 }) { + const expectedChatSummary = { + 'id': /[\w]{8}-[\w]{4}-[\w]{4}-[\w]{4}-[\w]{12}/, + 'appName': 'New Relic for Node.js tests', + 'request_id': 'eda0760a-c3f0-4fc1-9a1e-75559d642866', + 'llm.conversation_id': 'convo-id', + 'trace_id': tx.traceId, + 'span_id': tx.trace.root.children[0].id, + 'response.model': modelId, + 'vendor': 'bedrock', + 'ingest_source': 'Node', + 'request.model': modelId, + 'duration': tx.trace.root.children[0].getDurationInMillis(), + 'response.number_of_messages': error ? 1 : numMsgs, + 'response.choices.finish_reason': error ? undefined : 'endoftext', + 'request.temperature': 0.5, + 'request.max_tokens': 100, + 'error': error + } + + this.equal(chatSummary[0].type, 'LlmChatCompletionSummary') + this.match(chatSummary[1], expectedChatSummary, 'should match chat summary message') +} + +module.exports = { + DATASTORE_PATTERN, + EXTERN_PATTERN, + SNS_PATTERN, + SQS_PATTERN, + SEGMENT_DESTINATION, + checkAWSAttributes, + getMatchingSegments, + checkExternals +} diff --git a/test/versioned/aws-sdk-v3/elasticache.tap.js b/test/versioned/aws-sdk-v3/elasticache.tap.js new file mode 100644 index 0000000000..2daf0cd3d3 --- /dev/null +++ b/test/versioned/aws-sdk-v3/elasticache.tap.js @@ -0,0 +1,59 @@ +/* + * Copyright 2021 New Relic Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +'use strict' + +const tap = require('tap') +const helper = require('../../lib/agent_helper') +require('./common') +const { createResponseServer, FAKE_CREDENTIALS } = require('../../lib/aws-server-stubs') + +tap.test('ElastiCacheClient', (t) => { + t.beforeEach(async (t) => { + const server = createResponseServer() + await new Promise((resolve) => { + server.listen(0, resolve) + }) + t.context.server = server + t.context.agent = helper.instrumentMockedAgent() + const { ElastiCacheClient, ...lib } = require('@aws-sdk/client-elasticache') + t.context.AddTagsToResourceCommand = lib.AddTagsToResourceCommand + const endpoint = `http://localhost:${server.address().port}` + t.context.service = new ElastiCacheClient({ + credentials: FAKE_CREDENTIALS, + endpoint, + region: 'us-east-1' + }) + }) + + t.afterEach((t) => { + t.context.server.destroy() + helper.unloadAgent(t.context.agent) + }) + + t.test('AddTagsToResourceCommand', (t) => { + const { agent, service, AddTagsToResourceCommand } = t.context + helper.runInTransaction(agent, async (tx) => { + const cmd = new AddTagsToResourceCommand({ + ResourceName: 'STRING_VALUE' /* required */, + Tags: [ + /* required */ + { + Key: 'STRING_VALUE', + Value: 'STRING_VALUE' + } + ] + }) + await service.send(cmd) + tx.end() + setImmediate(t.checkExternals, { + service: 'ElastiCache', + operations: ['AddTagsToResourceCommand'], + tx + }) + }) + }) + t.end() +}) diff --git a/test/versioned/aws-sdk-v3/elb.tap.js b/test/versioned/aws-sdk-v3/elb.tap.js new file mode 100644 index 0000000000..fb51dfde5b --- /dev/null +++ b/test/versioned/aws-sdk-v3/elb.tap.js @@ -0,0 +1,62 @@ +/* + * Copyright 2021 New Relic Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +'use strict' + +const tap = require('tap') +const helper = require('../../lib/agent_helper') +require('./common') +const { createEmptyResponseServer, FAKE_CREDENTIALS } = require('../../lib/aws-server-stubs') + +tap.test('ElasticLoadBalancingClient', (t) => { + t.beforeEach(async (t) => { + const server = createEmptyResponseServer() + await new Promise((resolve) => { + server.listen(0, resolve) + }) + t.context.server = server + t.context.agent = helper.instrumentMockedAgent() + const { ElasticLoadBalancingClient, ...lib } = require('@aws-sdk/client-elastic-load-balancing') + t.context.AddTagsCommand = lib.AddTagsCommand + const endpoint = `http://localhost:${server.address().port}` + t.context.service = new ElasticLoadBalancingClient({ + credentials: FAKE_CREDENTIALS, + endpoint, + region: 'us-east-1' + }) + }) + + t.afterEach((t) => { + t.context.server.destroy() + helper.unloadAgent(t.context.agent) + }) + + t.test('AddTagsCommand', (t) => { + const { agent, service, AddTagsCommand } = t.context + helper.runInTransaction(agent, async (tx) => { + const cmd = new AddTagsCommand({ + LoadBalancerNames: ['my-load-balancer'], + Tags: [ + { + Key: 'project', + Value: 'lima' + }, + { + Key: 'department', + Value: 'digital-media' + } + ] + }) + await service.send(cmd) + tx.end() + setImmediate(t.checkExternals, { + service: 'Elastic Load Balancing', + operations: ['AddTagsCommand'], + tx + }) + }) + }) + t.end() +}) diff --git a/test/versioned/aws-sdk-v3/lambda.tap.js b/test/versioned/aws-sdk-v3/lambda.tap.js new file mode 100644 index 0000000000..ffb1a8d111 --- /dev/null +++ b/test/versioned/aws-sdk-v3/lambda.tap.js @@ -0,0 +1,58 @@ +/* + * Copyright 2021 New Relic Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +'use strict' + +const tap = require('tap') +const helper = require('../../lib/agent_helper') +require('./common') +const { createEmptyResponseServer, FAKE_CREDENTIALS } = require('../../lib/aws-server-stubs') + +tap.test('LambdaClient', (t) => { + t.beforeEach(async (t) => { + const server = createEmptyResponseServer() + await new Promise((resolve) => { + server.listen(0, resolve) + }) + t.context.server = server + t.context.agent = helper.instrumentMockedAgent() + const { LambdaClient, ...lib } = require('@aws-sdk/client-lambda') + t.context.AddLayerVersionPermissionCommand = lib.AddLayerVersionPermissionCommand + const endpoint = `http://localhost:${server.address().port}` + t.context.service = new LambdaClient({ + credentials: FAKE_CREDENTIALS, + endpoint, + region: 'us-east-1' + }) + }) + + t.afterEach((t) => { + t.context.server.destroy() + helper.unloadAgent(t.context.agent) + }) + + t.test('AddLayerVersionPermissionCommand', (t) => { + const { service, agent, AddLayerVersionPermissionCommand } = t.context + helper.runInTransaction(agent, async (tx) => { + const cmd = new AddLayerVersionPermissionCommand({ + Action: 'lambda:GetLayerVersion' /* required */, + LayerName: 'STRING_VALUE' /* required */, + Principal: '*' /* required */, + StatementId: 'STRING_VALUE' /* required */, + VersionNumber: 2 /* required */, + OrganizationId: 'o-0123456789', + RevisionId: 'STRING_VALUE' + }) + await service.send(cmd) + tx.end() + setImmediate(t.checkExternals, { + service: 'Lambda', + operations: ['AddLayerVersionPermissionCommand'], + tx + }) + }) + }) + t.end() +}) diff --git a/test/versioned/aws-sdk-v3/lib-dynamodb.tap.js b/test/versioned/aws-sdk-v3/lib-dynamodb.tap.js new file mode 100644 index 0000000000..67b16a88a6 --- /dev/null +++ b/test/versioned/aws-sdk-v3/lib-dynamodb.tap.js @@ -0,0 +1,260 @@ +/* + * Copyright 2020 New Relic Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +'use strict' + +const tap = require('tap') +const helper = require('../../lib/agent_helper') +const common = require('./common') +const { createEmptyResponseServer, FAKE_CREDENTIALS } = require('../../lib/aws-server-stubs') + +tap.test('DynamoDB', (t) => { + t.beforeEach(async (t) => { + const server = createEmptyResponseServer() + + await new Promise((resolve) => { + server.listen(0, resolve) + }) + + t.context.server = server + t.context.agent = helper.instrumentMockedAgent() + const lib = require('@aws-sdk/lib-dynamodb') + t.context.DynamoDBDocument = lib.DynamoDBDocument + t.context.DynamoDBDocumentClient = lib.DynamoDBDocumentClient + const { DynamoDBClient } = require('@aws-sdk/client-dynamodb') + t.context.ddbCommands = { + PutCommand: lib.PutCommand, + GetCommand: lib.GetCommand, + UpdateCommand: lib.UpdateCommand, + DeleteCommand: lib.DeleteCommand, + QueryCommand: lib.QueryCommand, + ScanCommand: lib.ScanCommand + } + + const endpoint = `http://localhost:${server.address().port}` + t.context.client = new DynamoDBClient({ + credentials: FAKE_CREDENTIALS, + endpoint, + region: 'us-east-1' + }) + + const tableName = `delete-aws-sdk-test-table-${Math.floor(Math.random() * 100000)}` + t.context.tests = createTests(tableName) + }) + + t.afterEach((t) => { + t.context.server.destroy() + helper.unloadAgent(t.context.agent) + Object.keys(require.cache).forEach((key) => { + if ( + key.includes('@aws-sdk/lib-dynamodb') || + key.includes('@aws-sdk/client-dynamodb') || + key.includes('@aws-sdk/smithy-client') || + key.includes('@smithy/smithy-client') + ) { + delete require.cache[key] + } + }) + }) + + t.test('client commands', (t) => { + const { DynamoDBDocumentClient, ddbCommands, client, agent, tests } = t.context + const docClient = new DynamoDBDocumentClient(client) + helper.runInTransaction(agent, async function (tx) { + for (let i = 0; i < tests.length; i++) { + const cfg = tests[i] + t.comment(`Testing ${cfg.operation}`) + + try { + await docClient.send(new ddbCommands[cfg.command](cfg.params)) + } catch (err) { + t.error(err) + } + } + + tx.end() + + const args = [t, tests, tx] + setImmediate(finish, ...args) + }) + }) + + t.test('client commands via callback', (t) => { + const { DynamoDBDocumentClient, ddbCommands, client, agent, tests } = t.context + const docClient = new DynamoDBDocumentClient(client) + helper.runInTransaction(agent, async function (tx) { + for (const test of tests) { + t.comment(`Testing ${test.operation}`) + + await new Promise((resolve) => { + docClient.send(new ddbCommands[test.command](test.params), (err) => { + t.error(err) + + return setImmediate(resolve) + }) + }) + } + + tx.end() + + const args = [t, tests, tx] + setImmediate(finish, ...args) + }) + }) + + t.test('client from commands', (t) => { + const { DynamoDBDocumentClient, ddbCommands, client, agent, tests } = t.context + const docClientFrom = DynamoDBDocumentClient.from(client) + helper.runInTransaction(agent, async function (tx) { + for (let i = 0; i < tests.length; i++) { + const cfg = tests[i] + t.comment(`Testing ${cfg.operation}`) + + try { + await docClientFrom.send(new ddbCommands[cfg.command](cfg.params)) + } catch (err) { + t.error(err) + } + } + + tx.end() + + const args = [t, tests, tx] + setImmediate(finish, ...args) + }) + }) + + t.test('calling send on client and doc client', (t) => { + const { DynamoDBDocumentClient, ddbCommands, client, agent, tests } = t.context + const docClientFrom = DynamoDBDocumentClient.from(client) + let errorOccurred = false + helper.runInTransaction(agent, async function (tx) { + for (let i = 0; i < tests.length; i++) { + const cfg = tests[i] + t.comment(`Testing ${cfg.operation}`) + + try { + await docClientFrom.send(new ddbCommands[cfg.command](cfg.params)) + await client.send(new ddbCommands[cfg.command](cfg.params)) + } catch (err) { + errorOccurred = true + t.error(err) + } + } + + t.notOk(errorOccurred, 'should not have a middleware error with two clients') + + tx.end() + t.end() + }) + }) + + t.test('DynamoDBDocument client from commands', (t) => { + const { DynamoDBDocument, ddbCommands, client, agent, tests } = t.context + const docClientFrom = DynamoDBDocument.from(client) + helper.runInTransaction(agent, async function (tx) { + for (let i = 0; i < tests.length; i++) { + const cfg = tests[i] + t.comment(`Testing ${cfg.operation}`) + + try { + await docClientFrom.send(new ddbCommands[cfg.command](cfg.params)) + } catch (err) { + t.error(err) + } + } + + tx.end() + + const args = [t, tests, tx] + setImmediate(finish, ...args) + }) + }) + t.end() +}) + +function finish(t, tests, tx) { + const root = tx.trace.root + const segments = common.checkAWSAttributes(t, root, common.DATASTORE_PATTERN) + + t.equal(segments.length, tests.length, `should have ${tests.length} aws datastore segments`) + + const externalSegments = common.checkAWSAttributes(t, root, common.EXTERN_PATTERN) + t.equal(externalSegments.length, 0, 'should not have any External segments') + + segments.forEach((segment, i) => { + const operation = tests[i].operation + t.equal( + segment.name, + `Datastore/operation/DynamoDB/${operation}`, + 'should have operation in segment name' + ) + const attrs = segment.attributes.get(common.SEGMENT_DESTINATION) + attrs.port_path_or_id = parseInt(attrs.port_path_or_id, 10) + t.match( + attrs, + { + 'host': String, + 'port_path_or_id': Number, + 'product': 'DynamoDB', + 'collection': String, + 'aws.operation': operation, + 'aws.requestId': String, + 'aws.region': 'us-east-1', + 'aws.service': 'DynamoDB' + }, + 'should have expected attributes' + ) + }) + + t.end() +} + +function createTests(tableName) { + const docUniqueArtist = `DELETE_One You Know ${Math.floor(Math.random() * 100000)}` + const docPutParams = getDocPutItemParams(tableName, docUniqueArtist) + const docItemParams = getDocItemParams(tableName, docUniqueArtist) + const docQueryParams = getDocQueryParams(tableName, docUniqueArtist) + + return [ + { params: docPutParams, operation: 'PutItemCommand', command: 'PutCommand' }, + { params: docItemParams, operation: 'GetItemCommand', command: 'GetCommand' }, + { params: docItemParams, operation: 'UpdateItemCommand', command: 'UpdateCommand' }, + { params: { TableName: tableName }, operation: 'ScanCommand', command: 'ScanCommand' }, + { params: docQueryParams, operation: 'QueryCommand', command: 'QueryCommand' }, + { params: docItemParams, operation: 'DeleteItemCommand', command: 'DeleteCommand' } + ] +} + +function getDocPutItemParams(tableName, uniqueArtist) { + return { + Item: { + AlbumTitle: 'Somewhat Famous', + Artist: uniqueArtist, + SongTitle: 'Call Me Today' + }, + TableName: tableName + } +} + +function getDocItemParams(tableName, uniqueArtist) { + return { + Key: { + Artist: uniqueArtist, + SongTitle: 'Call Me Today' + }, + TableName: tableName + } +} + +function getDocQueryParams(tableName, uniqueArtist) { + return { + ExpressionAttributeValues: { + ':v1': uniqueArtist + }, + KeyConditionExpression: 'Artist = :v1', + TableName: tableName + } +} diff --git a/test/versioned/aws-sdk-v3/newrelic.js b/test/versioned/aws-sdk-v3/newrelic.js new file mode 100644 index 0000000000..5bfe53711f --- /dev/null +++ b/test/versioned/aws-sdk-v3/newrelic.js @@ -0,0 +1,25 @@ +/* + * Copyright 2020 New Relic Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +'use strict' + +exports.config = { + app_name: ['My Application'], + license_key: 'license key here', + logging: { + level: 'trace', + filepath: '../../../newrelic_agent.log' + }, + utilization: { + detect_aws: false, + detect_pcf: false, + detect_azure: false, + detect_gcp: false, + detect_docker: false + }, + transaction_tracer: { + enabled: true + } +} diff --git a/test/versioned/aws-sdk-v3/package.json b/test/versioned/aws-sdk-v3/package.json new file mode 100644 index 0000000000..dd87a6c261 --- /dev/null +++ b/test/versioned/aws-sdk-v3/package.json @@ -0,0 +1,217 @@ +{ + "name": "aws-sdk-v3-tests", + "engines": { + "node": ">=16.0" + }, + "targets": [ + {"name": "@aws-sdk/client-sqs", "minAgentVersion": "8.7.1"}, + {"name": "@aws-sdk/client-sns", "minAgentVersion": "8.7.1"}, + {"name": "@aws-sdk/client-dynamodb", "minAgentVersion": "8.7.1"}, + {"name": "@aws-sdk/smithy-client", "minAgentVersion": "8.7.1"}, + {"name": "@smithy/smithy-client", "minAgentVersion": "11.0.0"}, + {"name": "@aws-sdk/client-bedrock-runtime", "minAgentVersion": "11.13.0"} + ], + "version": "0.0.0", + "private": true, + "tests": [ + { + "engines": { + "node": ">=16.0" + }, + "dependencies": { + "@aws-sdk/client-api-gateway": { + "versions": ">=3.0.0 <=3.193.0 || >3.196.0 <3.377.0 || >3.377.0 ", + "samples": 5 + } + }, + "files": [ + "api-gateway.tap.js" + ] + }, + { + "engines": { + "node": ">=16.0" + }, + "dependencies": { + "@aws-sdk/client-elasticache": { + "versions": ">=3.0.0 <=3.193.0 || >3.196.0 <3.377.0 || >3.377.0 ", + "samples": 2 + } + }, + "files": [ + "elasticache.tap.js" + ] + }, + { + "engines": { + "node": ">=16.0" + }, + "dependencies": { + "@aws-sdk/client-elastic-load-balancing": { + "versions": ">=3.0.0 <=3.193.0 || >3.196.0 <3.377.0 || >3.377.0 ", + "samples": 2 + } + }, + "files": [ + "elb.tap.js" + ] + }, + { + "engines": { + "node": ">=16.0" + }, + "dependencies": { + "@aws-sdk/client-lambda": { + "versions": ">=3.0.0 <=3.193.0 || >3.196.0 <3.377.0 || >3.377.0 ", + "samples": 2 + } + }, + "files": [ + "lambda.tap.js" + ] + }, + { + "engines": { + "node": ">=16.0" + }, + "dependencies": { + "@aws-sdk/client-rds": { + "versions": ">=3.0.0 <=3.193.0 || >3.196.0 <3.377.0 || >3.377.0 ", + "samples": 2 + } + }, + "files": [ + "rds.tap.js" + ] + }, + { + "engines": { + "node": ">=16.0" + }, + "dependencies": { + "@aws-sdk/client-redshift": { + "versions": ">=3.0.0 <=3.193.0 || >3.196.0 <3.377.0 || >3.377.0 ", + "samples": 2 + } + }, + "files": [ + "redshift.tap.js" + ] + }, + { + "engines": { + "node": ">=16.0" + }, + "dependencies": { + "@aws-sdk/client-rekognition": { + "versions": ">=3.0.0 <=3.193.0 || >3.196.0 <3.377.0 || >3.377.0 ", + "samples": 2 + } + }, + "files": [ + "rekognition.tap.js" + ] + }, + { + "engines": { + "node": ">=16.0" + }, + "dependencies": { + "@aws-sdk/client-s3": { + "versions": ">=3.0.0 <=3.193.0 || >3.196.0 <3.377.0 || >3.377.0 ", + "samples": 5 + } + }, + "files": [ + "s3.tap.js" + ] + }, + { + "engines": { + "node": ">=16.0" + }, + "dependencies": { + "@aws-sdk/client-ses": { + "versions": ">=3.0.0 <=3.193.0 || >3.196.0 <3.377.0 || >3.377.0 ", + "samples": 2 + } + }, + "files": [ + "ses.tap.js" + ] + }, + { + "engines": { + "node": ">=16.0" + }, + "dependencies": { + "@aws-sdk/client-sns": { + "versions": ">=3.0.0 <=3.193.0 || >3.196.0 <3.377.0 || >3.377.0 ", + "samples": 10 + } + }, + "files": [ + "sns.tap.js" + ] + }, + { + "engines": { + "node": ">=16.0" + }, + "dependencies": { + "@aws-sdk/client-sqs": { + "versions": ">=3.0.0 <=3.193.0 || >3.196.0 <3.377.0 || >3.377.0 ", + "samples": 10 + } + }, + "files": [ + "sqs.tap.js" + ] + }, + { + "engines": { + "node": ">=16.0" + }, + "dependencies": { + "@aws-sdk/client-dynamodb": { + "versions": ">=3.0.0 <=3.193.0 || >3.196.0 <3.377.0 || >3.377.0 ", + "samples": 10 + } + }, + "files": [ + "client-dynamodb.tap.js" + ] + }, + { + "engines": { + "node": ">=16.0" + }, + "dependencies": { + "@aws-sdk/util-dynamodb": "latest", + "@aws-sdk/client-dynamodb": "3.476.0", + "@aws-sdk/lib-dynamodb": { + "versions": ">=3.0.0 <=3.193.0 || >3.196.0 <3.377.0 || >3.377.0 ", + "samples": 10 + } + }, + "files": [ + "lib-dynamodb.tap.js" + ] + }, + { + "engines": { + "node": ">=16.0" + }, + "dependencies": { + "@aws-sdk/client-bedrock-runtime": "^3.474.0" + }, + "files": [ + "bedrock-chat-completions.tap.js", + "bedrock-embeddings.tap.js", + "bedrock-negative-tests.tap.js" + ] + } + ], + "dependencies": {} +} + diff --git a/test/versioned/aws-sdk-v3/rds.tap.js b/test/versioned/aws-sdk-v3/rds.tap.js new file mode 100644 index 0000000000..c314861611 --- /dev/null +++ b/test/versioned/aws-sdk-v3/rds.tap.js @@ -0,0 +1,58 @@ +/* + * Copyright 2021 New Relic Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +'use strict' + +const tap = require('tap') +const helper = require('../../lib/agent_helper') +require('./common') +const { createEmptyResponseServer, FAKE_CREDENTIALS } = require('../../lib/aws-server-stubs') + +tap.test('RDSClient', (t) => { + t.beforeEach(async (t) => { + const server = createEmptyResponseServer() + await new Promise((resolve) => { + server.listen(0, resolve) + }) + t.context.server = server + t.context.agent = helper.instrumentMockedAgent() + const { RDSClient, ...lib } = require('@aws-sdk/client-rds') + t.context.AddRoleToDBClusterCommand = lib.AddRoleToDBClusterCommand + const endpoint = `http://localhost:${server.address().port}` + t.context.service = new RDSClient({ + credentials: FAKE_CREDENTIALS, + endpoint, + region: 'us-east-1' + }) + }) + + t.afterEach((t) => { + t.context.server.destroy() + helper.unloadAgent(t.context.agent) + }) + + t.test('AddRoleToDBClusterCommand', (t) => { + const { service, agent, AddRoleToDBClusterCommand } = t.context + helper.runInTransaction(agent, async (tx) => { + const cmd = new AddRoleToDBClusterCommand({ + Action: 'lambda:GetLayerVersion' /* required */, + LayerName: 'STRING_VALUE' /* required */, + Principal: '*' /* required */, + StatementId: 'STRING_VALUE' /* required */, + VersionNumber: 2 /* required */, + OrganizationId: 'o-0123456789', + RevisionId: 'STRING_VALUE' + }) + await service.send(cmd) + tx.end() + setImmediate(t.checkExternals, { + service: 'RDS', + operations: ['AddRoleToDBClusterCommand'], + tx + }) + }) + }) + t.end() +}) diff --git a/test/versioned/aws-sdk-v3/redshift.tap.js b/test/versioned/aws-sdk-v3/redshift.tap.js new file mode 100644 index 0000000000..7c7436ba49 --- /dev/null +++ b/test/versioned/aws-sdk-v3/redshift.tap.js @@ -0,0 +1,53 @@ +/* + * Copyright 2021 New Relic Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +'use strict' + +const tap = require('tap') +const helper = require('../../lib/agent_helper') +require('./common') +const { createResponseServer, FAKE_CREDENTIALS } = require('../../lib/aws-server-stubs') + +tap.test('RedshiftClient', (t) => { + t.beforeEach(async (t) => { + const server = createResponseServer() + await new Promise((resolve) => { + server.listen(0, resolve) + }) + t.context.server = server + t.context.agent = helper.instrumentMockedAgent() + const { RedshiftClient, ...lib } = require('@aws-sdk/client-redshift') + t.context.AcceptReservedNodeExchangeCommand = lib.AcceptReservedNodeExchangeCommand + const endpoint = `http://localhost:${server.address().port}` + t.context.service = new RedshiftClient({ + credentials: FAKE_CREDENTIALS, + endpoint, + region: 'us-east-1' + }) + }) + + t.afterEach((t) => { + t.context.server.destroy() + helper.unloadAgent(t.context.agent) + }) + + t.test('AcceptReservedNodeExchangeCommand', (t) => { + const { agent, service, AcceptReservedNodeExchangeCommand } = t.context + helper.runInTransaction(agent, async (tx) => { + const cmd = new AcceptReservedNodeExchangeCommand({ + ReservedNodeId: 'STRING_VALUE' /* required */, + TargetReservedNodeOfferingId: 'STRING_VALUE' /* required */ + }) + await service.send(cmd) + tx.end() + setImmediate(t.checkExternals, { + service: 'Redshift', + operations: ['AcceptReservedNodeExchangeCommand'], + tx + }) + }) + }) + t.end() +}) diff --git a/test/versioned/aws-sdk-v3/rekognition.tap.js b/test/versioned/aws-sdk-v3/rekognition.tap.js new file mode 100644 index 0000000000..bc5d1f4d2c --- /dev/null +++ b/test/versioned/aws-sdk-v3/rekognition.tap.js @@ -0,0 +1,64 @@ +/* + * Copyright 2021 New Relic Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +'use strict' + +const tap = require('tap') +const helper = require('../../lib/agent_helper') +require('./common') +const { createEmptyResponseServer, FAKE_CREDENTIALS } = require('../../lib/aws-server-stubs') + +tap.test('RekognitionClient', (t) => { + t.beforeEach(async (t) => { + const server = createEmptyResponseServer() + await new Promise((resolve) => { + server.listen(0, resolve) + }) + t.context.server = server + t.context.agent = helper.instrumentMockedAgent() + const { RekognitionClient, ...lib } = require('@aws-sdk/client-rekognition') + t.context.CompareFacesCommand = lib.CompareFacesCommand + const endpoint = `http://localhost:${server.address().port}` + t.context.service = new RekognitionClient({ + credentials: FAKE_CREDENTIALS, + endpoint, + region: 'us-east-1' + }) + }) + + t.afterEach((t) => { + t.context.server.destroy() + helper.unloadAgent(t.context.agent) + }) + + t.test('CompareFacesCommand', (t) => { + const { service, agent, CompareFacesCommand } = t.context + helper.runInTransaction(agent, async (tx) => { + const cmd = new CompareFacesCommand({ + SimilarityThreshold: 90, + SourceImage: { + S3Object: { + Bucket: 'mybucket', + Name: 'mysourceimage' + } + }, + TargetImage: { + S3Object: { + Bucket: 'mybucket', + Name: 'mytargetimage' + } + } + }) + await service.send(cmd) + tx.end() + setImmediate(t.checkExternals, { + service: 'Rekognition', + operations: ['CompareFacesCommand'], + tx + }) + }) + }) + t.end() +}) diff --git a/test/versioned/aws-sdk-v3/s3.tap.js b/test/versioned/aws-sdk-v3/s3.tap.js new file mode 100644 index 0000000000..c525bca797 --- /dev/null +++ b/test/versioned/aws-sdk-v3/s3.tap.js @@ -0,0 +1,69 @@ +/* + * Copyright 2021 New Relic Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +'use strict' + +const tap = require('tap') +const helper = require('../../lib/agent_helper') +require('./common') +const { createEmptyResponseServer, FAKE_CREDENTIALS } = require('../../lib/aws-server-stubs') + +tap.test('S3 buckets', (t) => { + t.beforeEach(async (t) => { + const server = createEmptyResponseServer() + + await new Promise((resolve) => { + server.listen(0, resolve) + }) + + t.context.server = server + t.context.agent = helper.instrumentMockedAgent() + const { S3Client, ...lib } = require('@aws-sdk/client-s3') + t.context.client = new S3Client({ + region: 'us-east-1', + credentials: FAKE_CREDENTIALS, + endpoint: `http://localhost:${server.address().port}`, + // allows using generic endpoint, instead of needing a + // bucket.endpoint server setup. + forcePathStyle: true + }) + + t.context.lib = lib + }) + + t.afterEach((t) => { + t.context.server.destroy() + helper.unloadAgent(t.context.agent) + }) + + t.test('commands', (t) => { + const { + client, + agent, + lib: { HeadBucketCommand, CreateBucketCommand, DeleteBucketCommand } + } = t.context + const Bucket = 'delete-aws-sdk-test-bucket-' + Math.floor(Math.random() * 100000) + + helper.runInTransaction(agent, async (tx) => { + try { + await client.send(new HeadBucketCommand({ Bucket })) + await client.send(new CreateBucketCommand({ Bucket })) + await client.send(new DeleteBucketCommand({ Bucket })) + } catch (err) { + t.error(err) + } + + tx.end() + + const args = { + tx, + service: 'S3', + operations: ['HeadBucketCommand', 'CreateBucketCommand', 'DeleteBucketCommand'] + } + setImmediate(t.checkExternals, args) + }) + }) + t.end() +}) diff --git a/test/versioned/aws-sdk-v3/ses.tap.js b/test/versioned/aws-sdk-v3/ses.tap.js new file mode 100644 index 0000000000..d21bf0f23b --- /dev/null +++ b/test/versioned/aws-sdk-v3/ses.tap.js @@ -0,0 +1,54 @@ +/* + * Copyright 2021 New Relic Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +'use strict' + +const tap = require('tap') +const helper = require('../../lib/agent_helper') +require('./common') +const { createResponseServer, FAKE_CREDENTIALS } = require('../../lib/aws-server-stubs') + +tap.test('SESClient', (t) => { + t.beforeEach(async (t) => { + const server = createResponseServer() + await new Promise((resolve) => { + server.listen(0, resolve) + }) + t.context.server = server + t.context.agent = helper.instrumentMockedAgent() + const { SESClient, ...lib } = require('@aws-sdk/client-ses') + t.context.SendEmailCommand = lib.SendEmailCommand + const endpoint = `http://localhost:${server.address().port}` + t.context.service = new SESClient({ + credentials: FAKE_CREDENTIALS, + endpoint, + region: 'us-east-1' + }) + }) + + t.afterEach((t) => { + t.context.server.destroy() + helper.unloadAgent(t.context.agent) + }) + + t.test('SendEmailCommand', (t) => { + const { agent, service, SendEmailCommand } = t.context + helper.runInTransaction(agent, async (tx) => { + const cmd = new SendEmailCommand({ + Destination: 'foo@bar.com', + Message: 'Hello World', + Source: 'sender@ses.com' + }) + await service.send(cmd) + tx.end() + setImmediate(t.checkExternals, { + service: 'SES', + operations: ['SendEmailCommand'], + tx + }) + }) + }) + t.end() +}) diff --git a/test/versioned/aws-sdk-v3/sns.tap.js b/test/versioned/aws-sdk-v3/sns.tap.js new file mode 100644 index 0000000000..0ab125cd4d --- /dev/null +++ b/test/versioned/aws-sdk-v3/sns.tap.js @@ -0,0 +1,255 @@ +/* + * Copyright 2021 New Relic Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +'use strict' + +const tap = require('tap') +const helper = require('../../lib/agent_helper') +const common = require('./common') +const { createResponseServer, FAKE_CREDENTIALS } = require('../../lib/aws-server-stubs') +const sinon = require('sinon') + +tap.test('SNS', (t) => { + t.beforeEach(async (t) => { + const server = createResponseServer() + + await new Promise((resolve) => { + server.listen(0, resolve) + }) + + t.context.server = server + t.context.agent = helper.instrumentMockedAgent() + const Shim = require('../../../lib/shim/message-shim') + t.context.setLibrarySpy = sinon.spy(Shim.prototype, 'setLibrary') + const lib = require('@aws-sdk/client-sns') + const SNSClient = lib.SNSClient + t.context.lib = lib + t.context.sns = new SNSClient({ + credentials: FAKE_CREDENTIALS, + endpoint: `http://localhost:${server.address().port}`, + region: 'us-east-1' + }) + }) + + t.afterEach((t) => { + t.context.server.destroy() + helper.unloadAgent(t.context.agent) + t.context.setLibrarySpy.restore() + // this may be brute force but i could not figure out + // which files within the modules were cached preventing the instrumenting + // from running on every test + Object.keys(require.cache).forEach((key) => { + if ( + key.includes('@aws-sdk/client-sns') || + key.includes('@aws-sdk/smithy-client') || + key.includes('@smithy/smithy-client') + ) { + delete require.cache[key] + } + }) + }) + + t.test('publish with callback', (t) => { + const { + agent, + sns, + lib: { PublishCommand } + } = t.context + helper.runInTransaction(agent, (tx) => { + const params = { Message: 'Hello!' } + + const cmd = new PublishCommand(params) + sns.send(cmd, (err) => { + t.error(err) + tx.end() + + const destName = 'PhoneNumber' + const args = [t, tx, destName] + setImmediate(finish, ...args) + }) + }) + }) + + t.test('publish with default destination(PhoneNumber)', (t) => { + const { + agent, + sns, + lib: { PublishCommand } + } = t.context + helper.runInTransaction(agent, async (tx) => { + const params = { Message: 'Hello!' } + + try { + const cmd = new PublishCommand(params) + await sns.send(cmd) + } catch (error) { + t.error(error) + } + + tx.end() + + const destName = 'PhoneNumber' + const args = [t, tx, destName] + setImmediate(finish, ...args) + }) + }) + + t.test('publish with TopicArn as destination', (t) => { + const { + agent, + sns, + lib: { PublishCommand } + } = t.context + helper.runInTransaction(agent, async (tx) => { + const TopicArn = 'TopicArn' + const params = { TopicArn, Message: 'Hello!' } + + try { + const cmd = new PublishCommand(params) + await sns.send(cmd) + } catch (error) { + t.error(error) + } + + tx.end() + + const args = [t, tx, TopicArn] + setImmediate(finish, ...args) + }) + }) + + t.test('publish with TargetArn as destination', (t) => { + const { + agent, + sns, + lib: { PublishCommand } + } = t.context + helper.runInTransaction(agent, async (tx) => { + const TargetArn = 'TargetArn' + const params = { TargetArn, Message: 'Hello!' } + + try { + const cmd = new PublishCommand(params) + await sns.send(cmd) + } catch (error) { + t.error(error) + } + + tx.end() + + const args = [t, tx, TargetArn] + setImmediate(finish, ...args) + }) + }) + + t.test('publish with TopicArn as destination when both Topic and Target Arn are defined', (t) => { + const { + agent, + sns, + lib: { PublishCommand } + } = t.context + helper.runInTransaction(agent, async (tx) => { + const TargetArn = 'TargetArn' + const TopicArn = 'TopicArn' + const params = { TargetArn, TopicArn, Message: 'Hello!' } + + try { + const cmd = new PublishCommand(params) + await sns.send(cmd) + } catch (error) { + t.error(error) + } + + tx.end() + + const args = [t, tx, TopicArn] + setImmediate(finish, ...args) + }) + }) + + t.test( + 'should record external segment and not a SNS segment for a command that is not PublishCommand', + (t) => { + const { + agent, + sns, + lib: { ListTopicsCommand } + } = t.context + helper.runInTransaction(agent, async (tx) => { + const TargetArn = 'TargetArn' + const TopicArn = 'TopicArn' + const params = { TargetArn, TopicArn, Message: 'Hello!' } + + try { + const cmd = new ListTopicsCommand(params) + await sns.send(cmd) + } catch (error) { + t.error(error) + } + + tx.end() + + setImmediate(t.checkExternals, { + tx, + service: 'SNS', + operations: ['ListTopicsCommand'] + }) + }) + } + ) + + t.test('should mark requests to be dt-disabled', (t) => { + const { + agent, + sns, + lib: { ListTopicsCommand } + } = t.context + t.plan(2) + + helper.runInTransaction(agent, async (tx) => { + const params = { Message: 'Hiya' } + const cmd = new ListTopicsCommand(params) + sns.middlewareStack.add( + (next) => async (args) => { + const result = await next(args) + const headers = result.response.body.req._headers + t.notOk(headers.traceparent, 'should not add traceparent header to request') + return result + }, + { name: 'TestMw', step: 'deserialize' } + ) + const res = await sns.send(cmd) + tx.end() + t.ok(res) + }) + }) + t.end() +}) + +function finish(t, tx, destName) { + const root = tx.trace.root + + const messages = common.checkAWSAttributes(t, root, common.SNS_PATTERN) + t.equal(messages.length, 1, 'should have 1 message broker segment') + t.ok(messages[0].name.endsWith(destName), 'should have appropriate destination') + + const externalSegments = common.checkAWSAttributes(t, root, common.EXTERN_PATTERN) + t.equal(externalSegments.length, 0, 'should not have any External segments') + + const attrs = messages[0].attributes.get(common.SEGMENT_DESTINATION) + t.match( + attrs, + { + 'aws.operation': 'PublishCommand', + 'aws.requestId': String, + 'aws.service': /sns|SNS/, + 'aws.region': 'us-east-1' + }, + 'should have expected attributes for PublishCommand' + ) + + t.equal(t.context.setLibrarySpy.callCount, 1, 'should only call setLibrary once and not per call') + t.end() +} diff --git a/test/versioned/aws-sdk-v3/sqs.tap.js b/test/versioned/aws-sdk-v3/sqs.tap.js new file mode 100644 index 0000000000..8c7fed7871 --- /dev/null +++ b/test/versioned/aws-sdk-v3/sqs.tap.js @@ -0,0 +1,189 @@ +/* + * Copyright 2020 New Relic Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +'use strict' + +const tap = require('tap') +const helper = require('../../lib/agent_helper') +const common = require('./common') +const { createResponseServer, FAKE_CREDENTIALS } = require('../../lib/aws-server-stubs') +const sinon = require('sinon') + +const AWS_REGION = 'us-east-1' + +tap.test('SQS API', (t) => { + t.beforeEach(async (t) => { + const server = createResponseServer() + + await new Promise((resolve) => { + server.listen(0, resolve) + }) + + t.context.server = server + t.context.agent = helper.instrumentMockedAgent() + const Shim = require('../../../lib/shim/message-shim') + t.context.setLibrarySpy = sinon.spy(Shim.prototype, 'setLibrary') + const lib = require('@aws-sdk/client-sqs') + const SQSClient = lib.SQSClient + t.context.lib = lib + + t.context.sqs = new SQSClient({ + credentials: FAKE_CREDENTIALS, + endpoint: `http://localhost:${server.address().port}`, + region: AWS_REGION + }) + + t.context.queueName = 'delete-aws-sdk-test-queue-' + Math.floor(Math.random() * 100000) + }) + + t.afterEach((t) => { + t.context.server.destroy() + helper.unloadAgent(t.context.agent) + t.context.setLibrarySpy.restore() + }) + + t.test('commands with promises', async (t) => { + const { + agent, + queueName, + sqs, + lib: { + CreateQueueCommand, + SendMessageCommand, + SendMessageBatchCommand, + ReceiveMessageCommand + } + } = t.context + // create queue + const createParams = getCreateParams(queueName) + const createCommand = new CreateQueueCommand(createParams) + const { QueueUrl } = await sqs.send(createCommand) + t.ok(QueueUrl) + // run send/receive commands in transaction + await helper.runInTransaction(agent, async (transaction) => { + // send message + const sendMessageParams = getSendMessageParams(QueueUrl) + const sendMessageCommand = new SendMessageCommand(sendMessageParams) + const { MessageId } = await sqs.send(sendMessageCommand) + t.ok(MessageId) + // send message batch + const sendMessageBatchParams = getSendMessageBatchParams(QueueUrl) + const sendMessageBatchCommand = new SendMessageBatchCommand(sendMessageBatchParams) + const { Successful } = await sqs.send(sendMessageBatchCommand) + t.ok(Successful) + // receive message + const receiveMessageParams = getReceiveMessageParams(QueueUrl) + const receiveMessageCommand = new ReceiveMessageCommand(receiveMessageParams) + const { Messages } = await sqs.send(receiveMessageCommand) + t.ok(Messages) + // wrap up + transaction.end() + await finish({ t, transaction, queueName }) + }) + }) + t.end() +}) + +function finish({ t, transaction, queueName }) { + const expectedSegmentCount = 3 + + const root = transaction.trace.root + const segments = common.checkAWSAttributes(t, root, common.SQS_PATTERN) + + t.equal( + segments.length, + expectedSegmentCount, + `should have ${expectedSegmentCount} AWS MessageBroker/SQS segments` + ) + + const externalSegments = common.checkAWSAttributes(t, root, common.EXTERN_PATTERN) + t.equal(externalSegments.length, 0, 'should not have any External segments') + + const [sendMessage, sendMessageBatch, receiveMessage] = segments + + checkName(t, sendMessage.name, 'Produce', queueName) + checkAttributes(t, sendMessage, 'SendMessageCommand') + + checkName(t, sendMessageBatch.name, 'Produce', queueName) + checkAttributes(t, sendMessageBatch, 'SendMessageBatchCommand') + + checkName(t, receiveMessage.name, 'Consume', queueName) + checkAttributes(t, receiveMessage, 'ReceiveMessageCommand') + t.equal(t.context.setLibrarySpy.callCount, 1, 'should only call setLibrary once and not per call') +} + +function checkName(t, name, action, queueName) { + const specificName = `/${action}/Named/${queueName}` + + t.match(name, specificName, 'should have correct name') +} + +function checkAttributes(t, segment, operation) { + const actualAttributes = segment.attributes.get(common.SEGMENT_DESTINATION) + + const expectedAttributes = { + 'aws.operation': operation, + 'aws.requestId': String, + 'aws.service': /sqs|SQS/, + 'aws.region': AWS_REGION + } + + t.match(actualAttributes, expectedAttributes, `should have expected attributes for ${operation}`) +} + +function getCreateParams(queueName) { + return { + QueueName: queueName, + Attributes: { + MessageRetentionPeriod: '1200' // 20 minutes + } + } +} + +function getSendMessageParams(queueUrl) { + return { + MessageAttributes: { + Attr1: { + DataType: 'String', + StringValue: 'One' + } + }, + MessageBody: 'This is a test message', + QueueUrl: queueUrl + } +} + +function getSendMessageBatchParams(queueUrl) { + return { + Entries: [ + { + Id: 'ONE', + MessageBody: 'ONE BODY', + MessageAttributes: { + Attribute1: { DataType: 'String', StringValue: 'Value 1' }, + Attribute2: { DataType: 'String', StringValue: 'Value 2' } + } + }, + { + Id: 'TWO', + MessageBody: 'TWO BODY', + MessageAttributes: { + Attribute1: { DataType: 'String', StringValue: 'Value 1' }, + Attribute2: { DataType: 'String', StringValue: 'Value 2' } + } + } + ], + QueueUrl: queueUrl + } +} + +function getReceiveMessageParams(queueUrl) { + return { + AttributeNames: ['SentTimestamp'], + MaxNumberOfMessages: 2, + MessageAttributeNames: ['All'], + QueueUrl: queueUrl + } +} diff --git a/third_party_manifest.json b/third_party_manifest.json index 72d60bca56..48a0b1c12d 100644 --- a/third_party_manifest.json +++ b/third_party_manifest.json @@ -1,5 +1,5 @@ { - "lastUpdated": "Tue Apr 16 2024 15:55:51 GMT-0400 (Eastern Daylight Time)", + "lastUpdated": "Wed Apr 24 2024 12:06:09 GMT-0400 (Eastern Daylight Time)", "projectName": "New Relic Node Agent", "projectUrl": "https://github.com/newrelic/node-newrelic", "includeOptDeps": true, @@ -16,15 +16,15 @@ "licenseTextSource": "file", "publisher": "Contrast Security" }, - "@newrelic/native-metrics@10.1.1": { + "@newrelic/native-metrics@10.0.1": { "name": "@newrelic/native-metrics", - "version": "10.1.1", + "version": "10.0.1", "range": "^10.0.0", "licenses": "Apache-2.0", "repoUrl": "https://github.com/newrelic/node-native-metrics", - "versionedRepoUrl": "https://github.com/newrelic/node-native-metrics/tree/v10.1.1", + "versionedRepoUrl": "https://github.com/newrelic/node-native-metrics/tree/v10.0.1", "licenseFile": "node_modules/@newrelic/native-metrics/LICENSE", - "licenseUrl": "https://github.com/newrelic/node-native-metrics/blob/v10.1.1/LICENSE", + "licenseUrl": "https://github.com/newrelic/node-native-metrics/blob/v10.0.1/LICENSE", "licenseTextSource": "file", "publisher": "New Relic Node.js agent team", "email": "nodejs@newrelic.com" @@ -44,43 +44,30 @@ }, "includeDev": true, "dependencies": { - "@grpc/grpc-js@1.10.6": { + "@grpc/grpc-js@1.10.0": { "name": "@grpc/grpc-js", - "version": "1.10.6", + "version": "1.10.0", "range": "^1.9.4", "licenses": "Apache-2.0", "repoUrl": "https://github.com/grpc/grpc-node/tree/master/packages/grpc-js", - "versionedRepoUrl": "https://github.com/grpc/grpc-node/tree/master/packages/grpc-js/tree/v1.10.6", + "versionedRepoUrl": "https://github.com/grpc/grpc-node/tree/master/packages/grpc-js/tree/v1.10.0", "licenseFile": "node_modules/@grpc/grpc-js/LICENSE", - "licenseUrl": "https://github.com/grpc/grpc-node/tree/master/packages/grpc-js/blob/v1.10.6/LICENSE", + "licenseUrl": "https://github.com/grpc/grpc-node/tree/master/packages/grpc-js/blob/v1.10.0/LICENSE", "licenseTextSource": "file", "publisher": "Google Inc." }, - "@grpc/proto-loader@0.7.12": { + "@grpc/proto-loader@0.7.10": { "name": "@grpc/proto-loader", - "version": "0.7.12", + "version": "0.7.10", "range": "^0.7.5", "licenses": "Apache-2.0", "repoUrl": "https://github.com/grpc/grpc-node", - "versionedRepoUrl": "https://github.com/grpc/grpc-node/tree/v0.7.12", + "versionedRepoUrl": "https://github.com/grpc/grpc-node/tree/v0.7.10", "licenseFile": "node_modules/@grpc/proto-loader/LICENSE", - "licenseUrl": "https://github.com/grpc/grpc-node/blob/v0.7.12/LICENSE", + "licenseUrl": "https://github.com/grpc/grpc-node/blob/v0.7.10/LICENSE", "licenseTextSource": "file", "publisher": "Google Inc." }, - "@newrelic/aws-sdk@7.4.1": { - "name": "@newrelic/aws-sdk", - "version": "7.4.1", - "range": "^7.3.0", - "licenses": "Apache-2.0", - "repoUrl": "https://github.com/newrelic/node-newrelic-aws-sdk", - "versionedRepoUrl": "https://github.com/newrelic/node-newrelic-aws-sdk/tree/v7.4.1", - "licenseFile": "node_modules/@newrelic/aws-sdk/LICENSE", - "licenseUrl": "https://github.com/newrelic/node-newrelic-aws-sdk/blob/v7.4.1/LICENSE", - "licenseTextSource": "file", - "publisher": "New Relic Node.js agent team", - "email": "nodejs@newrelic.com" - }, "@newrelic/ritm@7.2.0": { "name": "@newrelic/ritm", "version": "7.2.0", @@ -95,15 +82,15 @@ "email": "w@tson.dk", "url": "https://twitter.com/wa7son" }, - "@newrelic/security-agent@1.2.0": { + "@newrelic/security-agent@1.1.1": { "name": "@newrelic/security-agent", - "version": "1.2.0", + "version": "1.1.1", "range": "^1.1.1", "licenses": "UNKNOWN", "repoUrl": "https://github.com/newrelic/csec-node-agent", - "versionedRepoUrl": "https://github.com/newrelic/csec-node-agent/tree/v1.2.0", + "versionedRepoUrl": "https://github.com/newrelic/csec-node-agent/tree/v1.1.1", "licenseFile": "node_modules/@newrelic/security-agent/LICENSE", - "licenseUrl": "https://github.com/newrelic/csec-node-agent/blob/v1.2.0/LICENSE", + "licenseUrl": "https://github.com/newrelic/csec-node-agent/blob/v1.1.1/LICENSE", "licenseTextSource": "file", "publisher": "newrelic" }, @@ -133,16 +120,16 @@ "publisher": "Max Ogden", "email": "max@maxogden.com" }, - "https-proxy-agent@7.0.4": { + "https-proxy-agent@7.0.2": { "name": "https-proxy-agent", - "version": "7.0.4", + "version": "7.0.2", "range": "^7.0.1", "licenses": "MIT", "repoUrl": "https://github.com/TooTallNate/proxy-agents", - "versionedRepoUrl": "https://github.com/TooTallNate/proxy-agents/tree/v7.0.4", - "licenseFile": "node_modules/https-proxy-agent/LICENSE", - "licenseUrl": "https://github.com/TooTallNate/proxy-agents/blob/v7.0.4/LICENSE", - "licenseTextSource": "file", + "versionedRepoUrl": "https://github.com/TooTallNate/proxy-agents/tree/v7.0.2", + "licenseFile": "node_modules/https-proxy-agent/README.md", + "licenseUrl": "https://github.com/TooTallNate/proxy-agents/blob/v7.0.2/README.md", + "licenseTextSource": "spdx", "publisher": "Nathan Rajlich", "email": "nathan@tootallnate.net", "url": "http://n8.io/" @@ -239,6 +226,32 @@ } }, "devDependencies": { + "@aws-sdk/client-s3@3.556.0": { + "name": "@aws-sdk/client-s3", + "version": "3.556.0", + "range": "^3.556.0", + "licenses": "Apache-2.0", + "repoUrl": "https://github.com/aws/aws-sdk-js-v3", + "versionedRepoUrl": "https://github.com/aws/aws-sdk-js-v3/tree/v3.556.0", + "licenseFile": "node_modules/@aws-sdk/client-s3/LICENSE", + "licenseUrl": "https://github.com/aws/aws-sdk-js-v3/blob/v3.556.0/LICENSE", + "licenseTextSource": "file", + "publisher": "AWS SDK for JavaScript Team", + "url": "https://aws.amazon.com/javascript/" + }, + "@aws-sdk/s3-request-presigner@3.556.0": { + "name": "@aws-sdk/s3-request-presigner", + "version": "3.556.0", + "range": "^3.556.0", + "licenses": "Apache-2.0", + "repoUrl": "https://github.com/aws/aws-sdk-js-v3", + "versionedRepoUrl": "https://github.com/aws/aws-sdk-js-v3/tree/v3.556.0", + "licenseFile": "node_modules/@aws-sdk/s3-request-presigner/LICENSE", + "licenseUrl": "https://github.com/aws/aws-sdk-js-v3/blob/v3.556.0/LICENSE", + "licenseTextSource": "file", + "publisher": "AWS SDK for JavaScript Team", + "url": "https://aws.amazon.com/javascript/" + }, "@koa/router@12.0.1": { "name": "@koa/router", "version": "12.0.1", @@ -313,6 +326,32 @@ "licenseTextSource": "file", "publisher": "Slack Technologies, LLC" }, + "@smithy/eventstream-codec@2.2.0": { + "name": "@smithy/eventstream-codec", + "version": "2.2.0", + "range": "^2.2.0", + "licenses": "Apache-2.0", + "repoUrl": "https://github.com/awslabs/smithy-typescript", + "versionedRepoUrl": "https://github.com/awslabs/smithy-typescript/tree/v2.2.0", + "licenseFile": "node_modules/@smithy/eventstream-codec/LICENSE", + "licenseUrl": "https://github.com/awslabs/smithy-typescript/blob/v2.2.0/LICENSE", + "licenseTextSource": "file", + "publisher": "AWS SDK for JavaScript Team", + "url": "https://aws.amazon.com/javascript/" + }, + "@smithy/util-utf8@2.3.0": { + "name": "@smithy/util-utf8", + "version": "2.3.0", + "range": "^2.3.0", + "licenses": "Apache-2.0", + "repoUrl": "https://github.com/awslabs/smithy-typescript", + "versionedRepoUrl": "https://github.com/awslabs/smithy-typescript/tree/v2.3.0", + "licenseFile": "node_modules/@smithy/util-utf8/LICENSE", + "licenseUrl": "https://github.com/awslabs/smithy-typescript/blob/v2.3.0/LICENSE", + "licenseTextSource": "file", + "publisher": "AWS SDK for JavaScript Team", + "url": "https://aws.amazon.com/javascript/" + }, "ajv@6.12.6": { "name": "ajv", "version": "6.12.6", @@ -337,6 +376,19 @@ "licenseTextSource": "file", "publisher": "Caolan McMahon" }, + "aws-sdk@2.1604.0": { + "name": "aws-sdk", + "version": "2.1604.0", + "range": "^2.1604.0", + "licenses": "Apache-2.0", + "repoUrl": "https://github.com/aws/aws-sdk-js", + "versionedRepoUrl": "https://github.com/aws/aws-sdk-js/tree/v2.1604.0", + "licenseFile": "node_modules/aws-sdk/LICENSE.txt", + "licenseUrl": "https://github.com/aws/aws-sdk-js/blob/v2.1604.0/LICENSE.txt", + "licenseTextSource": "file", + "publisher": "Amazon Web Services", + "url": "https://aws.amazon.com/" + }, "c8@8.0.1": { "name": "c8", "version": "8.0.1", @@ -428,15 +480,15 @@ "publisher": "Michael Radionov", "url": "https://github.com/mradionov" }, - "eslint-plugin-jsdoc@48.2.3": { + "eslint-plugin-jsdoc@48.0.6": { "name": "eslint-plugin-jsdoc", - "version": "48.2.3", + "version": "48.0.6", "range": "^48.0.5", "licenses": "BSD-3-Clause", "repoUrl": "https://github.com/gajus/eslint-plugin-jsdoc", - "versionedRepoUrl": "https://github.com/gajus/eslint-plugin-jsdoc/tree/v48.2.3", + "versionedRepoUrl": "https://github.com/gajus/eslint-plugin-jsdoc/tree/v48.0.6", "licenseFile": "node_modules/eslint-plugin-jsdoc/LICENSE", - "licenseUrl": "https://github.com/gajus/eslint-plugin-jsdoc/blob/v48.2.3/LICENSE", + "licenseUrl": "https://github.com/gajus/eslint-plugin-jsdoc/blob/v48.0.6/LICENSE", "licenseTextSource": "file", "publisher": "Gajus Kuizinas", "email": "gajus@gajus.com", @@ -453,15 +505,15 @@ "licenseUrl": "https://github.com/SonarSource/eslint-plugin-sonarjs/blob/v0.18.0/LICENSE", "licenseTextSource": "file" }, - "eslint@8.57.0": { + "eslint@8.56.0": { "name": "eslint", - "version": "8.57.0", + "version": "8.56.0", "range": "^8.24.0", "licenses": "MIT", "repoUrl": "https://github.com/eslint/eslint", - "versionedRepoUrl": "https://github.com/eslint/eslint/tree/v8.57.0", + "versionedRepoUrl": "https://github.com/eslint/eslint/tree/v8.56.0", "licenseFile": "node_modules/eslint/LICENSE", - "licenseUrl": "https://github.com/eslint/eslint/blob/v8.57.0/LICENSE", + "licenseUrl": "https://github.com/eslint/eslint/blob/v8.56.0/LICENSE", "licenseTextSource": "file", "publisher": "Nicholas C. Zakas", "email": "nicholas+npm@nczconsulting.com" @@ -592,15 +644,15 @@ "publisher": "Andrey Okonetchnikov", "email": "andrey@okonet.ru" }, - "lockfile-lint@4.13.2": { + "lockfile-lint@4.12.1": { "name": "lockfile-lint", - "version": "4.13.2", + "version": "4.12.1", "range": "^4.9.6", "licenses": "Apache-2.0", "repoUrl": "https://github.com/lirantal/lockfile-lint", - "versionedRepoUrl": "https://github.com/lirantal/lockfile-lint/tree/v4.13.2", + "versionedRepoUrl": "https://github.com/lirantal/lockfile-lint/tree/v4.12.1", "licenseFile": "node_modules/lockfile-lint/LICENSE", - "licenseUrl": "https://github.com/lirantal/lockfile-lint/blob/v4.13.2/LICENSE", + "licenseUrl": "https://github.com/lirantal/lockfile-lint/blob/v4.12.1/LICENSE", "licenseTextSource": "file", "publisher": "Liran Tal", "email": "liran.tal@gmail.com",